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
exportz 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ÉNOshell nahradí hodnotou ještě předtím, než příkaz spustí.echo $HOMEtedy shell nejdřív přepíše naecho /home/tya 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ířícdbez 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
$PATHv hodnotě — tím říkáš „vezmi, co tam bylo, a přidej". Kdybys napsal jenexport PATH="$HOME/bin", zahodíš všechny systémové cesty a přestanou fungovat ilsnebocat. 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řessu -) čte~/.bash_profile(a když neexistuje,~/.profile). Sem patří věci, které se mají nastavit jednou při přihlášení — hlavněexportproměnných jakoPATH,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 $0v login shellu vypíše-bash(pomlčka napřed), v běžném okně jenbash. 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.bashrcspustil 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
.bashrca nic se nestalo." Chybí reload..bashrcse čte jen při startu shellu — spusťsource ~/.bashrcnebo otevři nový terminál. Bez toho pořád běžíš na starém prostředí. - Přepsání
PATHmísto přidání.PATH=/opt/bin(bez:$PATH) zahodí všechny systémové cesty a najednou nefunguje anils. 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=hodnotabezexportvidí 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 = hodnotanení přiřazení — shell to čte jako příkazNAZEV. Píše seNAZEV=hodnotabez 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 (.envv.gitignore, správce hesel,~/.netrcs právy 600).
🛠️ Cvičení
- Prozkoumej svoje prostředí. Vypiš všechny proměnné prostředí a najdi mezi nimi
HOME,USER,SHELLaLANG. Pak vypiš jenPATHa spočítej, kolik složek obsahuje (nápověda: oddělovač je:). - Export vs neexport. Vytvoř proměnnou
TEST=ahojbez exportu a zkus ji přečíst v podprocesu (bash -c 'echo $TEST'). Pak ji exportuj a zkus znovu. Vysvětli rozdíl. - Přidej si složku do
PATH— bezpečně. Vytvoř~/bin, dej do ní jednoduchý spustitelný skript a přidej~/bindoPATHtak, aby ses ke skriptu dostal pouhým jménem. Proč musí být v hodnotě$PATH? - Alias a funkce, které přežijí restart. Přidej do
.bashrcaliasll='ls -la'a funkcimkcd. Ověř, že posource ~/.bashrcfungují. Co by se stalo, kdybyssourcevynechal? .bashrcvs.profile. Zjisti, který z těchto souborů máš v domově, a rozhodni, kam patříexport EDITOR=nanoa kam aliasgs='git status'. Zdůvodni.
Náčrt řešení — rozbal, až si cvičení zkusíš sám
- Prostředí —
env(neboprintenv) vypíše vše; konkrétní najdeš třebaprintenv HOME USER SHELL LANG. Jen cestu:echo $PATH. Počet složek napůl ručně, neboecho $PATH | tr ':' '\n' | wc -l. Pozor:PATHje jedna proměnná, uvnitř seznam oddělený dvojtečkami — ne víc proměnných. - Export vs neexport —
TEST=ahoj; bash -c 'echo $TEST'vypíše prázdno, protože podproces dostává jen exportované proměnné. Poexport TESTužbash -c 'echo $TEST'vypíšeahoj. 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. - Vlastní
PATH—mkdir -p ~/bin, do~/bin/pozdravdáš skript,chmod +x ~/bin/pozdrav, pakexport PATH="$HOME/bin:$PATH". Teď stačí napsatpozdrav. V hodnotě musí být$PATH, protože jinak bys všechny původní cesty zahodil a rozbil běžné příkazy —$PATHznamená 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. - Alias a funkce — do
.bashrcpřidášalias ll='ls -la'amkcd() { mkdir -p "$1" && cd "$1"; }, paksource ~/.bashrc. Bezsource(a bez nového terminálu) se změny neprojeví, protože.bashrcse čte jen při startu shellu — tvůj běžící shell o úpravě neví. Pozor:sourceběží v aktuálním shellu;bash ~/.bashrcby proběhl v podprocesu a nic by ti nezůstalo. .bashrcvs.profile—export EDITOR=nano(a obecněexportproměnných jakoPATH,LANG) patří do.profile/.bash_profile, protože se nastavuje jednou při přihlášení a dědí se dál. Aliasgs='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_profilenačte.bashrc(. ~/.bashrc), ať máš jedno místo. Pozor: aliasy v.profilese 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.
