Како користити команду за временско ограничење на Линуку

Vreme za računar je isteklo. Procesima se mogu odrediti vremenska ograničenja, postavljanjem maksimalnog trajanja njihovog rada pomoću komande `timeout`. U nastavku je prikazano kako se koristi ova komanda za ograničavanje vremena izvršavanja programa.

Šta tačno radi komanda `timeout`?

Komanda `timeout` omogućava vam da postavite vremensko ograničenje trajanja izvršavanja programa. Postavlja se pitanje, zašto biste to uopšte želeli?

Jedna od situacija je kada tačno znate koliko dugo želite da se proces izvršava. Uobičajen scenario je kontrolisanje programa za evidentiranje ili snimanje podataka kako bi se sprečilo da datoteke sa zapisima nekontrolisano zauzimaju prostor na vašem čvrstom disku.

Drugi slučaj je kada niste sigurni koliko dugo želite da proces traje, ali sigurno ne želite da se izvršava beskonačno. Možda imate naviku pokretanja procesa, minimiziranja terminala i zaboravljanja na njih.

Određeni programi, čak i jednostavni alati, mogu generisati mrežni saobraćaj koji može negativno uticati na performanse vaše mreže. Ili mogu opteretiti resurse na ciljnom uređaju, usporavajući ga (ping je jedan od takvih primera). Loša praksa je ostaviti takve programe da rade na duži vremenski period dok ste udaljeni od računara.

Komanda `timeout` je deo GNU Core Utilities, što znači da je integrisana u Linux i operativne sisteme slične Unix-u, poput macOS-a. Ne zahteva nikakvu instalaciju; odmah je spremna za upotrebu.

Prvi koraci sa komandom `timeout`

Pogledajmo jednostavan primer. Podrazumevano, komanda `ping` će se izvršavati dok je ne zaustavite kombinacijom tastera Ctrl+C. Ako je ne prekinete, nastaviće da radi.

ping 192.168.4.28

Koristeći `timeout`, možemo osigurati da se `ping` ne izvršava beskonačno, trošeći mrežni protok i opterećujući uređaj koji pingujemo.

Sledeća komanda koristi `timeout` za ograničavanje trajanja komande `ping`. Ograničavamo je na 15 sekundi rada.

timeout 15 ping 192.168.4.28

Nakon 15 sekundi, `timeout` prekida `ping` sesiju i vraća nas na komandnu liniju.

Korišćenje komande `timeout` sa drugim vremenskim jedinicama

Važno je napomenuti da nismo morali dodati „s“ iza broja 15. `timeout` pretpostavlja da je vrednost u sekundama. Možete dodati „s“, ali to ne pravi razliku.

Za korišćenje vremenske vrednosti izražene u minutama, satima ili danima, dodajte „m“, „h“ ili „d“.

Za pokretanje komande `ping` u trajanju od tri minuta, koristite sledeću komandu:

timeout 3m ping 192.168.4.28

Komanda `ping` će raditi tri minuta pre nego što je `timeout` zaustavi.

Ograničavanje prikupljanja podataka pomoću komande `timeout`

Neke datoteke za prikupljanje podataka mogu veoma brzo rasti. Da biste sprečili da takve datoteke postanu prevelike i problematične, ograničite trajanje programa za snimanje.

U ovom primeru koristimo `tcpdump`, alat za hvatanje mrežnog saobraćaja. Na test mašinama korišćenim za istraživanje ovog članka, `tcpdump` je već bio instaliran na Ubuntu i Fedora Linux sistemima. Moralo ga je instalirati na Manjaro i Arch Linux sistemima sa sledećom komandom:

sudo pacman -Syu tcpdump

Možemo pokrenuti `tcpdump` na 10 sekundi sa podrazumevanim opcijama i preusmeriti njegov izlaz u datoteku `capture.txt` sa sledećom komandom:

timeout 10 sudo tcpdump > capture.txt

(`tcpdump` ima svoje opcije za čuvanje snimljenog mrežnog saobraćaja u datoteci. Ovo je brzo rešenje jer se fokusiramo na `timeout`, a ne na `tcpdump`.)

`tcpdump` počinje da hvata mrežni saobraćaj i čekamo 10 sekundi. Tih 10 sekundi prođe, a `tcpdump` i dalje radi, a `capture.txt` datoteka i dalje raste. Potreban je brzi Ctrl+C da se zaustavi `tcpdump`.

Provera veličine `capture.txt` pomoću komande `ls` pokazuje da je narasla na 209K za nekoliko sekundi. Ta datoteka je brzo rasla!

ls -lh capture.txt

Šta se desilo? Zašto `timeout` nije zaustavio `tcpdump`?

Sve je u vezi sa signalima.

Slanje pravog signala

Kada `timeout` želi da zaustavi program, šalje SIGTERM signal. Ovo je ljubazan zahtev programu da se prekine. Neki programi mogu ignorisati SIGTERM signal. U tom slučaju, potrebno je naterati `timeout` da bude malo agresivniji.

To možemo učiniti tako što ćemo zatražiti od `timeout` da pošalje SIGKILL signal.

SIGKILL signal ne može biti „uhvaćen, blokiran ili ignorisan“ – uvek prolazi. SIGKILL ne traži ljubazno od programa da se zaustavi. SIGKILL čeka iza ugla sa štopericom i kosom.

Možemo koristiti opciju `-s` (signal) da kažemo `timeout` da pošalje SIGKILL signal.

timeout -s SIGKILL 10 sudo tcpdump > capture.txt

Ovog puta, čim prođe 10 sekundi, `tcpdump` se zaustavlja.

Prvo ljubazno pitajte

Možemo zahtevati od `timeout` da pokuša da zaustavi program koristeći SIGTERM i da pošalje SIGKILL samo ako SIGTERM ne uspe.

Za to koristimo opciju `-k` (kill after). Opcija `-k` zahteva vremensku vrednost kao parametar.

U ovoj komandi tražimo od `timeout` da pusti `dmesg` da radi 30 sekundi, a zatim ga prekine signalom SIGTERM. Ako `dmesg` i dalje radi nakon 40 sekundi, to znači da je diplomatski SIGTERM ignorisan i `timeout` treba da pošalje SIGKILL da završi posao.

`dmesg` je alat koji može pratiti poruke bafera prstena jezgra i prikazati ih u prozoru terminala.

timeout -k 40 30 dmesg -w

`dmesg` radi 30 sekundi i zaustavlja se kada primi SIGTERM signal.

Znamo da SIGKILL nije zaustavio `dmesg` jer SIGKILL uvek ostavlja jednodnevnu poruku u prozoru terminala: „Ubijen“. To se u ovom slučaju nije dogodilo.

Preuzimanje izlaznog koda programa

Programi koji se dobro ponašaju vraćaju vrednost u ljusku nakon završetka. Ovo je poznato kao izlazni kod. Obično se koristi da obavesti ljusku, ili bilo koji proces koji je pokrenuo program, da li je program naišao na probleme tokom rada.

`timeout` obezbeđuje sopstveni izlazni kod, ali nas to možda ne zanima. Verovatno nas više zanima izlazni kod procesa koji kontroliše `timeout`.

Ova komanda omogućava da `ping` radi pet sekundi. Pinguje računar pod nazivom Nostromo, koji se nalazi na test mreži korišćenoj za ovaj članak.

timeout 5 ping Nostromo.local

Komanda radi pet sekundi i `timeout` je prekida. Zatim možemo proveriti izlazni kod pomoću sledeće komande:

echo $?

Izlazni kod je 124. Ovo je vrednost koja se koristi za označavanje da je program prekinut pomoću SIGTERM-a. Ako SIGKILL prekine program, izlazni kod je 137.

Ako prekinemo program sa Ctrl+C, izlazni kod iz `timeout`-a je nula.

timeout 5 ping Nostromo.local
echo $?

Ako se izvršavanje programa završi pre nego što ga prekine `timeout`, `timeout` može da prosledi izlazni kod iz programa nazad u ljusku.

Da bi se ovo dogodilo, program mora da se zaustavi sam od sebe (drugim rečima, ne prekida ga `timeout`) i moramo koristiti opciju `–preserve-status`.

Ako koristimo opciju `-c` (count) sa vrednošću pet, `ping` će pokrenuti samo pet zahteva. Ako damo `timeout` od jednog minuta, `ping` će se definitivno prekinuti sam od sebe. Zatim možemo proveriti izlaznu vrednost pomoću `echo`.

timeout --preserve-status 1m ping -c 5 Nostromo.local
echo $?

`ping` završava svojih pet ping zahteva i završava. Izlazni kod je nula.

Da bismo proverili da izlazni kod dolazi od `ping`-a, hajde da primoramo `ping` da generiše drugačiji izlazni kod. Ako pokušamo da pošaljemo `ping` zahteve na nepostojeću IP adresu, `ping` neće uspeti sa izlaznim kodom greške. Zatim možemo koristiti `echo` da proverimo da li je izlazni kod različit od nule.

timeout --preserve-status 1m ping -c 5 NotHere.local
echo $?

Komanda `ping` očigledno ne može da stigne do nepostojećeg uređaja, pa prijavljuje grešku i zatvara se. Izlazni kod je dva. Ovo je izlazni kod koji `ping` koristi za opšte greške.

Postavljanje osnovnih pravila

`timeout` služi za postavljanje ograničenja za izvršavanje programa. Ako postoji rizik da datoteke sa zapisima mogu da preplave vaš čvrsti disk ili da zaboravite da ste ostavili neki mrežni alat da radi, koristite `timeout` i prepustite računaru da se samoreguliše.