shell直接退出后 后台進程關閉的原因和對處


在linux上進行測試時發現啟動后台進程后,如果使用exit退出登錄shell,shell退出后后台進程還是能夠正常運行但如果直接關閉登陸的窗口(如直接關掉xshell),那后台進程就會一起終了。都是退出登錄為什么前者后台進程會退出,而后者不會退出呢?

在查看bash的manual時發現有如下一段描述:

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP.

由此可以知道后台進程退出是由於登陸shell收到了SIGHUP信號后在退出前將SIGHUP轉發給所有的作業(jobs)。jobs由於收到SIGHUP而終止運行。

那能不能通過設置,在窗口異常關閉時保持后台進程繼續運行呢?

答案是肯定的,一般有如下4種方法:

(在此聲明,推薦使用exit退出,以下方法不一定管用,網上找的方法,未測試;第一種方法可能對一些進程有效,一些無效吧,至少我測試過,elasticsearch的kibana進程,nohup是無法阻止SIGHUP信號的)

1. 使用nohup運行命令

# nohup ./back.sh &
# nohup ./fore.sh
^Z
[2]+  Stopped                 nohup ./fore.sh
# jobs 
[1]-  Running                 nohup ./back.sh &
[2]+  Stopped                 nohup ./fore.sh
# ps -o pid,ppid,pgid,sid,cmd
  PID  PPID  PGID   SID CMD
 4766  4716  4766  4716 /bin/bash ./back.sh
 4769  4716  4769  4716 /bin/bash ./fore.sh
# fg
nohup ./fore.sh

### 關閉窗口並重新登錄 ###

# ps -eo pid,paid,pgid,sid,cmd |grep -E "back|fore"
 4766     1  4766  4716 /bin/bash ./back.sh
 4769     1  4769  4716 /bin/bash ./fore.sh

發現重新登錄后前台和后台進程都還運行着但父進程變成了init。

值得注意的是nohup會在當前目錄下產生一個nohup.out文件,並把實際命令的標准輸出和標准錯誤重定向為nohup.out

 

2. 使用setsid運行命令

# setsid ./back.sh &
# setsid ./fore.sh
# jobs 
# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 4871     1  4871  4871 /bin/bash ./back.sh
 4874     1  4874  4874 /bin/bash ./fore.sh

### 關閉窗口並重新登錄 ###

# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 4871     1  4871  4871 /bin/bash ./back.sh
 4874     1  4874  4874 /bin/bash ./fore.sh

可以發現在使用setsid后,不能在當前登錄shell的jobs中找到back.sh和fore.sh。並且由於在退出前back.sh和fore.sh的父進程已經是init,重新登錄后back.sh和fore.sh沒有發生任何改變。

 

3. 使用disown命令

# ./fore.sh
^Z
[2]+  Stopped 
# jobs 
[1]-  Running                 ./back.sh &
[2]+  Stopped                 ./fore.sh
# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 5395  5361  5395  5361 /bin/bash ./back.sh
 5396  5361  5396  5361 /bin/bash ./fore.sh
# disown -h %2
# disown -a %1
# jobs 
[2]+  Stopped                 ./fore.sh
# fg
./fore.sh

### 關閉窗口並重新登錄 ###

# ps -eo pid,ppid,pgid,sid,cmd |grep -E "back|fore"
 5395  5361  5395  5361 /bin/bash ./back.sh

重新登錄后發現fore.sh還是被終止了,並且經過調查發現終了的原因是收到了SIGHUP信號。由此可見disown僅對后台進程起作用。

 

4.  Catch SIGHUP信號

如果是shell腳本,則在腳本中加上下面的一條語句就行了。

# trap "" HUP

如果是C程序,則使用signal函數對SIGHUP進行屏蔽就行了。

signal(SIGHUP, SIG_IGN);

 

X. 當然相反的我們也可以讓shell在exit退出時發送SIGHUP給所有的jobs,具體設置如下:

# shopt -s huponexit

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM