Linux下使命令不受終端斷開的影響,保持在后台運行的幾種方法及原理


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

記錄一下Linux下使命令不受終端斷開的影響,保持在后台運行的幾個方法及其原理。當用戶注銷logout或者網絡中斷時,終端會受到HUP(hangup)信號從而關閉其所有子進程。因為解決方法大體有兩種:要么讓進程忽略HUP信號,要么讓進程運行在新的會話里從而成為不屬於此終端下的子進程。

1(本地單元測試通過)nohup命令可以讓要執行的命令忽略HUP信號,再加上&可以保證命令一直在后台運行。

例:nohup commandXXX > test.log 2>&1 &

命令解析:

  • nohup可以讓commandXXX這個命令忽略HUP信號;
  • 第一個>代表將命令的標准輸出重定向到指定的地方,這里是test.log
  • 2>&1代表重定向標准錯誤重定向到標准輸出,這里標准輸出已經被重定向到test.log,所以標准錯誤也會輸出到test.log。這里引申一下:

Linux中標准輸入即STDIN , 在/dev/stdin ,一般指鍵盤輸入, shell里代號是0;

Linux中標准輸出STDOUT, 在/dev/stdout,一般指終端(terminal), 就是顯示器, shell里代號是1;

Linux中標准錯誤STDERR,在/dev/stderr也是指終端(terminal),不同的是,錯誤信息送到這里 shell里代號是2

  • 最后一個&表示讓命令在后台運行
  • 關閉終端后可以通過ps -ef|grep commandXXX命令查找到后台進程。

2(本地單元測試通過)setsid命令可以讓進行運行在新的會話下,即不屬於當前終端的子進程。那么即使當前終端發出了HUP信號,也不會影響該進程。

例:setsid commandXXX

其實通過觀察進程中的父進程號(PPID)發現一些端倪,使用setsid后進行的PPID為1(即為init進程ID),並非當前終端的進程ID。

3(本地單元測試通過)將一個或多個命令用()括起來在shell中運行,所提交的作業並不在作業列表中,即無法通過jobs查看到。新提交的進程的PPID為1。

例:(commandXXX)

4(本地單元測試通過)若未加上述任何處理就執行了命令,如何補救才能讓其不受HUP信息的影響呢?答案是作業調度。對於某個已執行的命令,經過以下幾個步驟可以讓其忽略HUP信號:

  • 先使用ctrl+z命令將正在執行的命令變為job作業,; 
  • 使用jobs可以查看到具體的作業號(jobid);
  • 再用bg %jobid命令讓其在后台運行;
  • 最后使用disown -h jobid 即可使該作業忽略HUP信號

5(未安裝此命令,暫未驗證)有大量這種需要穩定的在后台運行的命令時,如何避免對每條命令都做上述的重復操作呢?答案是screen。screen提供了ANSI/VT100的終端模擬器,能夠在一個真實終端下運行多個全屏的偽終端。screen具有很多參數,功能強大,在此僅簡要分析一下為什么使用screen可以避免HUP信號的影響:

  • screen -dnS session new 建立一個處於斷開模式下的會話(並指定其會話名);
  • screen -list 列出所有會話;
  • screen -r session name 重新連接指定會話;
  • ctrl -a D暫時斷開當前會話;

當我們用-r連接到screen會話時,就進入了一個偽終端,不會再受到HUP信號的影響了。

其他命令:

  • pstree -H pid 查看進程號對應的進程命令的樹形結構
  • fg %jobid 將某個掛起的進程放回前台
  • bg %jobid 將某個掛起的進程調到后台繼續運行,這一點在調試代碼時尤其有用,因為將代碼編輯器掛起到后台再重新返回時,光標定位仍停留到上次掛起時的位置,避免了重新地凝望的麻煩。
  • ctrl +c 止當前命令
  • jobs -l 列出所有任務的pid,jobs的狀態可以是running/stopped/terminated,但若任務終止了(kill),shell會從當前列表中刪除任務的進程標識。


免責聲明!

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



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