V prostředí Linuxu si shell uchovává záznam o všech provedených příkazech, což umožňuje snadné vyhledávání a opakované spouštění dřívějších operací. Znalost příkazu `history` a jeho efektivní využití může výrazně zlepšit vaši produktivitu.
Práce s historií příkazů
Jak známý výrok praví, „Kdo si nepamatuje minulost, je odsouzen k jejímu opakování.“ V Linuxu platí, že pokud si nepamatujete dřívější příkazy, nemůžete je opakovat, i když byste chtěli.
Zde vstupuje do hry příkaz `history`. Umožňuje vám prohlížet a opakovat dříve použité příkazy. Nejde jen o šetření času či lenost – klíčová je efektivita a přesnost. Čím delší a složitější příkaz, tím obtížnější je zapamatovat si ho a zadat bez chyb. A chyby mohou mít dva charaktery: buď znemožní spuštění příkazu, nebo způsobí, že provede něco nečekaného.
Příkaz `history` eliminuje tyto problémy. Jak je u Linuxu zvykem, skrývá v sobě více, než se na první pohled zdá. Nicméně, jeho zvládnutí vám denně zlepší práci v příkazové řádce. Je to investice, která se vyplatí. Existují efektivnější způsoby využití `history`, než jen opakované stisky šipky nahoru.
Základní použití příkazu `history`
V nejzákladnější formě stačí pro zobrazení historie zadat příkaz:
history
Výsledkem bude seznam předchozích příkazů zobrazený v terminálu.
Příkazy jsou očíslovány, přičemž nejnovější příkazy (s nejvyššími čísly) jsou na konci seznamu.
Pro zobrazení určitého počtu příkazů můžete zadat číslo jako argument. Například pro zobrazení posledních 10 příkazů použijte:
history 10
Stejného výsledku dosáhnete použitím roury s příkazem `tail`:
history | tail -n 10
Opakování příkazů z historie
Pro opětovné spuštění příkazu z historie zadejte vykřičník (`!`) následovaný číslem příkazu (bez mezer).
Například pro opakování příkazu číslo 37 zadejte:
!37
Pro opakování posledního zadaného příkazu použijte dva vykřičníky za sebou:
!!
To se hodí, pokud zapomenete použít `sudo`. Stačí napsat `sudo !!` a stisknout Enter.
V následujícím příkladu jsme zapomněli na `sudo`. Místo přepisování celého příkazu můžeme ušetřit klávesy a použít `sudo !!`:
mv ./my_script.sh /usr/local/bin/
sudo !!
K opakování můžeme použít číslo příkazu ze seznamu nebo dvojitý vykřičník pro poslední příkaz. A co když chceme opakovat například pátý nebo osmý příkaz?
K opakování můžeme použít vykřičník, pomlčku (`-`) a číslo předchozího příkazu (opět bez mezer).
Například pro opakování 13. předchozího příkazu zadejte:
!-13
Vyhledávání příkazů podle textového řetězce
Pro opakování posledního příkazu, který začíná konkrétním textem, zadejte vykřičník a text (bez mezer) a stiskněte Enter.
Například pro opakování posledního příkazu, který začínal na `sudo`, zadejte:
!sudo
Je zde však riziko. Pokud poslední příkaz začínající na `sudo` není ten, který očekáváte, spustíte nesprávný příkaz.
Pro jistotu můžete použít modifikátor `:p` (print):
!sudo:p
Příkaz se vypíše do terminálu, ale nespustí se. Můžete si ho zkontrolovat, stisknout šipku nahoru a pak Enter pro spuštění.
Pro nalezení příkazu, který obsahuje konkrétní text, můžete použít vykřičník a otazník.
Například pro nalezení a spuštění prvního příkazu obsahujícího slovo „aliasy“ zadejte:
!?aliases
To najde libovolný příkaz s textem „aliasy“, bez ohledu na jeho umístění.
Interaktivní vyhledávání
Interaktivní vyhledávání umožňuje procházet seznam příkazů a vybrat ten, který chcete spustit.
Spusťte ho pomocí Ctrl+r.
Zadáváním textu se zobrazí první odpovídající příkaz. Zadaná písmena se objeví mezi zpětným apostrofem (`) a apostrofem (‚). Výsledky se aktualizují s každým napsaným písmenem.
Každým stiskem Ctrl+r hledáte další odpovídající příkaz směrem dozadu v historii.
Stiskem Enter se zobrazený příkaz spustí.
Pro úpravu příkazu před spuštěním použijte šipky vlevo nebo vpravo.
Příkaz se objeví v příkazové řádce a můžete ho upravit.
Pro prohledávání historie můžete použít i další nástroje. Například pro přenos výstupu z `history` do `grep` a hledání příkazů obsahujících „aliasy“ použijte:
history | grep aliases
Úprava posledního příkazu
Pokud potřebujete opravit překlep, můžete příkaz upravit pomocí stříšky (`^`). Je to praktický trik, který se hodí, pokud se spletete nebo chcete spustit příkaz znovu s jinou volbou.
Zadejte (bez mezer) stříšku, text k nahrazení, další stříšku, nový text, a další stříšku a stiskněte Enter.
Například, pokud jste zadali „shhd“ místo „sshd“:
sudo systemctl start shhd
Snadno to opravíte:
^shhd^sshd^
Příkaz se spustí s opraveným „shhd“ na „sshd“.
Odstraňování příkazů z historie
Příkazy lze odstraňovat z historie pomocí volby `-d` (delete). Není nutné uchovávat chybné příkazy v seznamu.
Pomocí `grep` naleznete číslo příkazu a pomocí `history -d` ho smažete. Poté ověřte, že byl odstraněn:
history | grep shhd
history -d 83
history | grep shhd
Volbě `-d` lze předat i rozsah příkazů. Pro odstranění položek od 22 do 32 (včetně) použijte:
history -d 22 32
Pro odstranění posledních pěti příkazů použijte záporné číslo:
history -d -5
Ruční aktualizace souboru historie
Při přihlášení nebo otevření terminálu se historie načte ze souboru. V Bashi je výchozí soubor `.bash_history`.
Změny v aktuální relaci se do souboru zapíší až při zavření terminálu nebo odhlášení.
Pokud chcete, aby nové příkazy byly dostupné v jiném terminálu, použijte v prvním terminálu volbu `-a` (all) před otevřením druhého terminálu.
Zadejte:
history -a
Příkazy se tiše zapíší do souboru historie.
Pokud chcete zapsat všechny změny (včetně smazaných příkazů) do souboru historie, použijte volbu `-w` (write):
history -w
Vymazání historie příkazů
Pro smazání všech příkazů z historie použijte volbu `-c` (clear):
history -c
Pro vynucení změn v souboru historie použijte i volbu `-w`:
history -w
Bezpečnost a soubor historie
Při používání aplikací, kde se zadávají citlivé údaje (např. hesla), se tyto údaje ukládají do historie. Pro zabránění ukládání citlivých informací je můžete okamžitě smazat pomocí následující struktury:
special-app my-secret-password;history -d $(history 1)
history 5
Struktura obsahuje dva příkazy oddělené středníkem (;). Rozklad:
- `special-app`: Název programu.
- `my-secret-password`: Heslo pro aplikaci. Konec prvního příkazu.
- `history -d`: Druhý příkaz vyvolává `history -d` (delete).
- `$(history 1)`: Substituce příkazu. Část v `$()` se provede v podshellu. Výsledek se vloží do původního příkazu. `history 1` vrátí předchozí příkaz. Tedy `history -d „poslední příkaz“`.
Pomocí `history 5` ověříte, že příkaz s heslem byl odstraněn.
Existuje i jednodušší způsob. Bash ignoruje řádky začínající mezerou. Vložte mezeru na začátek řádku:
special-app another-password
history 5
Příkaz s heslem se do historie neuloží. Důvod je v souboru `.bashrc`.
Soubor `.bashrc`
Soubor `.bashrc` se spustí při každém přihlášení nebo otevření terminálu. Obsahuje nastavení chování příkazu `history`. Upravte soubor pomocí `gedit`:
gedit .bashrc
V horní části najdete:
- `HISTSIZE`: Maximální počet položek v historii.
- `HISTFILESIZE`: Maximální počet řádků v souboru historie.
Tyto hodnoty se ovlivňují:
- Při přihlášení/otevření terminálu se historie načte z `.bash_history`.
- Při zavření terminálu se uloží maximálně `HISTSIZE` příkazů do `.bash_history`.
- Pokud je povolena `histappend`, příkazy se připojí k `.bash_history`. Jinak se `.bash_history` přepíše.
- Po uložení historie do `.bash_history` se soubor zkrátí na maximálně `HISTFILESIZE` řádků.
Dále je v souboru proměnná `HISTCONTROL`.
Můžete ji nastavit:
- `ignorespaces`: Řádky začínající mezerou se neukládají do historie.
- `ignoredups`: Duplicitní příkazy se neukládají.
- `ignoreboth`: Obě výše uvedené.
Můžete definovat příkazy, které se nemají ukládat do historie. Oddělte je dvojtečkou (:) a vložte do uvozovek („…“).
Pro přidání řádku s ignorovanými příkazy do `.bashrc` použijte strukturu:
export HISTIGNORE="ls:history"
Použití časových razítek
Pro přidání časových razítek použijte nastavení `HISTIMEFORMAT`. Stačí přidat řádek do `.bashrc`:
export HISTTIMEFORMAT="%c "
Všimněte si mezery před uvozovkami. To zabrání splynutí časového razítka s příkazy v seznamu historie.
Nyní při spuštění `history` uvidíte i datum a čas. U všech dřívějších příkazů se zobrazí čas přidání prvního časového razítka (zde příkaz 118).
Toto je rozsáhlé časové razítko. Můžete použít i jiné tokeny než `%c`:
- `%d`: Den
- `%m`: Měsíc
- `%y`: Rok
- `%H`: Hodina
- `%M`: Minuty
- `%S`: Sekundy
- `%F`: Celé datum (rok-měsíc-den)
- `%T`: Čas (hodina:minuty:sekundy)
- `%c`: Kompletní datum a čas (den-den-měsíc-rok a hodina:minuty:sekundy)
Vyzkoušejme jiné tokeny:
export HISTTIMEFORMAT="%d n%m %T "
Výstup zobrazuje den, měsíc a čas.
Pokud odstraníme den a měsíc, zobrazí se pouze čas.
Změny v `HISTIMEFORMAT` se aplikují na celou historii. Čas je uložen jako počet sekund od epochy Unixu. `HISTTIMEFORMAT` určuje pouze formát zobrazení tohoto čísla.
export HISTTIMEFORMAT="%T "
Výstup je nyní přehlednější.
Příkaz `history` lze využít i k auditu. Kontrola dřívějších příkazů může pomoci odhalit příčinu problému.
Stejně jako v životě, i v Linuxu můžete používat příkaz `history` prožít dobré časy a poučit se z těch špatných.