我們經常會碰到這樣的問題,用 telnet/ssh 登錄了遠程的 Linux 服務器,運行了一些耗時較長的任務, 結果卻由於網絡的不穩定導致任務中途失敗。如何讓命令提交后不受本地關閉終端窗口/網絡斷開連接的干擾呢?下面舉了一些例子, 您可以針對不同的場景選擇不同的方式來處理這個問題。
先介紹一下hangup 名稱的來由
在 Unix 的早期版本中,每個終端都會通過 modem 和系統通訊。當用戶 logout 時,modem 就會掛斷(hang up)電話。 同理,當 modem 斷開連接時,就會給終端發送 hangup 信號來通知其關閉所有子進程。
nohup/setsid/&
場景:
如果只是臨時有一個命令需要長時間運行,什么方法能最簡便的保證它在后台穩定運行呢?
解決方法:
我們知道,當用戶注銷(logout)或者網絡斷開時,終端會收到 HUP(hangup)信號從而關閉其所有子進程。因此,我們的解決辦法就有兩種途徑:要么讓進程忽略 HUP 信號,要么讓進程運行在新的會話里從而成為不屬於此終端的子進程。
1、nohup的使用
nohup 無疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 信號。
nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標准輸出和標准錯誤缺省會被重定向到 nohup.out 文件中。一般我們可在結尾加上"&"來將命令同時放入后台運行,也可用">filename 2>&1"
來更改缺省的重定向文件名。
nohup 示例
nohup ping baidu.com &
2。setsid
nohup 無疑能通過忽略 HUP 信號來使我們的進程避免中途被中斷,但如果我們換個角度思考,如果我們的進程不屬於接受 HUP 信號的終端的子進程,那么自然也就不會受到 HUP 信號的影響了。setsid 就能幫助我們做到這一點。讓我們先來看一下 setsid 的幫助信息
setsid 示例setsid ping baidu.com
screen
場景:
我們已經知道了如何讓進程免受 HUP 信號的影響,但是如果有大量這種命令需要在穩定的后台里運行,如何避免對每條命令都做這樣的操作呢?
解決方法:
此時最方便的方法就是 screen 了。簡單的說,screen 提供了 ANSI/VT100 的終端模擬器,使它能夠在一個真實終端下運行多個全屏的偽終端。screen 的參數很多,具有很強大的功能,我們在此僅介紹其常用功能以及簡要分析一下為什么使用 screen 能夠避免 HUP 信號的影響。
使用 screen 很方便,有以下幾個常用選項:
screen -S yourname -> 新建一個叫yourname的session
screen -ls -> 列出當前所有的session
screen -r yourname -> 回到yourname這個session
screen -d yourname -> 遠程detach某個session
screen -d -r yourname -> 結束當前session並回到yourname這個session
Screen中止某個會話(session)
screen
-S some_name -X quit
screen 示例
1.新建一個叫yourname的終端
screen -S newname
2.可運行要執行的命令
ping baidu.com
3.C-a d -> detach,暫時離開當前session,將目前的 screen session (可能含有多個 windows) 丟到后台執行,並會回到還沒進 screen 時的狀態,此時在 screen session 里,每個 window 內運行的 process (無論是前台/后台)都在繼續執行,即使 logout 也不影響。