1. 程式人生 > >nohup 讓進程在後臺可靠運行的幾種方法

nohup 讓進程在後臺可靠運行的幾種方法

AR 列表 進程 opp ron bsp HA 環境 per

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 關閉。

當你成功地提交進程以後,就會顯示出一個進程號,可以用它來監控該進程,或殺死它。(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結合就代表標準輸出了,就變成錯誤重定向到標準輸出.

退出任務
如果運行的任務在當前 shell 終端,可以通過 jobs 命令查詢相關信息,並且殺掉進程。

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


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

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

如果非當前 shell 終端,可以通過 ps auxf | grep ‘xxxxx‘ 獲取 pid 然後 kill pid。

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 來暫時斷開當前會話。

REF:

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

nohup 讓進程在後臺可靠運行的幾種方法