På denne siden

Kapittelet Shell-grunnleggende dekket $HOME, export og $PATH som verktøy du bruker sammen med andre kommandoer. Denne guiden går dypere: hvordan variabler oppfører seg, hvorfor noen overlever et skriptkall og andre ikke gjør det, hvilke filer bash leser ved oppstart, og hvordan du får oppsettet ditt til å sitte.

Alt her ble testet på bash 5.3 på Ubuntu 26.04, Fedora 44 og Arch Linux. Der oppforsel varierer mellom distribusjonene, vil du se det nevnt eksplisitt.

Hva miljøvariabler er

En miljøvariabel er et navn-verdi-par som skallet sender til hvert program det starter. Når du skriver ls, arver kjernen en tabell med variabler fra skallet: HOME, PATH, USER, LANG og flere. Noen settes av systemet ved pålogging; andre setter du selv. Skillet mellom hva som blir i skallet og hva som sendes ut er kjernekonseptet i denne guiden.

Lesing av variabler

Tre måter å inspisere hva som er satt.

env og printenv skriver begge ut hver eksportert variabel, altså de som arves av barneprosesser. Utdata er ett NAME=value-par per linje:

$ env
SHELL=/bin/bash
HOME=/home/ubuntu
USER=ubuntu
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:...

printenv kan også vise én enkelt variabel:

$ printenv HOME
/home/ubuntu

For å lese en variabel inne i skallet selv, bruk $-utvidelse med echo:

$ echo $USER
ubuntu

echo $PATH fungerer på samme måte og er den vanlige måten å inspisere søkestien på. $ er tegnet som forteller bash å sette inn verdien.

En praktisk forskjell: env og printenv viser bare eksporterte variabler. echo kan lese hvilken som helst variabel, selv en du akkurat satte uten å eksportere den.

Setting av variabler — og hva export faktisk gjør

En ren tilordning oppretter en shell-variabel. Den finnes i det gjeldende skallet, men er usynlig for ethvert program du starter:

$ MYVAR="hello"
$ echo $MYVAR
hello
$ env | grep MYVAR

Den siste linjen produserer ingenting. MYVAR finnes ikke i miljøet.

export forfremmer en variabel fra shell-omfang til miljøomfang. Du kan forfremme en eksisterende variabel:

$ export MYVAR
$ env | grep MYVAR
MYVAR=hello

Eller kombinere set og export i ett steg, som er den vanligste formen:

$ export EDITOR=nano
$ env | grep EDITOR
EDITOR=nano

Forskjellen betyr noe i skript. En variabel satt uten export er lokal for det gjeldende skallet. Hvis du kaller et skript eller en funksjon som starter underprosesser, vil ikke de underprosessene se den.

Shell-variabel vs. miljøvariabel — den korte versjonen: en shell-variabel lever bare i det gjeldende skallet. En miljøvariabel er en shell-variabel som har blitt eksportert, noe som betyr at hver barneprosess arver den. MYVAR=hello oppretter en shell-variabel. export MYVAR=hello oppretter en miljøvariabel.

Fjerning og nullstilling av variabler

unset fjerner en variabel helt, både den shell-lokale kopien og miljøkopien hvis den var eksportert:

$ export MYVAR="hello"
$ echo $MYVAR
hello
$ unset MYVAR
$ echo $MYVAR

$ env | grep MYVAR

Etter unset er variabelen borte. Det er ingen «tom» tilstand igjen: $MYVAR utvides til ingenting, og env lister den ikke lenger.

Forøvrig — fjerne en variabel for én kommando. Du trenger ikke alltid unset for å fjerne en variabel fra et programs miljø. env-kommandoen har et -u-flagg som fjerner en variabel for varigheten av én enkelt kommando — for eksempel kjører env -u HOME ls ls med HOME fjernet fra miljøet. Dette er et standard POSIX-flagg. Nyttig når et programs oppførsel avhenger av at HOME ikke er satt, selv om det er et sjeldent krav.

$PATH i dybden

$PATH er en kolonseparert liste med mapper. Når du skriver et kommandoenavn, søker bash i hver mappe i rekkefølge, fra venstre til høyre, til det finner en kjørbar fil med det navnet:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Å skrive ls får bash til å se først i /usr/local/sbin (ingenting der), deretter /usr/local/bin (fortsatt ingenting), deretter /usr/sbin eller /usr/bin avhengig av distribusjonen, der den til slutt finner ls.

Verktøyet type avslører hva bash resolver:

$ type ls
ls is /usr/bin/ls

På Fedora og Arch viser den samme kommandoen /usr/sbin/ls. Annen sti, samme binærfil. type identifiserer også innbygde kommandoer:

$ type cd
cd is a shell builtin

which er et eksternt verktøy som søker i $PATH og ikke noe annet:

$ which grep
/usr/bin/grep

Den forstår ikke innbygde kommandoer, aliaser eller funksjoner, så svaret kan avvike fra det bash faktisk kjører. GNU which kan rapportere en egen binærfil for et navn som egentlig er en innbygd kommando eller et alias, eller ikke finne noe i det hele tatt, avhengig av distribusjonen. type viser hvordan bash selv resolver et kommandonavn, og det gjør den til det mer pålitelige verktøyet.

Foranstillelse i PATH

Den vanligste PATH-manipuleringen er å legge til en mappe i front:

$ export PATH="$HOME/bin:$PATH"

Dette plasserer $HOME/bin først i søkerekkefølgen. Hvis du har et eget skript som heter ls i ~/bin, vil bash finne det før /usr/bin/ls. En personlig ls skygger for den ekte i hvert skall som leser PATH-en din — greit når det er bevisst, overraskende når det ikke er det.

Syntaksen betyr noe: $PATH på høyre side refererer til den gamle verdien, og hele uttrykket er sitatmerket for å håndtere stier med mellomrom på en trygg måte.

Shell-oppstartsfiler — hvilken fil kjører når

Når bash starter, leser det konfigurasjonsfiler i en bestemt rekkefølge. Filene varierer avhengig av om skallet er en login shell (første pålogging, eller ssh inn på et system) eller en interaktiv ikke-påloggingsshell (nytt terminalvindu i et skrivebordsmiljø):

  • Login shell: leser /etc/profile, deretter den første filen den finner av ~/.bash_profile, ~/.bash_login eller ~/.profile.
  • Interaktiv ikke-påloggingsshell: leser ~/.bashrc.

Du kan også velge modus manuelt:

$ bash -l    # login shell
$ bash -i    # interactive shell

Der distribusjonene skiller lag

Ubuntu leverer ikke en ~/.bash_profile som standard. Standard påloggingsfil er ~/.profile. Fedora og Arch leverer ~/.bash_profile som standard.

Alle tre skjelettfilene for pålogging gjør samme jobb: de leser inn ~/.bashrc. Ubuntus ~/.profile stiller source-linjen bak en betingelse og kjører den bare når bash kjører og fila finnes (if [ -n "$BASH_VERSION" ] pluss if [ -f "$HOME/.bashrc" ]). Fedoras ~/.bash_profile leser den inn når fila finnes (if [ -f ~/.bashrc ]; then . ~/.bashrc; fi). Archs består av én enkelt linje. Hele fila, kommentarer og alt:

#
# ~/.bash_profile
#

[[ -f ~/.bashrc ]] && . ~/.bashrc

Det er derfor endringer i ~/.bashrc også dukker opp i login-skall.

På systemssiden har Ubuntu og Arch /etc/bash.bashrc. Fedora bruker /etc/bashrc (merk: ingen .bash i navnet).

Alle tre distribusjonene bruker /etc/profile.d/, en mappe med .sh-filer som /etc/profile kjører ved pålogging. Systemomfattende PATH-tillegg eller umask-verdier bor ofte her.

Laste inn oppsettet på nytt

Etter å ha redigert en oppstartsfil trenger du ikke å logge ut og inn igjen. source-kommandoen leser fila inn i det gjeldende skallet på nytt:

$ source ~/.bashrc

Punktum-kommandoen gjør det samme og er POSIX-ekvivalenten:

$ . ~/.bashrc

Begge er identiske i bash. source er enklere å lese. Punktumformen virker i hvilken som helst POSIX-shell.

Få det til å sitte — praktiske oppskrifter

Å vite hvilken fil kjører når lar deg plassere konfigurasjonen der den tar effekt.

En personlig PATH-tillegging hører hjemme i ~/.bashrc for hvert nytt terminal- vindu, eller i ~/.profile (Ubuntu) / ~/.bash_profile (Fedora, Arch) hvis du bare trenger den ved pålogging. Bashrc-versjonen er som regel det folk vil ha:

# Add ~/bin to PATH
export PATH="$HOME/bin:$PATH"

Én advarsel: en variabel i ~/.bashrc når bare skall som leser fila. En cron-jobb gjør det aldri — cron kjører kommandoene sine med /bin/sh og et miljø helt sitt eget, så ingenting du eksporterer i ~/.bashrc er synlig for en planlagt jobb. Kapittelet Automatisering har mer om cron.

En egendefinert prompt bruker $PS1. Denne variabelen kontrollerer prompt- strengen i interaktive skall. Fedora og Arch har allerede satt den til et parentesformat:

$ export PS1='[\u@\h \W]\$ '

Backslash-sekvensene er spesielle: \u er brukernavnet ditt, \h er vertsmaskinen, \W er gjeldende mappes navn. Legg dette i ~/.bashrc for å gjøre det permanent.

Et standardredigeringsprogram er et annet nyttig export:

export EDITOR=nano

Mange terminalbaserte programmer leser $EDITOR for å avgjøre hvilket tekstredigeringsprogram de skal åpne — crontab -e, for eksempel, starter det variabelen peker på. Du kan også overstyre det for én enkelt kommando uten å endre variabelen permanent:

$ EDITOR=nano crontab -e

For å gjøre det permanent:

$ echo 'export EDITOR=nano' >> ~/.bashrc
$ source ~/.bashrc

Tilleggingen legger export-linjen i ~/.bashrc, så alle fremtidige skall som leser fila får den. source leser fila inn på nytt med en gang, så det gjeldende skallet får den også. Skall som allerede var åpne, og programmer som aldri leser ~/.bashrc, ser ingenting før de leser den.

$RANDOM er en bash-innbygd som returnerer et tilfeldig heltall mellom 0 og 32767. Det er ikke en miljøvariabel i vanlig forstand, siden det genererer en ny verdi hver gang det utvides:

$ echo $RANDOM
18462

$PWD holder gjeldende arbeidskatalog, og $OLDPWD holder den forrige. Disse vedlikeholdes av skallet automatisk:

$ pwd
/home/ubuntu/projects
$ cd /tmp
$ echo $OLDPWD
/home/ubuntu/projects

cd - bruker $OLDPWD for å hoppe tilbake. Bash vedlikeholder disse som en del av tilstanden for gjeldende katalog. Du setter dem ikke selv, men skript kan lese dem.

Distro-notater

Forskjellene er små men reelle. En hurtigreferanse:

Ubuntu 26.04 Fedora 44 Arch
Påloggingsfil ~/.profile ~/.bash_profile ~/.bash_profile
Bashrc-fil ~/.bashrc ~/.bashrc ~/.bashrc
System bashrc /etc/bash.bashrc /etc/bashrc /etc/bash.bashrc
System profile /etc/profile /etc/profile /etc/profile
Profile.d-mappe /etc/profile.d/ /etc/profile.d/ /etc/profile.d/

Hvis du administrerer dotfiles på tvers av maskiner, er den tryggeste tilnærmingen å plassere delte innstillinger i ~/.bashrc og kun påloggingsinnstillinger i en fil som ~/.profile eller ~/.bash_profile kjører. På den måten fungerer den samme ~/.bashrc overalt, og hver påloggingsfil håndterer sin egen distribusjons konvensjon.

Selve $SHELL-variabelen varierer: på Arch er den /usr/bin/bash, på Ubuntu og Fedora er den /bin/bash. De peker til den samme binærfilen (vanligvis en symlink), men skript som sammenligner $SHELL med en hardkodet sti bør ta hensyn til begge formene.

Hvor du står nå

Du vet hva miljøvariabler er, hvordan du setter og eksporterer dem, og hvilke filer bash leser ved oppstart. Hvis du vil sette dette ut i praksis:

  • Kapittelet Shell-grunnleggende dekker pipes, redireksjon, globber og aliaser — de hverdagslige byggesteinene som fungerer sammen med variablene.
  • Guiden Bash-skripting går dypere inn i anførselstegn, set -e/set -u, funksjoner og å skrive skript som oppfører seg når noe går galt.

Andre skall håndterer variabler annerledes. Zsh leser ~/.zshrc i stedet for ~/.bashrc og har sitt eget promp-system. Fish bruker ikke export i det hele tatt — hver variabel eksporteres som standard, og set håndterer begge omfang. Konseptene her er bash-spesifikke, selv om miljøvariabler som arvede nøkkel-verdi-par er et POSIX-vidt konsept.