Det er på tide å snakke om datamaskiner. Det finnes en måte å sette tidsbegrensninger på prosesser, ved å bruke «timeout»-kommandoen. Denne guiden viser hvordan du begrenser kjøretiden for programmer ved hjelp av denne kommandoen.
Hva er poenget med «timeout»?
Med «timeout»-kommandoen kan du bestemme hvor lenge et program skal kjøre. Men hvorfor skulle du trenge å gjøre det?
I noen tilfeller vet du nøyaktig hvor lenge en prosess skal pågå. For eksempel kan du ønske å begrense tiden et logg- eller datafangstprogram kjører, slik at loggfilene ikke fyller opp harddisken din.
Andre ganger vet du ikke nøyaktig hvor lenge en prosess bør kjøre, men du vet at du ikke vil at den skal kjøre for alltid. Kanskje du pleier å starte prosesser, minimere terminalvinduet og så glemme dem.
Visse programmer, selv enkle verktøy, kan generere nettverkstrafikk som kan påvirke ytelsen til nettverket ditt. De kan også oppta ressurser på enheten og redusere ytelsen. (Jeg ser på deg, «ping».) Å la slike programmer kjøre over lengre perioder mens du ikke er ved datamaskinen, er ikke en god ide.
«timeout» er en del av GNU Core Utils, og er dermed innebygd i Linux og Unix-lignende operativsystemer som macOS. Du trenger ikke å installere noe. Du kan bruke den med en gang.
Slik bruker du «timeout»
La oss se på et enkelt eksempel. Som standard vil «ping»-kommandoen fortsette å kjøre helt til du stopper den med Ctrl+C. Hvis du ikke avbryter den, vil den fortsette å kjøre.
ping 192.168.4.28
Med «timeout» kan vi sørge for at «ping» ikke kjører i det uendelige, og sluker nettverksbåndbredde og belaster enheten den pinger.
Denne kommandoen bruker «timeout» til å begrense kjøretiden til «ping». Vi gir «ping» 15 sekunder med kjøretid.
timeout 15 ping 192.168.4.28
Etter 15 sekunder avslutter «ping»-sesjonen, og vi returneres til ledeteksten.
Bruk av andre tidsenheter med «timeout»
Du la kanskje merke til at vi ikke la til en «s» etter 15. «timeout» antar at verdien er i sekunder. Du kan legge til en «s», men det spiller ingen rolle.
For å bruke en tidsverdi målt i minutter, timer eller dager, legger du til en «m», en «h» eller en «d».
For å kjøre «ping» i tre minutter, bruker du denne kommandoen:
timeout 3m ping 192.168.4.28
«ping» vil kjøre i tre minutter før «timeout» aktiveres og stopper «ping»-sesjonen.
Begrense datafangst med «timeout»
Enkelte datafangstfiler kan vokse svært fort. For å unngå at slike filer blir vanskelige å håndtere, må vi begrense hvor lenge fangstprogrammet får kjøre.
I dette eksemplet bruker vi «tcpdump», et verktøy for å fange opp nettverkstrafikk. På testmaskinene som denne artikkelen er basert på, var «tcpdump» allerede installert i Ubuntu Linux og Fedora Linux. På Manjaro Linux og Arch Linux måtte den installeres med følgende kommando:
sudo pacman -Syu tcpdump
Vi kan kjøre «tcpdump» i 10 sekunder med standardalternativene, og omdirigere utdataene til en fil kalt capture.txt med følgende kommando:
timeout 10 sudo tcpdump > capture.txt
(«tcpdump» har sine egne alternativer for å lagre fanget nettverkstrafikk til en fil. Dette er en rask løsning fordi vi diskuterer «timeout», ikke «tcpdump».)
«tcpdump» begynner å fange opp nettverkstrafikk, og vi venter i 10 sekunder. Men 10 sekunder går, og «tcpdump» fortsetter å kjøre, og capture.txt fortsetter å vokse. Vi må trykke Ctrl+C for å stoppe «tcpdump».
En sjekk av størrelsen på capture.txt med «ls» viser at den vokste til 209K på bare noen sekunder. Den filen vokste fort!
ls -lh capture.txt
Hva skjedde? Hvorfor stoppet ikke «timeout» «tcpdump»?
Alt handler om signaler.
Sende riktig signal
Når «timeout» ønsker å stoppe et program, sender den SIGTERM-signalet. Dette ber programmet om å avslutte på en høflig måte. Noen programmer kan velge å ignorere SIGTERM-signalet. I slike tilfeller må vi be «timeout» om å være litt mer kraftfull.
Det kan vi gjøre ved å be «timeout» om å sende SIGKILL-signalet i stedet.
SIGKILL-signalet kan ikke «fanges, blokkeres eller ignoreres» – det går alltid gjennom. SIGKILL ber ikke programmet om å stoppe på en høflig måte. SIGKILL står klar med en stoppeklokke og en klubbe.
Vi kan bruke alternativet «-s» (signal) for å be «timeout» om å sende SIGKILL-signalet.
timeout -s SIGKILL 10 sudo tcpdump > capture.txt
Denne gangen, så snart 10 sekunder har gått, stoppes «tcpdump».
Prøve å være høflig først
Vi kan be «timeout» om å forsøke å stoppe programmet ved hjelp av SIGTERM, og kun sende SIGKILL dersom SIGTERM ikke fungerte.
For å gjøre dette bruker vi alternativet «-k» (kill after). Alternativet «-k» krever en tidsverdi som parameter.
I denne kommandoen ber vi «timeout» om å la «dmesg» kjøre i 30 sekunder, og deretter avslutte det med SIGTERM-signalet. Hvis «dmesg» fortsatt kjører etter 40 sekunder, betyr det at det diplomatiske SIGTERM ble ignorert, og «timeout» skal sende inn SIGKILL for å fullføre jobben.
«dmesg» er et verktøy som kan overvåke kjernens ringbuffermeldinger og vise dem i et terminalvindu.
timeout -k 40 30 dmesg -w
«dmesg» kjører i 30 sekunder og stopper når den mottar SIGTERM-signalet.
Vi vet at det ikke var SIGKILL som stoppet «dmesg» fordi SIGKILL alltid legger igjen en kort melding i terminalvinduet: «Killed.» Det skjedde ikke i dette tilfellet.
Hente programmets returkode
Veloppdragne programmer sender en verdi tilbake til skallet når de avsluttes. Dette kalles en returkode. Vanligvis brukes dette for å fortelle skallet – eller hvilken som helst prosess som startet programmet – om det oppsto problemer med programmet mens det kjørte.
«timeout» gir sin egen returkode, men vi er kanskje ikke så opptatt av den. Vi er mer interessert i returkoden fra prosessen som «timeout» styrer.
Denne kommandoen lar «ping» kjøre i fem sekunder. Den pinger en datamaskin som heter Nostromo, som er på testnettverket som ble brukt under arbeidet med denne artikkelen.
timeout 5 ping Nostromo.local
Kommandoen kjører i fem sekunder, og «timeout» avslutter den. Vi kan deretter sjekke returkoden ved hjelp av denne kommandoen:
echo $?
Returkoden er 124. Dette er verdien som «timeout» bruker for å indikere at programmet ble avsluttet med SIGTERM. Hvis SIGKILL avslutter programmet, er returkoden 137.
Hvis vi avbryter programmet med Ctrl+C, er returkoden fra «timeout» null.
timeout 5 ping Nostromo.local
echo $?
Hvis programmet avsluttes før «timeout» stopper det, kan «timeout» sende returkoden fra programmet tilbake til skallet.
For at dette skal skje, må programmet stoppe av seg selv (med andre ord, det blir ikke avsluttet av «timeout»), og vi må bruke alternativet «–preserve-status».
Hvis vi bruker alternativet «-c» (count) med en verdi på fem, vil «ping» bare sende fem forespørsler. Hvis vi gir «timeout» en varighet på ett minutt, vil «ping» definitivt ha avsluttet av seg selv. Vi kan deretter sjekke returverdien ved å bruke «echo».
timeout --preserve-status 1m ping -c 5 Nostromo.local
echo $?
«ping» fullfører sine fem «ping»-forespørsler og avsluttes. Returkoden er null.
For å bekrefte at returkoden kommer fra «ping», lar vi «ping» generere en annen returkode. Hvis vi prøver å sende «ping»-forespørsler til en ikke-eksisterende IP-adresse, vil «ping» mislykkes med en feilreturkode. Vi kan deretter bruke «echo» for å sjekke at returkoden ikke er null.
timeout --preserve-status 1m ping -c 5 NotHere.local
echo $?
«ping»-kommandoen kan åpenbart ikke nå den ikke-eksisterende enheten, så den rapporterer feilen og lukkes. Returkoden er to. Dette er returkoden «ping» bruker for generelle feil.
Sette grunnregler
«timeout» handler om å sette grenser for kjørende programmer. Hvis du er bekymret for at loggfilene kan fylle opp harddisken, eller at du kanskje glemmer at et nettverksverktøy kjører, bruk «timeout» og la datamaskinen din selvregulere.