Använda history i bash
Introduktion till kommandot history
I förra bloggposten tittade vi på hur man enkelt repeterar ett tidigare kommando med dubbla utropstecken (!!). Vad bash gör när det upptäcker de dubbla utropstecknen är att det kollar i historiken över tidigare använda kommandon och skriver sedan ut (expanderar) våra utropstecknen till det senaste av dem. Om det inte är det senaste vi vill använda då? Kommandot history i bash ger oss goda möjligheter att överblicka och använda historik, något jag tänkte gå in på närmare här.
Den enklaste introduktionen till history är något de allra flesta som jobbat i terminalen förmodligen känner till: tangentbordsknapparna pil upp och pil ner bläddrar upp/ner bland tidigare skrivna kommandon och skriver ut dem i prompten. Det är ett snabbt och smidigt sätt att komma tillbaks till något man precis skrivit men som kanske innehöll ett stavfel och därför inte gjorde det vi ville. Vill vi däremot gå långt tillbaks blir det snabbt tröttsamt att bläddra rad för rad. För att se en komplett lista över vad som tidigare skrivits in använder vi kommandot history:
[anders@anders-laptop ~]$ history 1 cd / 2 ls 3 sudo apt-get update && sudo apt-get upgrade 4 clear 5 history ...
Som synes ovan får vi en komplett lista över alla tidigare kommandon. I exemplet här har det bara skrivits fem kommandon totalt sedan vårt operativsystem installerades (eller history-filen rensades, mer om den strax), något som förstås är osannolikt i verkligheten men bra för att visa upp. Förmodligen är listan så lång att den täcker mer än hela skärmen. Skriv
history | less
för att skicka listan till kommandot less som gör det enkelt att bläddra upp och ner bland kommandohistoriken med antingen piltangenterna eller med page up/page down. Ett annat och förmodligen bättre alternativ är att skriva
history > historik.txt
för att istället för att fylla upp skärmen skicka listan till en ny fil som vi i vårt fall pedagogiskt döper till historik.txt. Filen sparas i den nuvarande katalogen och kan sedan ögnas igenom i lugn och ro med valfri textredigerare. Slutligen kan vi också begränsa mängden data genom att säga till history-kommandot hur många av de senaste posterna vi vill visa:
history 10
returnerar alltså de 10 sista kommandona i vår historik. Notera att varje rad innehåller ett nummer framför namnet på kommandot som utförts. Detta indikerar förstås i vilken ordning kommandona skrivits in i historiken. Vi kan nu enkelt repetera valfritt kommando från history-listan genom att skriva ett enkelt utropstecken följt av det nummer i historiken vi vill repetera! I exemplet nedan repeterar vi det tredje kommandot i listan
[anders@anders-laptop ~]$ !3
Två enkla tecken ersätter alltså de 51 tecken vi annars behövt för att uppdatera vårt operativsystem! Normalt sätt är det dock bättre att använda bashkommandot alias om man önskar ge kortare namn åt ofta repeterade långa kommandon.
En djupare inblick i history
Hur fungerar då history-kommandot? Jo, varje gång du trycker på Enter i terminalen sparas informationen du skrivit i prompten till minnet. När du senare stänger ner din terminal sparas historiken från minnet till din history-fil. Den läses sedan in nästa gång du startar en terminal så att du alltid har tillgång till tidigare historik. Vad heter då history-filen och var hittar vi den? Det är lite olika beroende på vilken distribution, men normalt sett ligger den i din hemkatalog och heter enkelt nog .bash_history. Du kan själv ta reda på var din historik finns sparad genom att skriva ut variabeln HISTFILE
[anders@anders-laptop ~]$ echo $HISTFILE /home/anders/.bash_history
Då den senaste historiken oftast ligger direkt i minne och endast skrivs till fil vid avslut är det dock sällsynt att man läser history-filen direkt. Det är det vi har kommandot history till! Viktigare är då variabeln HISTSIZE som anger hur många kommandon som ska sparas i din historik. Normalt brukar den ha ett värde mellan 500-1000. Det finns dock ingen anledning att snåla på det, så vi höjer värdet en aning med en extra nolla:
[anders@anders-laptop ~]$ export HISTSIZE=10000
För att säkerställa att detta värde laddas även vid omstart sparar vi ovanstående i vår .bashrc-fil i hemkatalogen. Denna fil laddas alltid in när du loggar in och är ett bra ställe att placera variabler du alltid vill ha tillgång till. Öppna den med din föredragna texteditor och skriv in samma som ovan där, alternativt:
[anders@anders-laptop ~]$ echo "export HISTSIZE=10000" >> .bashrc
Viktigt i ovanstående är att säkerställa dubbla ”>”-tecken (har de ett svenskt namn?)! Används bara ett kommer nämligen den befintliga .bashrc-filen skrivas över!
Att söka i historiken
Minns ni hur vi skickade data från history till programmet less för att enklare kunna bläddra i den? Det enklaste sättet att söka i din history är genom att istället skicka all data till programmet grep. Grep är ett otroligt mångfacetterat program, men kortfattat så söker det i sitt igenom en text och returnerar alla rader som innehåller den text vi söker efter. Testar vi t.ex. att söka efter alla kommandon innehållandes kommandot yum (Fedoras pakethanterare) ser vi följande:
[anders@anders-laptop ~]$ history | grep "yum" 458 sudo yum install php-xml 460 sudo yum update 482 yum install fping 483 sudo yum install fping 539 sudo yum install preload 587 sudo yum update ...
Användbart om du t.ex. undrar vad det egentligen var du installerade den där gången du kom hem från krogen! Citationstecknen är inte nödvändiga så länge vi bara söker ett enkelt ord men behövs så fort vi letar efter ett kommando med fler ord eller parametrar, så som yum install. Det är därför god praxis att alltid citera texten du söker.
Ett annat alternativ för att söka igenom historiken efter ett specifikt kommando är att i terminalen trycka Ctrl+r. Du får då upp en prompt med texten (reverse-i-search)`’ och kan sedan skriva in texten du söker. Tryck Ctrl+r upprepade gånger för att gå längre bak i historiken. När du hittat kommandot du letade efter trycker du vänster- eller högerpil för att flytta ut texten till prompten.
Avancerad användning av history
Två andra användbara variabler som läses av av history-kommandot är HISTIGNORE och HISTCONTROL. Det första är tämligen självförklarande; det anger nämligen precis vilka kommandon (om några) vi inte vill lagra i vår historik. Variabeln kan ta flera värden som separeras med ett kolon ( : ) och fungerar enligt följande syntax:
HISTIGNORE="history:pwd"
Ovanstående skulle göra att kommandona history och pwd upphörde registreras i vår historik. Värt att notera är att ovanstående endast ignorerar exakta träffar! Kommandot history 10 hade alltså även fortsättningsvis registrerats då det inte matchar enbart ”history”. Vill vi att kommandot ska ignoreras totalt oavsett följande värden/parametrar lägger vi bara till ett * vid slutet:
HISTIGNORE="history*:pwd"
Kommandon som history kan möjligen platsa i HISTIGNORE, men min rekommendation är att vara försiktig med vad du lägger till. Det motverkar förstås syftet med history-funktionen att ignorera vad som sker! En kraftfullare och mer användbar variabel är då HISTCONTROL. HISTCONTROL anger både vad som ska sparas och hur det sparas. Variabeln kan ges totalt fyra olika värden av vilket ett är en sammanslagning av två andra. Värdena är som följer:
- ignorespace – ignorera alla kommandon som börjar med ett mellanslag. Registrerar alltså ”cd ..” men inte ” cd ..”. Användbart om man då och då önskar undanta ett kommando från history.
- ignoredups – ignorera dubbletter i följd. Skriver du alltså exempelvis ”ls” flera gånger i följd kommer endast den sista att registreras.
- ignoreboth – Sammanslagning av de två ovanstående parametrarna, aktiverar både ignorespace och ignoredups.
- erasedups – ignorera samtliga dubbletter i din historik! Skriver du exempelvis ”ls” kommer samtliga förekomster av kommandot ”ls” att tas bort från din historik och ersättas med enbart det sista. Användning av denna parameter känns svår att motivera annat än i specialfall.
Slutligen
Har du orkat ända hit bör du nu ha en god överblick över history-kommandot och hur det används i praktiken. För att avsluta bjuder jag här på en gammal goding i bash-sammanhang, nämligen en salig blandning kommandon sammansatta med pipes i en enda lång one-liner. Resultatet; en tio-i-topp-lista över de mest använda kommandona i historiken, sorterade efter antal!
[anders@anders-laptop ~]$ history | awk '{print$2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -n | tail | sort -nr
Resultatet för mig blir:
157 git
143 ls
129 sudo
101 cd
42 echo
34 man
33 su
28 mysql
24 chmod
23 rm
Vad blir det för dig? Klipp gärna in i kommentarerna!
