Okej, nu räcker det med datoranvändning. Du har möjlighet att begränsa processers körtid och definiera en maximal varaktighet för dem genom att använda kommandot timeout. Den här guiden kommer att visa dig hur du sätter tidsgränser för program med hjälp av detta kommando.
Vad kan timeout göra för dig?
Kommandot timeout ger dig möjligheten att bestämma den maximala tidsperioden ett program kan köras. Men varför är det nödvändigt?
I vissa fall vet du precis hur lång tid en process ska ta. Ett bra exempel är att styra loggnings- eller datainsamlingsprogram med timeout, så att loggfilerna inte okontrollerat fyller upp lagringsutrymmet på din hårddisk.
I andra fall vet du kanske inte exakt hur länge en process behöver köras, men du är säker på att den inte får fortsätta i evighet. Kanske har du en tendens att starta processer, minimera terminalfönstret och glömma bort dem.
Vissa program, även enkla verktyg, kan skapa nätverkstrafik som kan försämra nätverkets prestanda. De kan också binda resurser på den aktuella enheten och sakta ner den. (Vi tittar på dig, ping!) Att låta sådana program köras länge när du inte är vid datorn är inte optimalt.
timeout är en del av GNU Core Utilities, vilket betyder att operativsystem som Linux och macOS redan har timeout integrerat. Det kräver ingen installation; du kan använda det direkt.
Hur du kommer igång med timeout
Här är ett enkelt exempel. Standardbeteendet för kommandot ping är att det fortsätter att köras tills du avbryter det med Ctrl+C. Om du inte avbryter det, fortsätter det bara.
ping 192.168.4.28
Genom att använda timeout kan vi förhindra att ping körs oavbrutet, upptar nätverksbandbredd och överbelastar enheten som pingas.
Detta nästa kommando använder timeout för att begränsa pingens körtid. Vi tillåter ping att köras i 15 sekunder.
timeout 15 ping 192.168.4.28
Efter 15 sekunders timeout avslutas ping-sessionen, och vi återgår till kommandoraden.
Använda timeout med olika tidsenheter
Lägg märke till att vi inte behövde lägga till ett ”s” efter 15. timeout antar att värdet är i sekunder. Du kan lägga till ett ”s”, men det spelar ingen roll.
För att ange ett tidsvärde i minuter, timmar eller dagar använder du ”m”, ”h” eller ”d”.
För att köra ping i tre minuter, använd följande kommando:
timeout 3m ping 192.168.4.28
ping kommer att köras i tre minuter innan timeout avbryter ping-sessionen.
Begränsa datainsamling med timeout
Vissa datafångstfiler kan bli mycket stora på kort tid. För att förhindra att sådana filer blir svårhanterliga eller till och med problematiskt stora, begränsa tiden som fångstprogrammet tillåts att köra.
I det här exemplet använder vi tcpdump, ett verktyg för att samla in nätverkstrafik. På de testmaskiner som användes för den här artikeln var tcpdump redan installerat på Ubuntu Linux och Fedora Linux. Det måste installeras på Manjaro Linux och Arch Linux med följande kommando:
sudo pacman -Syu tcpdump
Vi kan köra tcpdump i 10 sekunder med dess standardalternativ och skicka utdata till en fil med namnet capture.txt med följande kommando:
timeout 10 sudo tcpdump > capture.txt
(tcpdump har egna alternativ för att spara infångad nätverkstrafik till en fil. Detta är en snabb fix eftersom vi fokuserar på timeout och inte tcpdump.)
tcpdump börjar samla in nätverkstrafik, och vi väntar i 10 sekunder. Men efter 10 sekunder fortsätter tcpdump att köras, och capture.txt fortsätter att växa. Det krävs en snabb Ctrl+C för att stoppa tcpdump.
Att kontrollera storleken på capture.txt med ls visar att den växte till 209K på några sekunder. Filen växte väldigt fort!
ls -lh capture.txt
Vad hände? Varför stoppade inte timeout tcpdump?
Allt handlar om signaler.
Skicka rätt signal
När timeout vill stoppa ett program skickar den en SIGTERM-signal. Det är en artig begäran om att programmet ska avslutas. Vissa program kan välja att ignorera SIGTERM-signalen. När det händer måste vi be timeout att vara lite mer bestämd.
Detta gör vi genom att be timeout att skicka SIGKILL-signalen istället.
SIGKILL-signalen kan inte ”fångas, blockeras eller ignoreras” – den kommer alltid igenom. SIGKILL är inte en artig begäran om att programmet ska avslutas. SIGKILL dyker upp oinbjuden med ett stoppur och en stor klubba.
Vi kan använda alternativet -s (signal) för att instruera timeout att skicka SIGKILL-signalen.
timeout -s SIGKILL 10 sudo tcpdump > capture.txt
Den här gången, så snart 10 sekunder har gått, stoppas tcpdump.
Fråga artigt först
Vi kan be timeout att först försöka stoppa programmet med SIGTERM och bara skicka SIGKILL om SIGTERM inte fungerar.
För att göra detta använder vi alternativet -k (döda efter). Alternativet -k behöver ett tidsvärde som parameter.
I det här kommandot ber vi timeout att låta dmesg köras i 30 sekunder och sedan avsluta den med SIGTERM-signalen. Om dmesg fortfarande körs efter 40 sekunder betyder det att den diplomatiska SIGTERM ignorerades, och timeout ska skicka en SIGKILL för att avsluta jobbet.
dmesg är ett verktyg för att övervaka meddelanden från kärnan och visa dem i ett terminalfönster.
timeout -k 40 30 dmesg -w
dmesg körs i 30 sekunder och stoppas sedan när den tar emot SIGTERM-signalen.
Vi vet att det inte var SIGKILL som stoppade dmesg eftersom SIGKILL alltid lämnar ett meddelande i terminalfönstret: ”Dödad.” Så skedde inte i det här fallet.
Hämta programmets utgångskod
Välskrivna program skickar ett värde tillbaka till skalet när de avslutas. Detta kallas en utgångskod. Vanligtvis används den för att informera skalet – eller processen som startade programmet – om problem uppstod när programmet kördes.
timeout genererar sin egen utgångskod, men vi kanske inte är intresserade av den. Vi är förmodligen mer intresserade av utgångskoden från processen som timeout kontrollerar.
Detta kommando låter ping köras i fem sekunder. Den pingar en dator som heter Nostromo, som finns på det testnätverk som användes för den här artikeln.
timeout 5 ping Nostromo.local
Kommandot körs i fem sekunder, och timeout avslutar det. Vi kan sedan kontrollera utgångskoden med detta kommando:
echo $?
Utgångskoden är 124. Detta är värdet som timeout använder för att visa att programmet avslutades med SIGTERM. Om SIGKILL avslutar programmet är utgångskoden 137.
Om vi avbryter programmet med Ctrl+C är utgångskoden från timeout noll.
timeout 5 ping Nostromo.local
echo $?
Om programkörningen avslutas innan timeout avslutar det, kan timeout skicka utgångskoden från programmet tillbaka till skalet.
För att det ska hända måste programmet avslutas av sig självt (med andra ord, det avslutas inte av timeout) och vi måste använda alternativet –preserve-status.
Om vi använder alternativet -c (count) med värdet fem, kommer ping bara att skicka fem förfrågningar. Om vi ger timeout en varaktighet på en minut, kommer ping definitivt att ha avslutat av sig själv. Vi kan sedan kontrollera utgångsvärdet med echo.
timeout --preserve-status 1m ping -c 5 Nostromo.local
echo $?
ping slutför sina fem ping-förfrågningar och avslutas. Utgångskoden är noll.
För att bekräfta att utgångskoden kommer från ping, låt oss tvinga ping att generera en annan utgångskod. Om vi försöker skicka ping-förfrågningar till en icke-existerande IP-adress, kommer ping att misslyckas med en utgångsfelkod. Vi kan sedan använda echo för att kontrollera att utgångskoden inte är noll.
timeout --preserve-status 1m ping -c 5 NotHere.local
echo $?
Ping-kommandot kan uppenbarligen inte nå den icke-existerande enheten, så det rapporterar felet och stängs. Utgångskoden är två. Det är den utgångskod som ping använder för generella fel.
Sätta upp regler
timeout handlar om att sätta begränsningar för program som körs. Om det finns en risk att loggfiler fyller din hårddisk eller att du glömmer att stänga av ett nätverksverktyg, använd timeout och låt din dator sköta sig själv.