問題描述:
每次SSH到服務器上,然后運行了一個自己寫的服務端程序,比如 ./myserver.sh ,然后關閉ssh或者終端之后,發現服務不能訪問。
簡要分析下:
根據 這篇博文 的提示,ssh登錄后會新建一個會話,一個登陸shell發起的會話,一般由一個會話首進程、一個前台進程組、一個后台進程組組成。通常來說,會話首進程是一個登錄shell,比如bash。進程組是一個或多個進程的集合,進程組屬於一個會話。一般來說,一個進程組中的其它進程的父進程是進程組組長進程的ID,如果,這個進程組組長終止掉之后,這個進程組中其它進程會變成孤兒進程,這個進程組也就成了孤兒進程組。對於后台進程組來說,后台進程組中的進程可以向終端設備寫,但是當一個后台進程組中的進程嘗試讀終端設備的時候,會收到一個SIGTTIN信號,然后停止。當一個進程組成為孤兒進程組的時候,Bash無法知曉其PID,那么就無法將其放入前台,當其試圖讀終端設備的時候,read()調用將失敗,並將errno置為EIO。
總結下就是,ssh登錄后,bash都是其子進程,一旦會話終止,該會話期的所有相關的進程都會被殺死。包括后台進程。&是沒有用的。
解決方案:
那么怎么解決這個問題呢?使用nohup命令。nohup命令會忽略SIGTTIN信號,從而可以在會話結束之后還可以繼續運行。
比如上面的例子中,就可以使用:
nohup ./myserver.sh &
后面的&可以加也可以不用加,區別就是是否是后台。和掛斷沒有關系。
具體的使用方法在 http://zjking.blog.51cto.com/976858/1117828 這篇博客中有提到。
如果要在下次會話的時候還想恢復到上次會話終止前的狀態,比如說我用nmap掃描某個IP段,下次登錄進來要看到掃描結果。
我們可以使用screen命令。
1.使用screen進入到子界面中,然后nmap -A xxxxxxx 2.按 ctrl + a ,d 暫停子界面。這時會顯示[detached],並且回到父界面。 3.想干啥干啥去。 4.查看子界面狀態 screen -ls There is a screen on: 447.pts-1.free (Detached) 這里的447就是子界面的進程號。 5.回到子界面 screen -r 子界面pid 比如:screen -r 447 6.在子界面殺死子界面的辦法是先ctrl + a ,然后按k。 具體的使用辦法可以 screen -h