Linux :忘記使用nohup該如何補救


Linux :忘記使用nohup該如何補救

0x00 摘要

在Linux做開發的同學也許會遇到這種困境:

  1. 運行了一個程序兩個小時之后,你心想:再有一個小時程序就運行完了,於是你興致勃勃的准備看結果。
  2. 女朋友突然發飆讓自己立刻出現。
  3. 此時你突然發現自己沒有使用 nohup,這就意味着這個程序在自己離開之后會死掉。之前兩個小時的運行時間就浪費了。
  4. 於是你滿懷悔恨的按下了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 操作序列

具體操作序列如下:

  1. 對於正在運行的進程,我們可以使用 ”CTRL+ z“ 來將當前進程掛起到后台暫停運行;
  2. 這時候進程已經進入后台暫停,我們使用 "jobs" 找到之前暫停的進程,每一個后台任務具有一個 jobnumber(任務的序列號,非PID)。
  3. 使用 "bg jobnumber" 讓該進程進入后台運行;
  4. 再次使用 "jobs"查看進程狀態,此時進程已經進入running 狀態;
  5. 使用disown命令 "disown -h %jobnumber" 進行處理,這樣該進程就會起到了 nohup 的同樣作用;此時大功告成。
  6. 如果想繼續查看,可以使用 ps 命令來查看進程狀態;
  7. 可以使用 "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后台任務提交,前后台任務轉換隨便玩

Linux的jobs命令

Linux jobs命令:查看當前終端放入后台的工作

Linux 守護進程的啟動方法

Linux中shell關閉后,nohup讓程序依然在后台運行

nohup:關閉shell程序依然執行


免責聲明!

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



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