Signallar va jarayonlarni boshqarish: kill, SIGTERM va SIGKILL
Jarayon ustuvorligini pasaytirish yoki oshirish u qancha CPU vaqti olishini o'zgartiradi, lekin jarayonni hech qachon to'xtatmaydi — ustuvorligi pasaytirilgan jarayon cheksiz ishlashda davom etadi. Administratorlarga esa muntazam ravishda butunlay boshqacha narsa kerak bo'ladi: qotib qolgan jarayonni majburan tugatish, ishlab turgan xizmatga to'liq qayta ishga tushirmasdan konfiguratsiyasini qayta yuklashni buyurish yoki uzoq davom etadigan ishni pauza qilib, keyinroq davom ettirish. Uchalasi ham bitta kernel mexanizmi — signallar orqali bajariladi, garchi ular uchun kundalik buyruqlar (kill, killall, Ctrl+C) tashqaridan bir-biriga bog'liq bo'lmagandek ko'rinsa ham.
Bu maqolada signal kernel darajasida aslida nima ekanini, kundalik administratorlik uchun muhim bo'lgan bir nechta signalni, nega SIGKILL birinchi refleks emas, oxirgi chora ekanini va jarayon signaldan shunchaki o'lish o'rniga uni qanday ushlab, qayta ishlashi mumkinligini ko'rib chiqamiz.
Signal aslida nima
Signal — kernel jarayonga yetkazadigan cheklangan, asinxron bildirishnoma. U kichik butun son va ramziy nom bilan aniqlanadi (SIGTERM — 15-signal, SIGKILL — 9-signal). Signallar jarayon hozir bajarayotgan ishni uzib qo'yadi va uni bildirishnomani uchta mumkin bo'lgan munosabatdan (disposition) biriga ko'ra qayta ishlashga majbur qiladi:
- Standart amal — agar jarayon hech qanday maxsus ish qilmasa, ko'pchilik signallar uchun kernel belgilagan standart amal bor: tugatish, core dump bilan tugatish, to'xtatish, davom ettirish yoki (ba’zilari uchun) butunlay e’tiborsiz qoldirish.
- E’tiborsiz qoldirilgan — jarayon kernelga signalni e’tiborga olmaslikni aniq aytishi mumkin.
- Ushlangan (qayta ishlangan) — jarayon signal kelganda ishga tushadigan o'z funksiyasini ro'yxatdan o'tkazishi mumkin. Bu unga qanday davom etishni hal qilishdan oldin resurslarni tozalash, hodisani logga yozish yoki konfiguratsiyani qayta yuklash imkonini beradi.
Eng muhimi, har bir signalni ushlash yoki e’tiborsiz qoldirish mumkin emas. SIGKILL (9) va SIGSTOP (19) ni kernel to'g'ridan-to'g'ri qayta ishlaydi va nishondagi jarayon ularni hech qanday sharoitda ushlay, bloklay yoki ularga o'z ishlovchisini bera olmaydi. Bu jarayon qanchalik yomon ishlamasin, uni to'xtatish yoki tugatishning har doim yo'li bo'lishini ta’minlaydigan ataylab qilingan loyiha kafolati.
Kundalik ishda muhim signallar
| Signal | Raqami | Standart amali | Odatiy qo'llanishi |
|---|---|---|---|
SIGHUP |
1 | tugatish | tarixan "terminal aloqasi uzildi"; daemon’lar uni ko'pincha "konfiguratsiyani qayta yukla" ma’nosida ishlatadi |
SIGINT |
2 | tugatish | interaktiv terminalda Ctrl+C yuboradi |
SIGQUIT |
3 | tugatish + core dump | Ctrl+\ yuboradi; nosozliklarni tuzatish uchun core dump so'raydi |
SIGKILL |
9 | tugatish | shartsiz, ushlab bo'lmaydigan tugatish |
SIGTERM |
15 | tugatish | muloyim, ushlanadigan to'xtash so'rovi — kill sukut bo'yicha yuboradigan signal |
SIGSTOP |
19 | to'xtatish | shartsiz, ushlab bo'lmaydigan pauza |
SIGCONT |
18 | davom ettirish | to'xtatilgan jarayonni davom ettiradi |
SIGTSTP |
20 | to'xtatish | Ctrl+Z yuboradi; SIGSTOP dan farqli ravishda ushlanadi |
SIGCHLD |
17 | e’tiborsiz qoldiriladi | bola jarayon tugaganda yoki to'xtaganda ota jarayonga yuboriladi |
SIGUSR1/SIGUSR2 |
10/12 | tugatish | ilovaning o'z maxsus ma’nosi uchun ajratilgan |
Aniq signal raqamlari CPU arxitekturasiga qarab biroz farq qilishi mumkin, lekin yuqorida keltirilganlari Ubuntu Server va RHEL oilasidagi tizimlarda ishlatiladigan keng tarqalgan x86_64 va aarch64 platformalarida bir xil.
Signal yuborish: kill, killall, pkill
Nomiga qaramay, kill faqat tugatish signallarini emas, istalgan signalni yuboradi — bu nom tarixan uning eng ko'p qo'llanishi tugatish bo'lganini aks ettiradi.
Uchala qator ham bir xil; kill signalni ramziy nomi bo'yicha (SIG prefiksi bilan yoki usiz) yoki raqami bo'yicha qabul qiladi. Hech qanday signal ko'rsatilmasa, kill 22110 sukut bo'yicha SIGTERM yuboradi.
killall jarayonning aniq nomi bo'yicha moslaydi; pkill esa nom bo'yicha yoki -f bilan butun buyruq qatoriga nisbatan moslaydi. Bu moslashuvchanroq, lekin ko'zda tutilmagan narsaga mos kelish ehtimoli ham yuqoriroq.
Warning
Andoza bo'yicha signal yuborishdan oldin nishonni doim tasdiqlang. Avval pgrep -af '<pattern>' ni (yoki killall ning aniq nom bo'yicha moslashi uchun pgrep -a ni) bajaring va mos kelgan natijaning har bir qatorini o'qing — ko'zda tutilganidan kengroq andoza nomi yoki argumentlarida shunchaki xuddi shu satr bo'lgan, umuman bog'liq bo'lmagan jarayonni tugatib yuborishi mumkin.
Jarayonga signal yubormasdan uning mavjudligini tekshirish
0-signal maxsus: kernel hech qanday signalni aslida yetkazmasdan, mavjudlik va ruxsat tekshiruvini bajaradi. 0 chiqish holati jarayon mavjudligini va sizda unga signal yuborish ruxsati borligini bildiradi; noldan farqli holat ("No such process" kabi xabar bilan) esa jarayon mavjud emasligini yoki sizda ruxsat yo'qligini bildiradi. Bu skriptda "bu PID hali tirikmi" degan savolni tekshirishning standart, yon ta’sirsiz usuli.
SIGTERM va SIGKILL: nega tartib muhim
SIGTERM jarayondan to'xtashni so'raydi. U ushlanishi mumkin bo'lgani uchun to'g'ri yozilgan jarayon undan chiqishdan oldin ochiq fayllarni yopish, buferdagi yozuvlarni diskka yozish, bajarilayotgan ma’lumotlar bazasi tranzaksiyasini tugatish va qulflarni toza bo'shatish uchun ishora sifatida foydalanadi. SIGKILL esa jarayonga bunday imkon bermaydi — kernel uni keyingi rejalashtirish imkoniyatidayoq, hech qanday tozalash kodi ishlamasdan darhol tugatadi.
Bu standart bosqichma-bosqich kuchaytirish andozasi: muloyim to'xtashni so'rang, jarayon haqiqatan chiqishi uchun oqilona vaqt kuting va faqat shu imtiyozli muddatdan keyin ham tirik bo'lsa, SIGKILL yuboring. systemctl stop ichida aynan shu andozaga amal qiladi va uni har bir unit uchun TimeoutStopSec orqali sozlash mumkin.
Danger
SIGKILL (kill -9) ga birinchi refleks sifatida murojaat qilish muntazam ravishda haqiqiy zarar keltiradi: yozish o'rtasida o'ldirilgan ma’lumotlar bazasi jarayoni keyingi ishga tushishda sekin tiklashni talab qiladigan buzilgan ma’lumotlar faylini qoldirishi mumkin; taqsimlangan qulfni ushlab turgan ilova uni hech qachon bo'shatmaydi, chunki uning tozalash ishlovchisi umuman ishlamaydi; jarayon muloyim chiqishda o'chirgan bo'ladigan vaqtinchalik fayl qolib ketadi. Har doim avval SIGTERM ni sinab ko'ring va kuchaytirishdan oldin jarayonga o'zi chiqib ketishi uchun haqiqiy imkoniyat bering.
Qayta ishga tushirmasdan konfiguratsiyani qayta yuklash: SIGHUP
Ko'p uzoq ishlaydigan daemon’lar — nginx, sshd, rsyslog — SIGHUP ni (uning asl, terminal bilan bog'liq standart amali jarayonni shunchaki tugatardi) mavjud ulanishlarni uzmasdan yoki to'plangan holatni yo'qotmasdan, konfiguratsiya faylini joyida qayta yuklash so'rovi sifatida qayta ma’nolaydi:
nginx -t signal yuborishdan oldin konfiguratsiya sintaksisini tekshiradi. Ilovaga qarab, buzilgan konfiguratsiya fayli bilan SIGHUP yuborish jarayonni nomuvofiq holatda qoldirishi yoki qayta yuklash jimgina muvaffaqiyatsiz bo'lishiga olib kelishi mumkin. Qaysi daemon bo'lishidan qat’i nazar, avval tekshirish xavfsizroq odat.
systemctl reload <service> odatda aynan shu SIGHUP mexanizmi (yoki unit faylining ExecReload= qismida sozlangan ilovaga xos ekvivalent) ustidagi yupqa va topilishi osonroq o'rama. Xizmat systemd tomonidan boshqarilsa, signalni qo'lda yuborishdan ko'ra undan foydalanish afzal — u systemd’ning unit holati haqidagi o'z tasavvurini izchil saqlaydi.
Pauza qilish va davom ettirish: SIGSTOP va SIGCONT
T STAT i jarayon haqiqatan to'xtatilganini tasdiqlaydi — u ishlamayapti ham, uxlamayapti ham, shunchaki kernel tomonidan joyida muzlatib qo'yilgan: CPU vaqtini sarflamaydi, lekin barcha xotirasi va ochiq fayl deskriptorlarini saqlab turadi. SIGCONT uni aynan to'xtagan joyidan davom ettiradi. Bu juftlik ba’zan resurs talab qiladigan fon ishini raqobat davrida vaqtincha pauza qilish uchun foydali — uni tugatib, qayta ishga tushirishdagi kabi uning bajargan ishi yo'qolmaydi.
Jarayon signalni qanday ushlaydi
Ilova sigaction() (yoki eskiroq signal()) system call’i orqali signal ishlovchisini ro'yxatdan o'tkazadi va kernelga "X signali kelganda standart amal o'rniga mening shu funksiyamni ishga tushir" deb aytadi. To'g'ri yozilgan xizmatdagi muloyim to'xtash mantiqi aynan shu mexanizmga asoslanadi: jarayon amal o'rtasida shunchaki g'oyib bo'lmasligi uchun asosiy siklga joriy ish birligini tugatib, toza chiqishni buyuradigan bayroq o'rnatadigan SIGTERM ishlovchisi.
Ishlab turgan jarayonga qisqa vaqt strace ni ulab, boshqa terminaldan unga signal yuborish jarayon shu signal uchun haqiqatan o'z ishlovchisini ro'yxatdan o'tkazganmi yoki kernelning standart amaliga tayanayotganini real vaqtda ko'rsatishi mumkin. Bu xizmat nima uchun o'z hujjatlarida da’vo qilinganidek SIGHUP ga javob bermayotgandek ko'rinishini tashxislashda foydali.
Intervyuda
Keng tarqalgan intervyu savoli: "nega SIGKILL ni ushlab bo'lmaydi va bu amalda nima uchun muhim?" Kernel darajasidagi javob: SIGKILL va SIGSTOP oddiy signal yetkazish va munosabat mexanizmini butunlay chetlab o'tadi va shu bilan jarayonning signallarni qayta ishlashidagi xatolardan qat’i nazar, administratorda har qanday jarayonni tugatish yoki pauza qilishning har doim yo'li bo'lishini kafolatlaydi. Amaliy oqibati esa ba’zan o'ylanganining aksi: SIGKILL ni ushlab bo'lmasligi aynan uning birinchi tanlov emas, oxirgi chora bo'lishi kerakligining sababi — jarayon qulflarni bo'shatish, ma’lumotlarni diskka yozish yoki vaqtinchalik holatni tozalash imkoniyatini olmaydi. Yuqorida aytilgan buzilish va resurslar sizib chiqishi muammolarining bevosita sababi ham shu.
Zombilar: bola jarayonning chiqish holati hech qachon yig'ib olinmaganda
Jarayon tugaganda u jarayonlar jadvalidan darhol yo'qolmaydi — ota jarayon o'sha holatni yig'ib olish uchun wait() (yoki waitpid()) ni chaqirmaguncha u faqat o'z chiqish holatini saqlab turadigan zombiga (STAT — Z) aylanadi. Hech qachon wait() ni chaqirmaydigan ota jarayon — odatda bu xato, ba’zan esa bola jarayonlarni ishga tushirib, ularni hech qachon tekshirmaydigan haqiqatan oddiy skript — zombilar to'planib borishiga sabab bo'ladi.
Kichik va barqaror sondagi o'tkinchi zombilar odatiy holat — har bir bola jarayon chiqish va tozalanish o'rtasida qisqa vaqt shu holatdan o'tadi. Vaqt o'tishi bilan o'sib boradigan zombilar soni, ayniqsa ularning hammasi bitta ota PID ga ega bo'lsa, ota jarayonda haqiqiy tozalash (reaping) xatosi borligini ko'rsatadi.
Note
Zombi jarayonni o'ldirib bo'lmaydi — u allaqachon o'lgan; faqat uning jarayonlar jadvalidagi yozuvi tozalanishini kutib qolgan. Unga istalgan signal, jumladan SIGKILL yuborish ham hech qanday ta’sir qilmaydi. Yagona yechim — ota jarayonning wait() ni chaqirishi. Bu yo ota jarayon kodini tuzatishni, yo ota jarayonning o'zi javob bermayotgan bo'lsa, uni tugatishni anglatadi (bunda zombi PID 1 yoki subreaper’ga qayta biriktiriladi, ular esa uni to'g'ri tozalaydi).
Real vaziyat: xizmat odatdagi to'xtatishga javob bermayapti
Muammo. systemctl stop catalog.service qaytadi, lekin sozlangan kutish muddatidan keyin ham systemctl status jarayon ishlayotganini ko'rsatyapti va deploy pipeline’i endi uni kutib qotib qolgan.
Avval jarayonning haqiqiy holatini tekshiring:
systemctl status catalog.service
ps -o pid,ppid,stat,cmd -p "$(systemctl show -p MainPID --value catalog.service)"
D STAT i (signalni shunchaki e’tiborsiz qoldirish emas, uzilmas uyqu) asosiy topilma: jarayon kernel ichida I/O amalida bloklangan va loyihaga ko'ra, aynan shu kernel amali tugamaguncha yoki uning muddati o'tmaguncha uni hech qanday signal, jumladan SIGTERM va hatto SIGKILL ham uza olmaydi.
U nimada bloklanganini tasdiqlang:
Xulosa. Agar jarayon haqiqatan qotib qolgan disk yoki tarmoq fayl tizimi amalida D holatida tursa, ostidagi I/O hal bo'lmaguncha yoki kernel darajasida uning muddati o'tmaguncha hech qanday signal uni tugatmaydi. Bu ilova SIGTERM ni shunchaki e’tiborsiz qoldirishidan tubdan farq qiladigan holat va SIGKILL ni qayta-qayta yuborish yordam bermaydi. Haqiqiy yechim jarayonning o'zini emas, qotib qolgan I/O manbasini (javob bermayotgan NFS server, ishdan chiqayotgan disk) nishonga oladi; I/O tugagach yoki kernel undan voz kechgach, jarayonni odatdagidek o'ldirish mumkin bo'ladi. Agar buning o'rniga jarayon S yoki R STAT ini ko'rsatsa va SIGTERM dan keyin shunchaki hech qachon chiqmasa, bu ilovaning o'z signal ishlovchisi buzilgani yoki yo'qligiga ishora qiladi — to'g'ri qayta yuklash/to'xtatish signali uchun uning hujjatlarini tekshirishga arziydi — va faqat shundan keyingina SIGKILL ga o'tish o'rinli, garchi qo'pol bo'lsa ham, keyingi qadam bo'ladi.
Keng tarqalgan xatolar
Birinchi qadam sifatida kill -9 ga murojaat qilish
Bu jarayon muloyim SIGTERM da ishga tushirgan bo'ladigan har qanday tozalash kodini o'tkazib yuboradi va buzilgan ma’lumotlar fayllari, bo'shatilmagan qulflar va yetim qolgan vaqtinchalik holat xavfini tug'diradi. Har doim avval SIGTERM ni sinab ko'ring va oqilona vaqt kuting.
SIGHUP har doim "qayta yuklash" degani deb o'ylash
Ilovaga xos ishlovchi bo'lmasa, SIGHUP ning standart amali — tugatish. Muayyan daemon uni "konfiguratsiyani qayta yukla" deb qayta talqin qilishi butunlay o'sha daemon’ning o'z kodiga bog'liq — bu kelishuv hamma joyda qo'llanadi deb o'ylamasdan, uning hujjatlarini tekshiring.
Zombini o'ldirishga urinish
Zombi allaqachon o'lgan; hech qanday signal unga ta’sir qilmaydi. Yechim zombi yozuvining o'zini emas, wait() ni chaqirmagan ota jarayonni nishonga oladi.
Avval tekshirmasdan keng pkill andozasini ishlatish
pkill -f butun buyruq qatoriga nisbatan moslaydi va jimgina xuddi shu satrni o'z ichiga olgan, bog'liq bo'lmagan jarayonlarni ham ushlab olishi mumkin. Avval xuddi shu andoza bilan pgrep -af ni bajaring va mos kelgan har bir qatorni o'qing.
SIGKILL D holatidagi jarayonni darhol tugatadi deb kutish
Kernel I/O amalida uzilmas uyquda bloklangan jarayonni aynan shu amal hal bo'lmaguncha hech qanday signal, jumladan SIGKILL ham tugata olmaydi. O'ldirishga urinishni takrorlash o'rniga ostidagi qotib qolgan I/O ni tashxislang.
Mashqlar
- Fonda
sleep 300 &ni ishga tushiring, ungaSIGTERMyuboring vapsbilan u chiqqanini tasdiqlang. BuniSIGSTOP, so'ngps -o stat, keyinSIGCONTbilan takrorlang va har bir qadamda jarayon bilan nima sodir bo'lganidagi farqni tasvirlab bering. - Tegishli signal raqamlarini keltirib, nega
kill -9 <pid>vakill -SIGSTOP <pid>ni nishondagi jarayon ushlab qola olmasligini,kill -15 <pid>vakill -SIGTSTP <pid>ni (Ctrl+Zdan) esa ushlab qola olishini tushuntiring. - Tizimingizda
SIGHUPorqali konfiguratsiyani qayta yuklashni qo'llab-quvvatlaydigan xizmatni toping (yoki shunday xizmat haqida fikr yuriting) vanginxuchun ko'rsatilgan andozaga amal qilib, unga signal yuborishdan oldin uning konfiguratsiyasini tekshirish uchun ishlatadigan aniq buyruqlar ketma-ketligini yozing. - Jarayon
ZSTATini ko'rsatmoqda, bir soatdan ko'proq vaqtdan beri mavjud va bittaPPIDga ega qo'shni jarayonlar soni o'sib bormoqda. Javobgar ota jarayonni aniqlash uchun ishlatadigan diagnostika buyruqlari ketma-ketligini yozing va aslida nimani tuzatish kerakligini tushuntiring.
Mashqni bajardim deyish uchun: ishlab turgan jarayonga nisbatan birinchi amal sifatida SIGKILL ni taklif qiladigan har qanday javob noto'g'ri — agar aynan shu holat uchun SIGTERM samarasiz ekani allaqachon tasdiqlanganini yozma ravishda asoslab bera olmasangiz.
Manbalar
- Linux man-pages:
signal(7): https://man7.org/linux/man-pages/man7/signal.7.html - Linux man-pages:
kill(1),kill(2): https://man7.org/linux/man-pages/man1/kill.1.html - Linux man-pages:
pkill(1),killall(1): https://man7.org/linux/man-pages/man1/pkill.1.html - Linux man-pages:
sigaction(2): https://man7.org/linux/man-pages/man2/sigaction.2.html - Linux man-pages:
wait(2),waitpid(2): https://man7.org/linux/man-pages/man2/waitpid.2.html - Linux man-pages:
proc(5)—/proc/[pid]/stat,/proc/[pid]/wchan: https://man7.org/linux/man-pages/man5/proc.5.html - freedesktop.org: systemd.service —
ExecReload=,TimeoutStopSec=: https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html