Prostředí a konfigurace

env proměnné, PATH, .bashrc, dotfiles.

Každý běžící program potřebuje vědět pár věcí o svém okolí — kdo jsi, kde máš domovský adresář, jaký jazyk používáš, kde má hledat příkazy. Tyhle informace nese prostředí (environment): sada pojmenovaných hodnot, tzv. proměnných prostředí, které shell předává každému programu, co spustíš. Když je pochopíš, přestaneš „přepisovat kód" kvůli každé maličkosti — spoustu chování naladíš zvenku, jen změnou proměnné nebo řádku v konfiguračním souboru.


Pár pojmů na úvod

  • Proměnná prostředí (env variable) = pojmenovaná hodnota (JMÉNO=hodnota), kterou shell drží v paměti a předává programům, které spustí. Např. HOME=/home/ty, LANG=cs_CZ.UTF-8.
  • Konfigurace bez přepisování kódu = program čte nastavení z prostředí nebo souboru, takže stejný binárku naladíš pro různé stroje/uživatele bez zásahu do zdrojáku. Základ přenositelnosti.
  • Shell proměnná vs env proměnná = obyčejná proměnná žije jen v tvém shellu; teprve export z ní udělá env proměnnou, kterou zdědí i podprocesy (viz níže — tohle je nejčastější zádrhel).
  • Konfigurační soubor shellu (dotfile) = skrytý soubor (.bashrc, .profile…) ve tvém domově, který se spustí při startu shellu a nastaví ti prostředí, aliasy a funkce.
  • PATH = seznam složek, kde shell hledá spustitelné příkazy. Bez něj bys musel psát celou cestu ke každému programu. Nejdůležitější proměnná, kterou budeš potkávat pořád.

Co jsou proměnné prostředí a k čemu

Prostředí si představ jako tabulku KLÍČ=HODNOTA, kterou nese každý proces. Když spustíš program, dostane kopii téhle tabulky a může z ní číst. Díky tomu ví editor, kdo jsi (USER), instalátor, kam zapisovat dočasné soubory (TMPDIR), a aplikace, jakým jazykem s tebou mluvit (LANG).

Celou tabulku svého shellu vypíšeš takhle:

env          # vypíše všechny proměnné prostředí
printenv     # to samé (printenv PATH vypíše jen jednu)

Jednu konkrétní proměnnou přečteš přes $:

echo $HOME          # /home/ty
echo $USER          # ty
printenv PATH       # bezpečnější u proměnných, kde by $ mohl něco rozbít

💡 $JMÉNO shell nahradí hodnotou ještě předtím, než příkaz spustí. echo $HOME tedy shell nejdřív přepíše na echo /home/ty a teprve to spustí. Tomuhle se říká expanze proměnné.


Vytvoření proměnné a proč export

Proměnnou vyrobíš prostým přiřazením (žádné mezery kolem =!):

NAZEV=Siti          # správně
NAZEV = Siti        # ŠPATNĚ — shell to bere jako příkaz "NAZEV" s argumenty

Jenže takhle vytvořená proměnná žije jen ve tvém shellu. Podproces (skript, program) ji neuvidí. Aby ji zdědily i procesy, které spustíš, musíš ji exportovat:

export NAZEV=Siti           # vytvoří a rovnou exportuje
# nebo dvoufázově:
NAZEV=Siti
export NAZEV                # zveřejní už existující proměnnou

Rozdíl na příkladu — spustíme podproces (nový bash) a zkusíme proměnnou přečíst:

POKUS=ahoj
bash -c 'echo "podproces vidí: $POKUS"'   # podproces vidí: (prázdné!)

export POKUS
bash -c 'echo "podproces vidí: $POKUS"'   # podproces vidí: ahoj

💡 Proč to tak je: podproces dostává kopii prostředí rodiče — a v prostředí jsou jen exportované proměnné. Neexportovaná proměnná zůstává „soukromá" v rodičovském shellu. Proto skoro všechno, co má vidět nějaký program, exportuješ.

Proměnnou zrušíš přes unset NAZEV.


Důležité proměnné, které musíš znát

  • PATH — seznam složek oddělených dvojtečkou, kde shell hledá příkazy (viz vlastní sekce níže).
  • HOME — tvůj domovský adresář (/home/ty). Sem míří cd bez argumentu i zkratka ~.
  • USER — přihlašovací jméno (ty). Programy podle něj poznají, kdo je spustil.
  • SHELL — cesta k tvému výchozímu shellu (/bin/bash). Pozor: říká, jaký shell máš nastavený v systému, ne nutně ten, ve kterém právě píšeš.
  • LANG / LC_* — jazyk a formát (cs_CZ.UTF-8). Ovlivňuje jazyk hlášek, řazení, desetinnou čárku vs tečku, formát data.
  • EDITOR — který editor mají programy otevřít, když tě chtějí nechat něco napsat (git commit, crontab -e…). Např. export EDITOR=nano.
echo "$HOME $USER $SHELL $LANG"
printenv EDITOR

PATH — jak shell hledá příkazy

Když napíšeš ls, shell nezná předem, kde ls leží. Projde postupně složky v PATH (zleva doprava) a spustí první ls, který najde. Podívej se, jak PATH vypadá:

echo $PATH
# /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/home/ty/.local/bin

Jsou to složky oddělené dvojtečkou. Kterou konkrétně shell použil, zjistíš přes which nebo type:

which ls        # /usr/bin/ls
type ls         # ls is /usr/bin/ls

Pokud si chceš přidat vlastní složku s programy (třeba ~/bin), přidáš ji k existujícímu PATH, ne místo něj:

export PATH="$HOME/bin:$PATH"     # svoje bin dej dopředu — má přednost
export PATH="$PATH:$HOME/bin"     # nebo dozadu — použije se jen když nic dřív nesedí

🚩 Všimni si $PATH v hodnotě — tím říkáš „vezmi, co tam bylo, a přidej". Kdybys napsal jen export PATH="$HOME/bin", zahodíš všechny systémové cesty a přestanou fungovat i ls nebo cat. O tomhle průšvihu je celá jedna sekce ve Failure modes.

Aby ti přidání do PATH vydrželo i po zavření terminálu, patří ten export řádek do .bashrc (nebo .profile) — viz další sekce.


Konfigurační soubory shellu — .bashrc vs .profile

Když spustíš bash, přečte při startu jeden nebo víc souborů ve tvém domově a provede, co v nich je. Které přesně, závisí na typu shellu:

  • Login shell (přihlášení do textové konzole, ssh, přepnutí přes su -) čte ~/.bash_profile (a když neexistuje, ~/.profile). Sem patří věci, které se mají nastavit jednou při přihlášení — hlavně export proměnných jako PATH, EDITOR, LANG.
  • Interaktivní ne-login shell (nový záložka/okno terminálu v grafickém prostředí) čte ~/.bashrc. Sem patří věci pro každodenní psaní — aliasy, funkce, prompt, doplňování.

Aby ses nemusel starat, který zrovna běží, je běžný trik nechat .bash_profile načíst .bashrc:

# ~/.bash_profile
if [ -f ~/.bashrc ]; then
  . ~/.bashrc
fi

Tím máš jedno místo (.bashrc) pro skoro všechno a .bash_profile ho jen „přizve".

💡 Jak poznat, který mám? echo $0 v login shellu vypíše -bash (pomlčka napřed), v běžném okně jen bash. Nemusíš to řešit denně — stačí vědět, že to jsou dva různé případy.


⚠️ Po editaci .bashrc musíš reloadnout

Nejčastější zklamání začátečníka: upravím .bashrc, přidám alias — a nic. Důvod: .bashrc se čte jen při startu shellu. Tvůj už běžící terminál o změně neví. Máš dvě možnosti:

source ~/.bashrc     # načte soubor do aktuálního shellu (tečka: . ~/.bashrc dělá totéž)

nebo prostě zavři terminál a otevři nový — ten si .bashrc přečte čerstvě.

🚩 source (nebo .) spustí soubor v aktuálním shellu, takže se změny projeví tady a teď. Kdybys .bashrc spustil jako obyčejný skript (bash ~/.bashrc), proběhne v podprocesu a jakmile skončí, je všechno pryč — v tvém shellu se nezmění nic.


Aliasy a funkce — zkratky, které si nastavíš

Alias je přezdívka pro delší příkaz. Napíšeš krátké, shell to nahradí dlouhým:

alias ll='ls -la'                 # ll = detailní výpis včetně skrytých
alias ..='cd ..'
alias grep='grep --color=auto'    # obarví shody

Když potřebuješ víc než jen náhradu textu (argumenty, víc příkazů, logiku), použij funkci:

# vytvoř složku a rovnou do ní vejdi
mkcd() {
  mkdir -p "$1" && cd "$1"
}

Obojí patří do .bashrc, aby ti to vydrželo. Po přidání nezapomeň na source ~/.bashrc:

# ~/.bashrc
alias ll='ls -la'
alias gs='git status'

mkcd() { mkdir -p "$1" && cd "$1"; }

💡 Aktuálně platné aliasy vypíšeš příkazem alias (bez argumentů). Jeden zrušíš unalias ll.


Dotfiles a jejich verzování (krátce)

.bashrc, .profile, .gitconfig, .vimrc a spol. se souhrnně říká dotfiles — jsou skryté (začínají tečkou) a nesou tvoje osobní nastavení. Protože je to obyčejný text, dá se verzovat gitem: založíš si repozitář (třeba ~/dotfiles), soubory tam dáš a symlinkuješ zpět do domova. Výhoda: na novém stroji máš za minutu úplně stejné prostředí a historii změn máš v gitu.

🚩 Pozor: do veřejného repozitáře dotfiles nikdy nedávej tajemství — tokeny, hesla, SSH klíče. Ta patří jinam (viz Failure modes). Verzuj konfiguraci, ne přihlašovací údaje.


Failure modes — časté omyly začátečníků

  • „Upravil jsem .bashrc a nic se nestalo." Chybí reload. .bashrc se čte jen při startu shellu — spusť source ~/.bashrc nebo otevři nový terminál. Bez toho pořád běžíš na starém prostředí.
  • Přepsání PATH místo přidání. PATH=/opt/bin (bez :$PATH) zahodí všechny systémové cesty a najednou nefunguje ani ls. Vždycky přidávej: PATH="/opt/bin:$PATH". Když se to stane, zavři a otevři nový terminál (nový shell si načte čistý PATH) a řádek oprav.
  • Zapomenutý export. NAZEV=hodnota bez export vidí jen tvůj shell; spuštěný skript/program proměnnou nedostane a chová se, jako by nebyla. Co má vidět podproces, musí být exportované.
  • Mezery kolem =. NAZEV = hodnota není přiřazení — shell to čte jako příkaz NAZEV. Píše se NAZEV=hodnota bez mezer.
  • Tajemství v env nebo v gitnutých dotfiles. Heslo v export DB_PASSWORD=... v .bashrc, který je ve veřejném repu, je únik. Env proměnné navíc vidí i podprocesy a bývají v logách. Citlivé věci drž mimo git (.env v .gitignore, správce hesel, ~/.netrc s právy 600).

🛠️ Cvičení

  1. Prozkoumej svoje prostředí. Vypiš všechny proměnné prostředí a najdi mezi nimi HOME, USER, SHELL a LANG. Pak vypiš jen PATH a spočítej, kolik složek obsahuje (nápověda: oddělovač je :).
  2. Export vs neexport. Vytvoř proměnnou TEST=ahoj bez exportu a zkus ji přečíst v podprocesu (bash -c 'echo $TEST'). Pak ji exportuj a zkus znovu. Vysvětli rozdíl.
  3. Přidej si složku do PATH — bezpečně. Vytvoř ~/bin, dej do ní jednoduchý spustitelný skript a přidej ~/bin do PATH tak, aby ses ke skriptu dostal pouhým jménem. Proč musí být v hodnotě $PATH?
  4. Alias a funkce, které přežijí restart. Přidej do .bashrc alias ll='ls -la' a funkci mkcd. Ověř, že po source ~/.bashrc fungují. Co by se stalo, kdybys source vynechal?
  5. .bashrc vs .profile. Zjisti, který z těchto souborů máš v domově, a rozhodni, kam patří export EDITOR=nano a kam alias gs='git status'. Zdůvodni.
Náčrt řešení — rozbal, až si cvičení zkusíš sám
  1. Prostředíenv (nebo printenv) vypíše vše; konkrétní najdeš třeba printenv HOME USER SHELL LANG. Jen cestu: echo $PATH. Počet složek napůl ručně, nebo echo $PATH | tr ':' '\n' | wc -l. Pozor: PATH je jedna proměnná, uvnitř seznam oddělený dvojtečkami — ne víc proměnných.
  2. Export vs neexportTEST=ahoj; bash -c 'echo $TEST' vypíše prázdno, protože podproces dostává jen exportované proměnné. Po export TESTbash -c 'echo $TEST' vypíše ahoj. Rozdíl: neexportovaná proměnná zůstává soukromá v rodičovském shellu; export ji vloží do prostředí, které se dědí do podprocesů. Pozor: export platí i pro všechny další spuštěné programy, ne jen ten jeden.
  3. Vlastní PATHmkdir -p ~/bin, do ~/bin/pozdrav dáš skript, chmod +x ~/bin/pozdrav, pak export PATH="$HOME/bin:$PATH". Teď stačí napsat pozdrav. V hodnotě musí být $PATH, protože jinak bys všechny původní cesty zahodil a rozbil běžné příkazy — $PATH znamená připoj to k tomu, co tam bylo. Aby to vydrželo, dej ten řádek do .bashrc. Pozor: pořadí rozhoduje — složka vlevo má přednost.
  4. Alias a funkce — do .bashrc přidáš alias ll='ls -la' a mkcd() { mkdir -p "$1" && cd "$1"; }, pak source ~/.bashrc. Bez source (a bez nového terminálu) se změny neprojeví, protože .bashrc se čte jen při startu shellu — tvůj běžící shell o úpravě neví. Pozor: source běží v aktuálním shellu; bash ~/.bashrc by proběhl v podprocesu a nic by ti nezůstalo.
  5. .bashrc vs .profileexport EDITOR=nano (a obecně export proměnných jako PATH, LANG) patří do .profile/.bash_profile, protože se nastavuje jednou při přihlášení a dědí se dál. Alias gs='git status' patří do .bashrc, protože aliasy platí jen v interaktivním shellu a chceš je v každém novém okně. Běžný trik: .bash_profile načte .bashrc (. ~/.bashrc), ať máš jedno místo. Pozor: aliasy v .profile se ti v grafickém terminálu nemusí projevit — proto patří do .bashrc.

🧠 Otázky & odpovědi

K čemu jsou proměnné prostředí a proč jsou lepší než měnit kód?

Proměnná prostředí je pojmenovaná hodnota (třeba HOME nebo LANG), kterou shell drží v paměti a předává každému programu, co spustíš. Program si z ní přečte, jak se má chovat — kdo jsi, jaký jazyk používáš, kde má hledat příkazy. Výhoda oproti přepisování zdrojáku je obrovská: stejnou binárku nebo skript naladíš pro jiný stroj, jiného uživatele nebo jiné prostředí (test vs produkce) jen změnou proměnné, bez zásahu do kódu a bez nového buildu. Proto se přes prostředí předávají třeba přístupové údaje, cesty a přepínače chování.

Proč musím proměnnou exportovat a co se stane, když to neudělám?

Obyčejné přiřazení (NAZEV=hodnota) vytvoří proměnnou, která žije jen v tvém aktuálním shellu. Podproces — spuštěný skript nebo program — dostává jen kopii prostředí, a v tom prostředí jsou pouze exportované proměnné. Bez exportu ji tedy podproces neuvidí a chová se, jako by neexistovala. Jakmile napíšeš export NAZEV, proměnná se vloží do prostředí a zdědí ji každý proces, který od té chvíle spustíš. Proto skoro všechno, co má vidět nějaký program (PATH, EDITOR, přístupové tokeny), exportuješ.

Jak funguje PATH a proč ho nesmím přepsat?

PATH je seznam složek oddělených dvojtečkou, ve kterých shell hledá spustitelné příkazy. Když napíšeš ls, shell projde ty složky zleva doprava a spustí první ls, na který narazí — proto nemusíš psát celou cestu. Když si přidáváš vlastní složku, musíš připojit k tomu, co tam už je: PATH=$HOME/bin:$PATH. Kdybys napsal jen PATH=$HOME/bin, zahodíš všechny systémové cesty a přestanou fungovat i základní příkazy jako ls nebo cat, protože je shell najednou nemá kde najít. Když se ti to povede, stačí zavřít a otevřít nový terminál — ten si načte čistý PATH — a řádek opravit.

Jaký je rozdíl mezi .bashrc a .bash_profile a kdy se čtou?

Záleží na typu shellu. Login shell (přihlášení do konzole, ssh, su -) čte .bash_profile, a když neexistuje, .profile — sem patří věci nastavené jednou při přihlášení, hlavně export proměnných jako PATH nebo EDITOR. Interaktivní ne-login shell (nové okno terminálu v grafice) čte .bashrc — sem patří aliasy, funkce a nastavení promptu, tedy věci pro každodenní psaní. Aby ses tím nemusel trápit, bývá zvykem nechat .bash_profile načíst .bashrc, takže máš jedno místo pro skoro všechno. Když si nejsi jistý, který běží, echo $0 v login shellu ukáže -bash s pomlčkou napřed.

Upravil jsem .bashrc a nic se nezměnilo — co dělám špatně?

Nic zásadního, jen ti chybí reload. Soubor .bashrc se čte pouze při startu shellu, takže tvůj už běžící terminál o úpravě neví. Máš dvě cesty: buď spustit source ~/.bashrc (tečka . ~/.bashrc dělá totéž), což soubor načte přímo do aktuálního shellu a změny se projeví hned, nebo prostě zavřít terminál a otevřít nový, který si .bashrc přečte čerstvě. Pozor na to, že spuštění jako obyčejný skript (bash ~/.bashrc) nepomůže — proběhne v podprocesu a jakmile skončí, je všechno pryč, protože se to nezapsalo do tvého shellu.