Linux kill正在執(zhí)行的后臺(tái)任務(wù) kill進(jìn)程組使用詳解
零. 用到的命令
# 查看當(dāng)前session會(huì)話正在后臺(tái)執(zhí)行的job jobs -l # 查看當(dāng)前腳本的進(jìn)程信息 ps -ef | grep -a "[m]y_script_child_process.sh" ps -o pid,pgid,ppid,cmd --forest # 以樹狀圖的形式表示指定的進(jìn)程號(hào) pstree -p 659 # 殺死659的進(jìn)程號(hào) kill -TERM 659 # 殺死659的進(jìn)程組 kill -TERM -659 # 查看bigfile.csv被哪個(gè)進(jìn)程占用 lsof bigfile.csv # 用setsid啟動(dòng)新會(huì)話,確保子進(jìn)程和父進(jìn)程用同一個(gè)進(jìn)程組 setsid nohup bash my_script_child_process.sh > /dev/null 2>&1 &
一. 待執(zhí)行的腳本
有如下2個(gè)腳本
apluser@FengYeHong-HP:0727$ ls -l -rw-r--r-- 1 apluser apluser 194 Jul 27 11:01 my_script_child_process.sh -rw-r--r-- 1 apluser apluser 180 Jul 27 11:42 my_script_no_child_process.sh
兩個(gè)腳本的作用相同,都是要花時(shí)間生成一個(gè)csv文件之后,然后睡眠10秒,然后打印內(nèi)容到控制臺(tái)
my_script_child_process.sh:在腳本中使用了(),在腳本啟動(dòng)時(shí),會(huì)創(chuàng)建一個(gè)子進(jìn)程my_script_no_child_process.sh:沒有使用(),在腳本啟動(dòng)時(shí),不會(huì)創(chuàng)建一個(gè)子進(jìn)程
apluser@FengYeHong-HP:0727$ cat my_script_child_process.sh
(
echo "No,姓名,auid,地址"
seq 1 40000000 | awk 'BEGIN{OFS=","} {
printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1
}'
) > bigfile.csv
sleep 10
echo "執(zhí)行完成"
apluser@FengYeHong-HP:0727$ cat my_script_no_child_process.sh
echo "No,姓名,auid,地址"
seq 1 40000000 | awk 'BEGIN{OFS=","} {
printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1
}' > bigfile.csv
sleep 10
echo "執(zhí)行完成"
二. 執(zhí)行含子進(jìn)程的腳本,并kill
2.1 進(jìn)程查看
通過&的方式在后臺(tái)執(zhí)行腳本,并使用jobs -l查看正在執(zhí)行的job的狀態(tài)
- 可以看到該腳本目前處于
Running的狀態(tài) - 腳本對(duì)應(yīng)的進(jìn)程號(hào)為:
659
apluser@FengYeHong-HP:0727$ bash my_script_child_process.sh & [1] 659 apluser@FengYeHong-HP:0727$ jobs -l [1]+ 659 Running bash my_script_child_process.sh &
通過ps -ef的方式查看腳本的進(jìn)程,因?yàn)槭褂?code>()在腳本內(nèi)部開啟了子進(jìn)程,所以我們會(huì)發(fā)現(xiàn)有2個(gè)關(guān)聯(lián)進(jìn)程
apluser@FengYeHong-HP:0727$ ps -ef | grep -a "[m]y_script_child_process.sh" # UID(用戶) PID(進(jìn)程 ID) PPID(父進(jìn)程 ID) CPU 占用率 啟動(dòng)時(shí)間 TTY(終端) 占用 CPU 時(shí)間 啟動(dòng)的命令 apluser 659 517 0 15:18 pts/0 00:00:00 bash my_script_child_process.sh apluser 660 659 0 15:18 pts/0 00:00:00 bash my_script_child_process.sh
查看進(jìn)程的父子層級(jí)關(guān)系(樹狀結(jié)構(gòu))以及每個(gè)進(jìn)程的 ID 信息
pid:進(jìn)程 IDpgid:進(jìn)程組 IDppid:父進(jìn)程 IDcmd:啟動(dòng)命令--forest:以 樹狀結(jié)構(gòu) 顯示進(jìn)程的父子層級(jí)關(guān)系
apluser@FengYeHong-HP:0727$ ps -o pid,pgid,ppid,cmd --forest
PID PGID PPID CMD
517 517 516 -bash
659 659 517 \_ bash my_script_child_process.sh
660 659 659 | \_ bash my_script_child_process.sh
661 659 660 | \_ seq 1 40000000
662 659 660 | \_ awk BEGIN{OFS=","} { printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1 }
665 665 517 \_ ps -o pid,pgid,ppid,cmd --forest
圖形化地查看進(jìn)程樹(659是主進(jìn)程)
659的主進(jìn)程中,創(chuàng)建了660的子進(jìn)程
通過()創(chuàng)建的660的子進(jìn)程內(nèi)部
- 又通過awk和seq命令分別創(chuàng)建了661和662的進(jìn)程
- 這些子進(jìn)程和主進(jìn)程都屬于
PGID為659的進(jìn)程組
apluser@FengYeHong-HP:0727$ pstree -p 659
bash(659)───bash(660)─┬─awk(662)
└─seq(661)
2.2 遇到的問題
在我們執(zhí)行kill命令之前,生成的文件大小如下
apluser@FengYeHong-HP:0727$ ls -l bigfile.csv -rw-r--r-- 1 apluser apluser 732053526 Jul 27 15:19 bigfile.csv
通過kill命令殺死PID為659的主進(jìn)程
apluser@FengYeHong-HP:0727$ kill -TERM 659 apluser@FengYeHong-HP:0727$ [1]+ Terminated bash my_script_child_process.sh
kill命令執(zhí)行之后,再次觀察文件,發(fā)現(xiàn)文件并沒有停止增長,反而繼續(xù)增大
apluser@FengYeHong-HP:0727$ ls -l bigfile.csv -rw-r--r-- 1 apluser apluser 960819222 Jul 27 15:19 bigfile.csv
此時(shí)通過lsof命令查看bigfile.csv文件被哪些進(jìn)程所占用,得到如下結(jié)果
- 可以看到主線程被kill掉之后,子線程依然活躍,所以文件 bigfile.csv 仍然在持續(xù)寫入
- 在主線程被kill掉之后,awk 的進(jìn)程(例如 PID 662)已經(jīng)獨(dú)立運(yùn)行,此時(shí)的進(jìn)程被稱為
孤兒進(jìn)程 - 除非我們顯式地kill掉,否則孤兒進(jìn)程會(huì)一直執(zhí)行到結(jié)束
apluser@FengYeHong-HP:0727$ lsof bigfile.csv COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 660 apluser 1w REG 8,48 1222258710 42569 bigfile.csv awk 662 apluser 1w REG 8,48 1222266902 42569 bigfile.csv
2.3 解決
2.3.1 kill進(jìn)程的時(shí)候,kill進(jìn)程組
我們?cè)凇?.1 進(jìn)程查看】的時(shí)候,查看過腳本相關(guān)的進(jìn)程的詳細(xì)信息
apluser@FengYeHong-HP:0727$ ps -o pid,pgid,ppid,cmd --forest
PID PGID PPID CMD
517 517 516 -bash
659 659 517 \_ bash my_script_child_process.sh
660 659 659 | \_ bash my_script_child_process.sh
661 659 660 | \_ seq 1 40000000
662 659 660 | \_ awk BEGIN{OFS=","} { printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1 }
665 665 517 \_ ps -o pid,pgid,ppid,cmd --forest
下面的這行命令,kill的是PID為659的主進(jìn)程,并不會(huì)對(duì)子進(jìn)程產(chǎn)生影響
kill -TERM 659
要想同時(shí)殺死主進(jìn)程的關(guān)聯(lián)子進(jìn)程,kill的對(duì)象不是PID,而應(yīng)該是PGID,即進(jìn)程組,只要所有的子進(jìn)程和主進(jìn)程同屬于一個(gè)進(jìn)程組,kill掉進(jìn)程組就可殺死主進(jìn)程的關(guān)聯(lián)子進(jìn)程。
# ??注意,使用【-】來指定kill的是進(jìn)程組?? kill -TERM -659
2.3.2 不使用() 或者 使用{}
不使用()
apluser@FengYeHong-HP:0727$ cat my_script_no_child_process.sh
echo "No,姓名,auid,地址"
seq 1 40000000 | awk 'BEGIN{OFS=","} {
printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1
}' > bigfile.csv
sleep 10
echo "執(zhí)行完成"
apluser@FengYeHong-HP:0727$ bash my_script_no_child_process.sh &
[1] 687
- 可以看到,只有一個(gè)線程存在
apluser@FengYeHong-HP:0727$ ps -ef | grep -a "[m]y_script_no_child_process.sh" apluser 687 517 0 16:21 pts/0 00:00:00 bash my_script_no_child_process.sh
使用{}
apluser@FengYeHong-HP:0727$ cat my_script_no_child_process.sh
{
echo "No,姓名,auid,地址";
seq 1 40000000 | awk 'BEGIN{OFS=","} {
printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1
}'
} > bigfile.csv
sleep 10
echo "執(zhí)行完成"
apluser@FengYeHong-HP:0727$ bash my_script_no_child_process.sh &
[1] 702
- 可以看到,只有一個(gè)線程存在
apluser@FengYeHong-HP:0727$ ps -ef | grep -a "[m]y_script_no_child_process.sh" apluser 702 517 0 16:33 pts/0 00:00:00 bash my_script_no_child_process.sh
2.3.3 使用setsid啟動(dòng)新會(huì)話
通過bash my_script_child_process.sh &啟動(dòng)的腳本,其中的子進(jìn)程和父進(jìn)程有可能不在同一個(gè)進(jìn)程組里面,可通過setsid解決該問題。
setsid 的作用:
- 啟動(dòng)一個(gè)新進(jìn)程,并創(chuàng)建新的會(huì)話(SID)和新的進(jìn)程組(PGID),新進(jìn)程成為這個(gè)會(huì)話的首進(jìn)程(session leader)。
- 然后這個(gè)新進(jìn)程(比如 PID 776)執(zhí)行
bash my_script_child_process.sh,這就成為了腳本的頂層的bash進(jìn)程。 - 所有其fork 出來的子進(jìn)程(包括 seq、awk 等),默認(rèn)都會(huì)繼承這個(gè) PGID 和 SID,除非子進(jìn)程中自己調(diào)用了 setsid 或 setpgid 修改了所屬組/會(huì)話。
啟動(dòng)腳本
- 注意:啟動(dòng)腳本時(shí)出現(xiàn)的808進(jìn)程號(hào)是
setsid命令本身的進(jìn)程號(hào) - 808進(jìn)程號(hào)并不是
my_script_child_process.sh腳本的進(jìn)程號(hào)
apluser@FengYeHong-HP:0727$ cat my_script_child_process.sh
(
echo "No,姓名,auid,地址"
seq 1 40000000 | awk 'BEGIN{OFS=","} {
printf "%d,user_name_%09d,auid_%09d,地球%d\n", $1, $1, $1, $1
}'
) > bigfile.csv
sleep 10
echo "執(zhí)行完成"
apluser@FengYeHong-HP:0727$ setsid nohup bash my_script_child_process.sh > /dev/null 2>&1 &
[1] 808
apluser@FengYeHong-HP:0727$
[1]+ Done setsid nohup bash my_script_child_process.sh > /dev/null 2>&1
apluser@FengYeHong-HP:0727$
查看my_script_child_process.sh腳本的進(jìn)程號(hào)
apluser@FengYeHong-HP:0727$ ps -ef | grep -a "[m]y_script_child_process.sh" apluser 809 516 0 17:03 ? 00:00:00 bash my_script_child_process.sh apluser 810 809 0 17:03 ? 00:00:00 bash my_script_child_process.sh
kill腳本進(jìn)程組前后的文件變化
# kill之前查看問價(jià)大小 apluser@FengYeHong-HP:0727$ ls -l bigfile.csv -rw-r--r-- 1 apluser apluser 352866326 Jul 27 17:03 bigfile.csv # kill進(jìn)程組 apluser@FengYeHong-HP:0727$ kill -TERM -809 # kill之后查看文件大小,沒有再發(fā)生變化 apluser@FengYeHong-HP:0727$ ls -l -rw-r--r-- 1 apluser apluser 692047894 Jul 27 17:03 bigfile.csv apluser@FengYeHong-HP:0727$ ls -l -rw-r--r-- 1 apluser apluser 692047894 Jul 27 17:03 bigfile.csv
三. kill的相關(guān)知識(shí)
3.1kill -TERM -113和kill -TERM 113的不同之處
kill -TERM 113
只對(duì) 一個(gè)進(jìn)程(PID = 113)發(fā)出終止信號(hào)。
它不會(huì)影響這個(gè)進(jìn)程的任何子進(jìn)程,除非你手動(dòng)對(duì)每個(gè)子進(jìn)程都發(fā)送信號(hào)。
這是最常用、最基本的 kill 形式。
kill -TERM -113
前面帶了 -,表示你要?dú)⒌氖?進(jìn)程組(process group)。
所以這個(gè)命令會(huì)向 進(jìn)程組 ID 為 113 的所有進(jìn)程(包括前臺(tái)/后臺(tái)作業(yè)中的多個(gè)子進(jìn)程)發(fā)送 SIGTERM。
| 命令 | 意思 |
|---|---|
| kill -TERM 113 | 向 PID 為 113 的單個(gè)進(jìn)程發(fā)送 SIGTERM |
| kill -TERM -113 | 向 進(jìn)程組 ID 為 113 的整個(gè)進(jìn)程組發(fā)送 SIGTERM |
3.2kill -TERM -113和kill -9 -113的區(qū)別
kill -TERM -113:給整個(gè)進(jìn)程組發(fā)送終止請(qǐng)求(溫和)
這樣可以讓進(jìn)程有機(jī)會(huì)做清理工作(比如關(guān)閉文件、釋放資源)
kill -9 -113:給整個(gè)進(jìn)程組發(fā)送立即終止(粗暴),發(fā)出的是 SIGKILL,無法被捕獲或忽略,進(jìn)程會(huì)被直接殺死,可能導(dǎo)致:
- 文件寫到一半
- 臨時(shí)資源未釋放
- 數(shù)據(jù)庫等狀態(tài)不一致
| 命令 | 信號(hào)類型 | 行為 | 可被攔截或清理? |
|---|---|---|---|
| kill -TERM -113 | SIGTERM (15) | 請(qǐng)求正常終止整個(gè)進(jìn)程組 | ? 是的 |
| kill -9 -113 | SIGKILL (9) | 強(qiáng)制立即終止整個(gè)進(jìn)程組 | ? 否 |
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Apache James配置連接達(dá)夢(mèng)數(shù)據(jù)庫的步驟
本文介紹了如何配置Apache James郵件服務(wù)器以連接達(dá)夢(mèng)數(shù)據(jù)庫,包括導(dǎo)入JDBC驅(qū)動(dòng)、修改配置文件和SQL語句,并提供了解決啟動(dòng)報(bào)錯(cuò)的方法2024-09-09
Linux 基于CentOS的LNMP 服務(wù)器部署標(biāo)準(zhǔn) 新手簡明版
Linux 基于CentOS的LNMP 服務(wù)器部署標(biāo)準(zhǔn) 新手簡明版,需要配置centos服務(wù)器的朋友可以參考下。2011-01-01
Centos7如何升級(jí)openssl和openssh最新版
這篇文章主要介紹了Centos7如何升級(jí)openssl和openssh最新版的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
Linux系統(tǒng)中swap分區(qū)的設(shè)置與增加/刪除
我們都知道在安裝Linux系統(tǒng)時(shí)在分區(qū)時(shí)可以分配swap分區(qū),而系統(tǒng)安裝后(在運(yùn)行中)如何建立或調(diào)整swap分區(qū)呢?下面這篇文章主要給大家介紹了關(guān)于Linux系統(tǒng)中swap分區(qū)的設(shè)置與增加/刪除的相關(guān)資料,需要的朋友可以參考下2018-07-07
apache負(fù)載均衡的安裝和實(shí)現(xiàn)方法
在負(fù)載均衡技術(shù)中,硬件設(shè)備是比較昂貴的,對(duì)于負(fù)載均衡的學(xué)習(xí)者如果不是在企業(yè)中應(yīng)用或者是學(xué)員中學(xué)習(xí),很少有機(jī)會(huì)能碰到實(shí)際操作的訓(xùn)練。所以,很多朋友都會(huì)選擇軟件方面的設(shè)置進(jìn)行研究?,F(xiàn)在我們就來介紹一下再Apache下的Tomcat負(fù)載均衡的一些使用問題2012-10-10
如何解決Linux下Too many open files問題
Too many open files是Linux系統(tǒng)中常見的錯(cuò)誤,從字面意思上看就是說程序打開的文件數(shù)過多,不過這里的files不單是文件的意思,也包括打開的通訊鏈接(比如socket),正在監(jiān)聽的端口等等,所以有時(shí)候也可以叫做句柄(handle),這個(gè)錯(cuò)誤通常也可以叫做句柄數(shù)超出系統(tǒng)限制。2021-06-06
Linux主機(jī)登錄abrt-cli status timed out的問題及解決
這篇文章主要介紹了Linux主機(jī)登錄abrt-cli status timed out的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
tomcat服務(wù)器如何配置字符集為utf-8徹底解決中文亂碼的問題詳解
這篇文章主要給大家介紹了關(guān)于tomcat服務(wù)器如何配置字符集為utf-8徹底解決中文亂碼問題的相關(guān)資料,文中先對(duì)字符集進(jìn)行了簡單的介紹,然后給大家詳細(xì)介紹了解決的方法,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
解決-BASH: /HOME/JAVA/JDK1.8.0_221/BIN/JAVA: 權(quán)限不夠問題
這篇文章主要介紹了解決-BASH: /HOME/JAVA/JDK1.8.0_221/BIN/JAVA: 權(quán)限不夠的問題,需要的朋友可以參考下2019-09-09

