nohup 讓進程在后台可靠運行的幾種方法


1. nohup

nohup 無疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 信號。

nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標准輸出和標准錯誤缺省會被重定向到 nohup.out 文件中。一般我們可在結尾加上"&"來將命令同時放入后台運行,也可用">filename 2>&1"來更改缺省的重定向文件名。

nohup 示例
[root@~]# nohup ping www.ibm.com &
[1] 3059
nohup: appending output to `nohup.out'
[root@~]# ps -ef |grep 3059
root      3059   984  0 21:06 pts/3    00:00:00 ping www.ibm.com
root      3067   984  0 21:06 pts/3    00:00:00 grep 3059
[root@~]#

該命令的一般形式為:nohup command &

如果使用nohup命令提交作業,那么在缺省情況下該作業的所有輸出都被重定向到一個名為nohup.out的文件中,除非另外指定了輸出文件:

nohup command > myout.file 2>&1 &

在上面的例子中,輸出被重定向到myout.file文件中。

使用 jobs 查看任務。

使用 fg %n 關閉,n為任務號。

 
當你成功地提交進程以后,就會顯示出一個進程號,可以用它來監控該進程,或殺死它。(ps -ef | grep 進程號 或者 kill -9 進程號)

使用了nohup之后,很多人就這樣不管了,其實這樣有可能在當前賬戶非正常退出或者結束的時候,命令還是自己結束了。
所以在 使用nohup命令后台運行命令之后,需要使用exit正常退出當前賬戶,這樣才能保證命令一直在后台運行。

    ctrl + z
    可以將一個正在前台執行的命令放到后台,並且處於暫停狀態。

    Ctrl+c
    終止前台命令。

    jobs
    查看當前有多少在后台運行的命令。
    jobs -l 選項可顯示所有任務的PID, jobs的狀態可以是running, stopped, Terminated。但是如果任務被終止了(kill),shell 從當前的shell環境已知的列表中刪除任務的進程標識。
    2>&1解析

command >out.file 2>&1 &
    command>out.file是將command的輸出重定向到out.file文件,即輸出內容不打印到屏幕上,而是輸出到out.file文件中。
    2>&1 是將標准出錯重定向到標准輸出,這里的標准輸出已經重定向到了out.file文件,即將標准出錯也輸出到out.file文件中。最后一個&, 是讓該命令在后台執行。
    試想2>1代表什么,2與>結合代表錯誤重定向,而1則代表錯誤重定向到一個文件1,而不代表標准輸出;換成2>&1,&與1結合就代表標准輸出了,就變成錯誤重定向到標准輸出.

注意:如果退出了啟動nohup的那個窗口,或者,在其他窗口,無法使用jobs來查看運行中的命令。此時,可以用下面的命令查看:
top -U username
ps auxw
ps x
 
 
退出任務
如果運行的任務在當前 shell 終端,可以通過 jobs 命令查詢相關信息,並且殺掉進程。

# 查看當前 shell 終端的后台運行任務進程信息
$ jobs
[ 1]+ Running nohup java -jar adapter-minisite.jar /tomcat-1 /tomcat-2 > logs.txt 2>&1 &
# 殺掉任務號, kill %后面是任務號1
$ kill %1


# 找到 pid
$ jobs -l
[1]+ 11076  
$ kill 11076

#  
$ fg %n # 置為前端運行,n為任務號
Ctrl + c # 退出

如果非當前 shell 終端,可以通過 ps auxf | grep 'xxxxx' 獲取 pid 然后 kill pid。xxxxx 表示nohup后邊的命令。
 
When using nohup and you put the task in the background, the background operator ( &) will give you the PID at the command prompt. If your plan is to manually manage the process, you can save that PID and use it later to kill the process if needed, via kill PID or kill -9 PID (if you need to force kill).
Alternatively, you can find the PID later on by ps -ef | grep "command name" and locate the PID from there. Note that nohup keyword/command itself does not appear in the ps output for the command in question.
 

2. setsid

nohup 無疑能通過忽略 HUP 信號來使我們的進程避免中途被中斷,但如果我們換個角度思考,如果我們的進程不屬於接受 HUP 信號的終端的子進程,那么自然也就不會受到 HUP 信號的影響了。
setsid 的使用也是非常方便的,也只需在要處理的命令前加上 setsid 即可。
setsid 示例
[root@~]# setsid ping www.ibm.com
[root@~]# ps -ef |grep www.ibm.com
root     31094     1  0 07:28 ?        00:00:00 ping www.ibm.com
root     31102 29217  0 07:29 pts/4    00:00:00 grep www.ibm.com
 

3. &

這里還有一個關於 subshell 的小技巧。我們知道,將一個或多個命名包含在“()”中就能讓這些命令在子 shell 中運行中,從而擴展出很多有趣的功能,我們現在要討論的就是其中之一。

當我們將"&"也放入“()”內之后,我們就會發現所提交的作業並不在作業列表中,也就是說,是無法通過jobs來查看的。讓我們來看看為什么這樣就能躲過 HUP 信號的影響吧。

subshell 示例
[root@~]# (ping www.ibm.com &)
[root@~]# ps -ef |grep www.ibm.com
root     16270     1  0 14:13 pts/4    00:00:00 ping www.ibm.com
root     16278 15362  0 14:13 pts/4    00:00:00 grep www.ibm.com

4. disown

場景:

我們已經知道,如果事先在命令前加上 nohup 或者 setsid 就可以避免 HUP 信號的影響。但是如果我們未加任何處理就已經提交了命令,該如何補救才能讓它避免 HUP 信號的影響呢?

解決方法:

這時想加 nohup 或者 setsid 已經為時已晚,只能通過作業調度和 disown 來解決這個問題了。
  • disown -h jobspec來使某個作業忽略HUP信號。
  • disown -ah 來使所有的作業都忽略HUP信號。
  • disown -rh 來使正在運行的作業忽略HUP信號。

需要注意的是,當使用過 disown 之后,會將把目標作業從作業列表中移除,我們將不能再使用jobs來查看它,但是依然能夠用ps -ef查找到它。

但是還有一個問題,這種方法的操作對象是作業,如果我們在運行命令時在結尾加了"&"來使它成為一個作業並在后台運行,那么就萬事大吉了,我們可以通過jobs命令來得到所有作業的列表。但是如果並沒有把當前命令作為作業來運行,如何才能得到它的作業號呢?答案就是用 CTRL-z(按住Ctrl鍵的同時按住z鍵)了!

CTRL-z 的用途就是將當前進程掛起(Suspend),然后我們就可以用jobs命令來查詢它的作業號,再用bg jobspec來將它放入后台並繼續運行。需要注意的是,如果掛起會影響當前進程的運行結果,請慎用此方法。

 

5. screen

場景:

我們已經知道了如何讓進程免受 HUP 信號的影響,但是如果有大量這種命令需要在穩定的后台里運行,如何避免對每條命令都做這樣的操作呢?

解決方法:

此時最方便的方法就是 screen 了。簡單的說,screen 提供了 ANSI/VT100 的終端模擬器,使它能夠在一個真實終端下運行多個全屏的偽終端。screen 的參數很多,具有很強大的功能,我們在此僅介紹其常用功能以及簡要分析一下為什么使用 screen 能夠避免 HUP 信號的影響。

 

使用 screen 很方便,有以下幾個常用選項:

  • screen -dmS session name來建立一個處於斷開模式下的會話(並指定其會話名)。
  • screen -list 來列出所有會話。
  • screen -r session name來重新連接指定會話。
  • 用快捷鍵CTRL-a d 來暫時斷開當前會話。

 Screen 詳細使用說明:

https://www.cnblogs.com/emanlee/p/3424635.html

 

REF:

https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/

 

 
   


免責聲明!

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



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