Fork-bomba (és harakiri) :)

Ma az alábbi scriptről lesz szó, ami nemes egyszerűséggel a fork_bomb.sh nevet kapta. Arra való, hogy padlóra vigye a Linux vagy UNIX rendszert. Ha egy szülő folyamat egy gyermek folyamatot indít, fork történik. Ez a “bomba” saját magát indítja el újra meg újra. Ez egyébként csúnya dolog ebben a formában. 🙂

gvamosi@gergo1:~$ cat fork_bomb.sh
#!/bin/sh
#
# fork test by gvamosi on 2019-09-29
############################################

var1=0
if [ -n "$1" ]; then
var1=$1
fi
echo "$0 $var1"
var1=$((var1 + 1))

while true; do
sleep 2
/bin/sh $0 $var1 & # itt történik a rekurzív hívás, a "fork"
done

Hogy hogyan lehet elindítani?

gvamosi@gergo1:~$ ./fork_bomb.sh &

És leállítani, ha még nem késő? Két másodpercre vettem a sleep-jét, hogy legyen idő beavatkozni. A Linux-unk ugyan korlátozza az egy felhasználó által nyitható processzek számát, de egy másodperces sleep-pel a notebook-omat sikerült úgy megfektetnem, hogy csak a “szentháromság” (ctrl+alt+del) segített. Ugyanis hiába zárja be az operációs rendszer a processzeket, a rekurzív fork miatt újra és újra nyílnak a kis programocskák, így egy tartós leterhelt állapot keletkezik. Ilyenkor nem, vagy csak alig reagál a számítógépünk.

gvamosi@gergo1:~$ killall fork_bomb.sh
gvamosi@gergo1:~$ killall sh

Ez a két parancs segíthet, ebben a sorrendben, ha elég gyorsak vagyunk. 🙂

Utólag nézem, hogy a “kill -9 -1” – ilyet azért root-ként (rendszergazdaként) vagy dba-ként (adatbázis-adminisztrátorként) be ne írjunk, adatvesztés történhet! – úgy kivágta a saját processz-erdőmet egy szemvillanás alatt, hogy öröm volt nézni. 🙂 Megteszi reboot helyett, még jó, hogy a chrome böngészőmben van “restore” funkció a tabfülekre. 🙂

Egyébként a rendelkezésre álló “javakról” az ulimit parancs segítségével tájékozódhatunk.

gvamosi@gergo1:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 30575
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 30575
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

Jól látható, hogy 1024-nél több fork_bomb.sh-t nem igen indíthatunk. A rendszergazda így simán tökön tud rúgni minket, ha garázdálkodunk. Régebben egyébként használtak az adminok ún. “watchdog” démont, ami automtikusan reboot-olta a rendszert, ha nagy volt a baj. 🙂

Van még egy érdekes parancs. Ez a root-ként (rendszergazdaként) kiadott “rm -rf /“. Rákérdezés nélküli rekurzív törlés a gyökérből kiindulva. Használata szigorúan TILOS!!! Letöröl MINDENT a DISZKRŐL!!! VÉGLEGESEN!!! Ezt a parancsot csak egyszer adhatjuk ki. 😦

Zombi-gyilkolás :)

A folyamatok státusza a top parancs képernyője szerint lehet “running” – “futó“, “sleeping” – “alvó“, “stopped” – “megállított“, illetve “zombie” – “zombi“.

A tegnapi secure shell-es lecke megírása közben véletlenül lehajtottam a Linux notebook képernyőjét, azaz összecsuktam a gépet. Közben az asztali Mac mini-ről bejelentkezve maradtam.

Ilyenkor egy bennragadt shell processzről van szó. Majdhogynem zombi. Persze valójában nem az. Zombit ugyanis nem lehet kill-elni, mivel a zombi processz már “halott”. Akkor tűnik el a processztáblából, ha a szülő processzét kinyírtuk. 🙂

A szülő processz id-ket ps all vagy céltudatosabban a ps -A -ostat,pid,ppid paranccsal írhatjuk ki. Ez utóbbinál az ostat ha z vagy Z, akkor van szó zombi processzről, a pid a processz azonosító, a ppid pedig a szülő folyamaté. Bővebben az alábbi linken lehet erről olvasni.

https://stackoverflow.com/questions/16944886/how-to-kill-zombie-process

Hogy hogyan lőttem ki kill -9-cel a bennragadt bash processzt, lásd az alábbiakban.

gvamosi@gergo1:~$ w
23:56:28 up 2 days, 13:11, 2 users, load average: 1.16, 0.91, 0.94
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
gvamosi tty2 tty2 Sat10 2days 1:39m 11.13s /opt/google/chrome/chrome --type=renderer --field-trial-handle=15503761646981189628,17074726826077816693,131072 --lang=en-US --enable-auto-reload
gvamosi pts/1 192.168.0.113 18:21 5:35m 0.00s 0.00s -bash
gvamosi@gergo1:~$ ps axu | grep bash
gvamosi 5312 0.0 0.0 7300 3612 pts/0 Ss Sep14 0:00 -bash
gvamosi 26716 0.0 0.0 6076 876 pts/0 S+ 23:56 0:00 grep bash
gvamosi 32208 0.0 0.0 7188 3884 pts/1 Ss+ 18:21 0:00 -bash
gvamosi@gergo1:~$ kill -9 32208
gvamosi@gergo1:~$ ps axu | grep bash
gvamosi 5312 0.0 0.0 7300 3612 pts/0 Ss Sep14 0:00 -bash
gvamosi 27005 0.0 0.0 6076 884 pts/0 S+ 23:56 0:00 grep bash
gvamosi@gergo1:~$ w
23:56:56 up 2 days, 13:12, 1 user, load average: 1.04, 0.90, 0.93
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
gvamosi tty2 tty2 Sat10 2days 1:39m 11.14s /opt/google/chrome/chrome --type=renderer --field-trial-handle=15503761646981189628,17074726826077816693,131072 --lang=en-US --enable-auto-reload
gvamosi@gergo1:~$

A w paranccsal megnéztem, hogy pts/1-en “benn maradtam” a szerverként szolgáló notebook-on gvamosi felhasználó név alatt (2 users). Utána ps paranccsal megkerestem azt a bash shell-t, ami szintén a pts/1-hez van rendelve. Ezután elég volt egy kill -9 PID – processz azonosító, azaz kill -9 32208 parancs. Jól látható az utána kiadott w parancs után, hogy eltűnt a “bennragadt” felhasználó (1 user). 🙂

Linux parancsok III. – folyamat (processz vagyis process) kezelés

A rendszer illetve felhasználói folyamatok változását a top paranccsal követhetjük nyomon.

gvamosi@gergo1:~$ top
top - 14:07:27 up 10 days, 23:46, 1 user, load average: 1.25, 1.64, 1.48
Tasks: 296 total, 1 running, 295 sleeping, 0 stopped, 0 zombie
%Cpu(s): 6.6 us, 2.7 sy, 0.0 ni, 90.2 id, 0.1 wa, 0.0 hi, 0.4 si, 0.0 st
MiB Mem : 7787.5 total, 338.1 free, 5721.7 used, 1727.8 buff/cache
MiB Swap: 7999.0 total, 5819.9 free, 2179.1 used. 1256.1 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2344 gvamosi 20 0 1374840 286664 77172 S 4.5 3.6 12:53.42 chrome
1078 gvamosi 20 0 3845288 419172 154072 S 4.3 5.3 65:51.87 gnome-shell
651 root 20 0 242112 7888 4120 S 3.3 0.1 44:46.06 polkitd
618 message+ 20 0 10980 4864 2812 S 2.5 0.1 34:15.79 dbus-daemon
9875 gvamosi 20 0 786732 142276 37384 S 2.2 1.8 16:27.54 chrome
2572 gvamosi 20 0 746960 250692 171320 S 2.0 3.1 52:54.91 chrome
2535 gvamosi 20 0 1605200 350008 59044 S 1.2 4.4 57:11.69 chrome
1277 gvamosi 20 0 802672 11396 6860 S 1.0 0.1 12:39.06 gsd-power
259 root 20 0 78056 22700 12216 S 0.7 0.3 7:51.31 systemd-journal
2577 gvamosi 20 0 424236 79836 18900 S 0.7 1.0 13:30.91 chrome
2898 gvamosi 20 0 720348 135476 39892 S 0.5 1.7 6:50.90 chrome
5869 gvamosi 20 0 425680 27296 18704 S 0.5 0.3 1:03.25 gnome-terminal-
24660 root 20 0 23136 2064 1584 S 0.5 0.0 0:02.33 systemd-udevd
626 root 20 0 236956 4252 3864 S 0.3 0.1 4:11.97 iio-sensor-prox
710 root 20 0 1419904 3700 3476 S 0.3 0.0 5:10.92 libvirtd
2891 gvamosi 20 0 1622204 368832 71120 S 0.3 4.6 15:17.82 chrome
3038 gvamosi 20 0 846480 219688 52028 S 0.3 2.8 18:07.01 chrome
6242 gvamosi 20 0 631976 58680 22788 S 0.3 0.7 1:53.68 chrome
6382 gvamosi 20 0 654012 77832 22240 S 0.3 1.0 1:58.41 chrome
31699 gvamosi 20 0 11592 4068 3188 R 0.3 0.1 0:00.30 top
1 root 20 0 170984 7468 5340 S 0.2 0.1 3:27.43 systemd

Jól látható a tetején az “up” azaz 10 napja volt elindítva a gép – persze közben volt sleep státuszban 🙂 -, aztán hogy 1 felhasználó van bejelentkezve, és hogy a load, azaz a kihasználtsága a rendszernek körülbelül 1,5 – ami jónak mondható.

Aztán a folytatásban a teljes taszkok (folyamatok) száma 296, amiből egy van “running”, azaz “futó” státuszban.

Majd a processzor kihasználtság százalékokban: felhsználó, rendszer, idle. Ezt követi a memória és a swap kihasználtsága. 🙂

Ezen általános rendszer-mérőszámok után következnek a processzek, vagyis a folyamatok, pid – processz id-vel, tulajdonos user-rel (többnyire gvamosi, illetve root a példában), mindenféle memóriafoglaltságokkal és cpu (processzor) használattal, végül az eddigi futási idő összesen és a parancs neve. 🙂

Fontos parancs még a teljes processz lista lekérése, a ps axu. Ez az összes processz kilistázása a rendszeren.

gvamosi@gergo1:~$ ps axu | less

Ebben a listában szemügyre vehetjük, a top kimenetéhez hasonlóan, hogy ki mit futtat, illetve mennyi erőforrást vesznek igénybe az egyes folyamatok.

Ha megszámoljuk a sorokat a wc -l (word count) paranccsal, akkor a topban kapott “Tasks total” számot + egyet, a fejléc miatt – kell kapjunk. 🙂

gvamosi@gergo1:~$ ps axu | wc -l
286

Látható, hogy a top parancs óta pár folyamat “bezáródott”.

Nézzük még meg a kill parancsot. Bemutatom, hogyan lehet saját magunk alatt kivágni vele a “fát”. Előbb lekérdezzük a bash shell-ünk id-jét a ps paramccsal, majd -9 -es killel termináljuk a saját shell-ünk. 🙂

gvamosi@gergo1:~$ ps
PID TTY TIME CMD
20646 pts/0 00:00:00 bash
20733 pts/0 00:00:00 ps
gvamosi@gergo1:~$ kill -9 20646

A folyamatokról a teljes leírást státuszdiagrammal az alábbiakban olvashatjuk (angolul).

https://www.tecmint.com/linux-process-management/

Sorvége jel Linux, Mac és Windows alatt, folyamat kezelés parancssorból

Az ún. szövegfile-ok feldolgozása soronként történik. A sorvége karakterek a CR – carriage return, escape szekvenciája \r, (decimális kódja 13, hexadecimálisan pedig 0D, jelölik még ^M, azaz CTRL+M-ként is, “CTRL+V CTRL+M”-ként lehet “előhozni”), illetve az LF – line feed, azaz shell scriptben vagy c-ben jelölve \n (decimális kódja 10, hexadecimálisan pedig 0A).

Linux alatt – illetve OS X alatt is – ez “\n”, klasszikus Mac alatt “\r”, Windows alatt pedig “\r\n”. Látható tehát, hogy teljes káosz. 🙂

https://en.wikipedia.org/wiki/Newline

Nézzünk meg néhány hasznos billentyűzet kódot Linux/UNIX alatt, illetve a folyamat kezelés ide vonatkozó részeit!

CTRL+C: SIGINT, megszakítás, azaz interrupt, vagyis “kill
CTRL+Z
: SIGTSTP, az előtérben futó processz megszakítása, szoktak utána “bg <ENTER>“-t beírni, így a processz háttérben (background) tovább fut, jobs parancs-csal lehet kiírni a futó processzeket, illetve fg (foreground) paranccsal újra “előtérbe hozni” – eleve “háttérben” a sor végi “&” jellel lehet indítani egy folyamatot/processzt
CTRL+D: file vége, úgyis mint exit parancs a shellben, pl. bash-ban

CTRL+L: képernyőtörlés – ugyanaz, mint a “clear” parancs
CTRL+S
: leállítja a képernyőre/terminálba küldött “kimenetet”
CTRL+Q: a CTRL+S-sel leállított kimenetet “folytatja”

https://www.howtogeek.com/howto/ubuntu/keyboard-shortcuts-for-bash-command-shell-for-ubuntu-debian-suse-redhat-linux-etc/

https://www.thegeekdiary.com/understanding-the-job-control-commands-in-linux-bg-fg-and-ctrlz/