Linux :忘記使用nohup該如何補救
0x00 摘要
在Linux做開發的同學也許會遇到這種困境:
- 執行了一個程式兩個小時之後,你心想:再有一個小時程式就執行完了,於是你興致勃勃的準備看結果。
- 女朋友突然發飆讓自己立刻出現。
- 此時你突然發現自己沒有使用 nohup,這就意味著這個程式在自己離開之後會死掉。之前兩個小時的執行時間就浪費了。
- 於是你滿懷悔恨的按下了CTR+c,然後使用 nohup 重新執行程式。
慢著,其實這種忘記 nohup 的情況是可以補救的,下面我們就看看如何操作。
0x01 問題描述
1.1 為何關閉程式
當使用者登出(logout)或者網路斷開時,終端會收到 HUP(hangup)訊號從而關閉其所有子程式。
原因是:SSH會話關閉時,ssh所關聯的pty關閉,系統會給這個pty所關聯的session中的所有程式傳送SIGHUP訊號,SIGHUP的預設訊號處理程式是終止程式,除非程式自己處理了SIGHUP。
因此,我們的解決辦法就有兩種途徑:
- 要麼讓程式忽略 HUP 訊號;
- 要麼讓程式執行在新的會話裡從而成為不屬於此終端的子程式;
1.2 nohup 作用
nohup
命令對程式做了三件事。
- 阻止
SIGHUP
訊號發到這個程式。- 關閉標準輸入。該程式不再能夠接收任何輸入,即使執行在前臺。
- 重定向標準輸出和標準錯誤到檔案
nohup.out
。
也就是說,nohup
命令實際上將子程式與它所在的 session 分離了。所以當shell視窗關閉時候,nohup 命令所在的程式也不會被結束。
0x02 簡述
如果忘記使用了 nohup,該如何補救?具體操作如下:
2.1 操作序列
具體操作序列如下:
- 對於正在執行的程式,我們可以使用 ”CTRL+ z“ 來將當前程式掛起到後臺暫停執行;
- 這時候程式已經進入後臺暫停,我們使用 "jobs" 找到之前暫停的程式,每一個後臺任務具有一個 jobnumber(任務的序列號,非PID)。
- 使用 "bg jobnumber" 讓該程式進入後臺執行;
- 再次使用 "jobs"檢視程式狀態,此時程式已經進入running 狀態;
- 使用disown命令 "disown -h %jobnumber" 進行處理,這樣該程式就會起到了 nohup 的同樣作用;此時大功告成。
- 如果想繼續檢視,可以使用 ps 命令來檢視程式狀態;
- 可以使用 "fg" 把後臺任務轉成前臺任務執行,此時可以對該程式進行操作,比如結束;
2.2 樣例
我們以執行一個redis為例給出具體操作序列,具體如下圖:
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
mylinux $ bg 1
[1]+ redis-server &
mylinux $ jobs
[1]+ Running redis-server &
mylinux $ disown -h %1
mylinux $ ps -elf| grep redis
501 1987 521 4006 0 31 0 4289624 1932 - T 0 ttys001 0:00.01 redis-server *:6 9:49上午
mylinux $ fg
redis-server
^C1987:signal-handler (1616291836) Received SIGINT scheduling shutdown...
1987:M 21 Mar 09:57:16.634 # User requested shutdown...
1987:M 21 Mar 09:57:16.634 * Saving the final RDB snapshot before exiting.
1987:M 21 Mar 09:57:16.641 * DB saved on disk
1987:M 21 Mar 09:57:16.641 # Redis is now ready to exit, bye bye...
0x03 原理
下面我們對操作命令的原理一一進行分析。
3.1 CTRL + Z
Ctrl+Z是把當前的程式掛起,暫停執行這個程式。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
這樣程式就被掛起進入了後臺。可以掛起好多程式到後臺。
3.2 jobs
jobs命令用來檢視當前有多少在後臺執行。
在Linux中,啟動、停止、終止以及恢復作業的這些功能統稱為作業控制。作業控制中的關鍵命令是jobs命令,jobs命令允許檢視shell當前正在處理的作業。jobs命令中輸出有加號和減號,帶加號的作業被當做預設作業,帶減號的為下一個預設作業。
一旦當前的預設工作處理完成,則帶減號的工作就會自動成為新的預設工作,換句話說,不管此時有多少正在執行的工作,任何時間都會有且僅有一個帶加號的工作和一個帶減號的工作。
我們可以看到,此時 redis-server 就在後臺執行,[1] 表示程式編號為 1。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
3.3 bg
bg命令能夠將在後臺暫停的命令,變為在後臺進行繼續執行。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
mylinux $ bg 1
[1]+ redis-server &
使用了bg之後,可以看到輸出 redis-server 之後帶了一個 &,表示已經後臺執行。
我們也可以再次使用 jobs 檢視程式狀態。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
mylinux $ bg 1
[1]+ redis-server &
mylinux $ jobs
[1]+ Running redis-server &
3.4 disown
disown 命令 可以將指定任務從"後臺任務"列表(jobs
命令的返回結果)之中移除。一個"後臺任務"只要不在這個列表之中,session 就肯定不會向它發出SIGHUP
訊號。這樣就達到了 nohup 相同的作用。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
mylinux $ bg 1
[1]+ redis-server &
mylinux $ jobs
[1]+ Running redis-server &
mylinux $ disown -h %1
3.5 ps
當使用過 disown 之後,會將把目標作業從作業列表中移除,我們將不能再使用jobs
來檢視它,但是依然能夠用ps -ef
查詢到它。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
mylinux $ bg 1
[1]+ redis-server &
mylinux $ jobs
[1]+ Running redis-server &
mylinux $ disown -h %1
mylinux $ ps -elf| grep redis
501 1987 521 4006 0 31 0 4289624 1932 - T 0 ttys001 0:00.01 redis-server *:6 9:49上午
3.6 fg
fg 命令能夠將在後臺執行的命令調至前臺進行執行,如果後臺執行的任務數量比較多,可以通過選擇jobnumber(任務的序列號,非PID)來進行選擇。
另外關於當前任務,如果後臺執行的任務號有2個時候,當1號任務執行完畢之後,2號任務此時就為當前任務,那麼使用fg、bg等命令不加上job number的時候,預設為變動的都是當前任務。
mylinux $ redis-server
* The server is now ready to accept connections on port 6379
^Z
[1]+ Stopped redis-server
mylinux $ jobs
[1]+ Stopped redis-server
mylinux $ bg 1
[1]+ redis-server &
mylinux $ jobs
[1]+ Running redis-server &
mylinux $ disown -h %1
mylinux $ ps -elf| grep redis
501 1987 521 4006 0 31 0 4289624 1932 - T 0 ttys001 0:00.01 redis-server *:6 9:49上午
mylinux $ fg
redis-server
0xEE 個人資訊
★★★★★★關於生活和技術的思考★★★★★★
微信公眾賬號:羅西的思考
如果您想及時得到個人撰寫文章的訊息推送,或者想看看個人推薦的技術資料,敬請關注。
0xFF 參考
https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/
https://www.ibm.com/developerworks/cn/linux/l-cn-screen/
nohup命令_掌握這幾個命令,Linux後臺任務提交,前後臺任務轉換隨便玩