問題描述:當SSH遠程連接到服務器上,然后運行一個服務 ./.sh start,然后把終端開閉(切斷SSH連接)之后,發現該服務中斷,導致網頁無法訪問。
解決方法:使用nohup命令讓程序在關閉窗口(切換SSH連接)的時候程序還能繼續在后臺運行。
Unix/Linux下一般比如想讓某個程序在后臺運行,很多都是使用& 在程序結尾來讓程序自動運行。比如我們要運行mysql在后臺:
/usr/local/mysql/bin/ --user=mysql &
但是加入我們很多程序并不象一樣做成守護進程,可能我們的程序只是普通程序而已,一般這種程序使用& 結尾,但是如果終端關閉,那么程序也會被關閉。但是為了能夠后臺運行,那么我們就可以使用nohup這個命令,比如我們有個test.php需要在后臺運行,并且希望在后臺能夠定期運行linux下添加自動重啟程序,那么就使用nohup:
nohup /root/test.php &
提示:
[~]$ to nohup.out
嗯,證明運行成功,同時把程序運行的輸出信息放到當前目錄的nohup.out 文件中去。
nohup命令說明:
用途:不掛斷地運行命令。
語法:nohup [ Arg ... ] [& ]
描述:nohup 命令運行由 參數和任何相關的 Arg 參數指定的命令,忽略所有掛斷()信號。在注銷后使用 nohup 命令運行后臺中的程序。要運行后臺中的 nohup 命令,添加 & ( 表示“and”的符號)到命令的尾部。
無論是否將 nohup 命令的輸出重定向到終端,輸出都將附加到當前目錄的 nohup.out 文件中。如果當前目錄的 nohup.out 文件不可寫,輸出重定向到 $HOME/nohup.out 文件中。如果沒有文件能創建或打開以用于追加,那么 參數指定的命令不可調用。如果標準錯誤是一個終端,那么把指定的命令寫給標準錯誤的所有輸出作為標準輸出重定向到相同的文件描述符。
退出狀態:該命令返回下列出口值:
126 可以查找但不能調用 參數指定的命令。
127 nohup 命令發生錯誤或不能查找由 參數指定的命令。
否則,nohup 命令的退出狀態是 參數指定命令的退出狀態。
nohup命令及其輸出文件
nohup命令:如果你正在運行一個進程,而且你覺得在退出帳戶時該進程還不會結束,那么可以使用nohup命令。該命令可以在你退出帳戶/關閉終端之后繼續運行相應的進程。nohup就是不掛起的意思( n ohang up)。
該命令的一般形式為:nohup &
使用nohup命令提交作業
如果使用nohup命令提交作業,那么在缺省情況下該作業的所有輸出都被重定向到一個名為nohup.out的文件中,除非另外指定了輸出文件:(也就是說自定義輸出的文件名)
nohup > myout.file 2>&1 &
在上面的例子中,輸出被重定向到myout.file文件中。
使用 jobs 查看任務。
使用 fg %n關閉。
另外有兩個常用的ftp工具和,可以實現后臺的ftp上傳和下載,這樣我就可以利用這些命令在后臺上傳和下載文件了。
思考:問題1為什么ssh一關閉,程序就不再運行了?
元兇: 信號
讓我們來看看為什么關掉窗口/斷開連接會使得正在運行的程序死掉。
在Linux/Unix中,有這樣幾個概念:
進程組( group):一個或多個進程的集合,每一個進程組有唯一一個進程組ID,即進程組長進程的ID。
會話期():一個或多個進程組的集合,有唯一一個會話期首進程( )。會話期ID為首進程的ID。
會話期可以有一個單獨的控制終端( )。與控制終端連接的會話期首進程叫做控制進程( )。當前與終端交互的進程稱為前臺進程組。其余進程組稱為后臺進程組。
根據POSIX.1定義:
掛斷信號()默認的動作是終止程序。
當終端接口檢測到網絡連接斷開,將掛斷信號發送給控制進程(會話期首進程)。
如果會話期首進程終止linux下添加自動重啟程序,則該信號發送到該會話期前臺進程組。
一個進程退出導致一個孤兒進程組中產生時,如果任意一個孤兒進程組進程處于STOP狀態,發送和信號到該進程組中所有進程。(關于孤兒進程參照: )
結論:因此當網絡斷開或終端窗口關閉后,也就是SSH斷開以后,控制進程收到信號退出,會導致該會話期內其他進程退出。
簡而言之:就是ssh 打開以后,bash等都是他的子程序,一旦ssh關閉,系統將所有相關進程殺掉!! 導致一旦ssh關閉,執行中的任務就取消了
例子:
我們來看一個例子。打開兩個SSH終端窗口,在其中一個運行top命令。
[root@ root]# top
在另一個終端窗口,找到top的進程ID為5180,其父進程ID為5128,即登錄shell。
[root@ root]# ps -ef|grep top
root 5180 5128 0 01:03 pts/0 00:00:02 top
root 5857 3672 0 01:12 pts/2 00:00:00 grep top
使用命令可以更清楚地看到這個關系:
[root@ root]# -H 5180|grep top
|-sshd-+-sshd---bash---top
使用ps-xj命令可以看到,登錄shell(PID 5128)和top在同一個會話期,shell為會話期首進程,所在進程組PGID為5128,top所在進程組PGID為5180,為前臺進程組。
[root@ root]# ps -xj|grep 5128
5 5128 pts/0 5180 S 0 0:00 -bash
5 5128 pts/0 5180 S 0 0:50 top
3672 18095 18094 3672 pts/2 18094 S 0 0:00 grep 5128
關閉第一個SSH窗口,在另一個窗口中可以看到top也被殺掉了。
[root@ root]# ps -ef|grep 5128
root 18699 3672 0 04:35 pts/2 00:00:00 grep 5128
問題2 為什么守護程序就算ssh 打開的,就算關閉ssh也不會影響其運行?
因為他們的程序特殊,比如httpd –k start運行這個以后,他不屬于sshd這個進程組 而是單獨的進程組,所以就算關閉了ssh,和他也沒有任何關系!
[root@-4 ~]# |grep http