Jak používat příkaz historie v systému Linux

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.