ssh關閉後仍保持當前運行的進程
症狀:使用SecureCRT工具ssh遠程連接linux,不退出ssh,而是強行關閉終端(合上筆記本走人)情況下,後台啟動的應用也會關閉。
測試案例:
很明顯的是關閉終端後,前台運行的程序會被隨之關閉,但是後台進程也會因為終端異常關閉而關掉,如下是一個簡單的測試結果:
1、後台執行程序,正常關閉ssh連接,關閉終端的情況:
開啟兩個終端,其中第一個在後台執行ping操作
ping google.com | tee log.txt &
在第二個終端觀察
tail -f log.txt 可以看到日志一直在寫
使用pstree命令可以看到ping的進程存在
|-sshd-+-sshd---sshd---bash---pstree
| `-sshd---sshd---bash-+-ping
| `-tee
Ctrl+D 退出第一個終端 然後關閉終端
第二個終端的日志仍然在寫,pstree命令:
|-ping
ps x
29427 ? S 0:00 ping google.com
看到ping的進程依然存在
2、後台執行程序,非正常關閉ssh連接(模擬突然掉電或者,未來得及退出ssh,或者ssh仍然連接,直接關閉終端SecureCRT)情況:
同樣開啟兩個終端,其中第一個在後台執行ping操作
ping google.com | tee log.txt &
在第二個終端觀察
tail -f log.txt 可以看到日志一直在寫
使用pstree命令可以看到ping的進程存在
|-sshd-+-sshd---sshd---bash---pstree
| `-sshd---sshd---bash-+-ping
| `-tee
在不退出ssh的情況下,強行關閉第一個終端(SecureCRT)
在第二個終端觀察
tail -f log.txt 可以看到日志已經停止寫。
使用pstree命令可以看到ping的進程被停掉
ps aux看不到ping的進程,說明強行關閉終端的情況下後台進程也別kill掉了
查了一下資料,這其中起關鍵的是 SIGHUP信號
查看所有的信號:
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1
36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5
40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5
60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1
64) SIGRTMAX
列表中,編號為1 ~ 31的信號為傳統UNIX支持的信號,是不可靠信號(非實時的),編號為32 ~ 63的信號是後來擴充的,稱做可靠信號(實時信號)。不可靠信號和可靠信號的區別在於前者不支持排隊,可能會造成信號丟失,而後者不會。
SIGHUP信號在用戶終端連接(正常或非正常)結束時發出, 通常是在終端的控制進程結束時, 通知同一session內的各個作業, 這時它們與控制終端不再關聯。
登錄Linux時,系統會分配給登錄用戶一個終端(Session)。在這個終端運行的所有程序,包括前台進程組和後台進程組,一般都屬於這個 Session。
當用戶退出Linux登錄時,前台進程組和後台有對終端輸出的進程將會收到SIGHUP信號。這個信號的默認操作為終止進程,因此前台進程組和後台有終端輸出的進程就會中止。
不過有的程序可以捕獲這個信號,並忽略它,這樣就算退出了Linux登錄,後台程序依舊運行。
此外,對於與終端脫離關系的守護進程,這個信號用於通知它重新讀取配置文件。
secureCRT異常退出和執行exit的區別?
如果直接關閉secureCRT(此處假設是使用ssh登錄終端的),那麼對於被登錄的系統來說,就是遠端程序異常斷連。和我們突然斷網掉線是一樣的效果。
這種情況下,用戶並沒有信號發送,而是sshd服務檢測到對端響應超時,然後向之前建立起的連接以及該連接下(ssh登錄後會分配一個bash給用戶)的進程發送結束信號。如果部分進程忽略sshd發送的信號,進程不退出,在分配給用戶的bash退出後,該進程將被init進程接管。
終端異常退出後,後台進程不關閉的解決辦法:
1、使用nohup命令: nohup <command> [argument…] & nohup可以屏蔽SIGHUP信號!
2、使用 screen命令。
簡單介紹如下:
SCREEN vi /tmp/2hei.net
需要中斷連接:
screen Ctrl+a d
查詢screen進程:
ps x
20377 ? Ss 0:00 SCREEN vi /tmp/2hei.net
重連 screen -r 20377
Linux Jobs等前後台運行命令解
A,Shell支持作用控制,有以下命令:
1. command& 讓進程在後台運行
2. jobs 查看後台運行的進程
3. fg %n 讓後台運行的進程n到前台來
4. bg %n 讓進程n到後台去;
PS:"n"為jobs查看到的進程編號.
fg、bg、jobs、&、ctrl + z都是跟系統任務有關的,雖然現在基本上不怎麼需要用到這些命令,但學會了也是很實用的
一。& 最經常被用到
這個用在一個命令的最後,可以把這個命令放到後台執行
二。ctrl + z
可以將一個正在前台執行的命令放到後台,並且暫停
三。jobs
查看當前有多少在後台運行的命令
四。fg
將後台中的命令調至前台繼續運行
如果後台中有多個命令,可以用 fg %jobnumber將選中的命令調出,%jobnumber是通過jobs命令查到的後台正在執行的命令的序號(不是pid)
五。 bg
將一個在後台暫停的命令,變成繼續執行
如果後台中有多個命令,可以用bg %jobnumber將選中的命令調出,%jobnumber是通過jobs命令查到的後台正在執行的命令的序號(不是pid)
#Linux下使用Shell命令控制任務 Jobs執行
下列命令可以用來操縱進程任務:
ps 列出系統中正在運行的進程;
kill 發送信號給一個或多個進程(經常用來殺死一個進程);
jobs 列出當前shell環境中已啟動的任務狀態,若未指定jobsid,則顯示所有活動的任務狀態信息;如果報告了一個任務的終止(即任務的狀態被標記為 Terminated),shell 從當前的shell環境已知的列表中刪除任務的進程標識;
bg 將進程搬到後台運行(Background);
fg 將進程搬到前台運行(Foreground);
將job 轉移到後台運行
如果你經常在X圖形下工作,你可能有這樣的經歷:通過終端命令運行一個GUI程序,GUI界面出來了,但是你的終端還停留在原地,你不能在shell中繼續執行其他命令了,除非將GUI程序關掉。
為了使程序執行後終端還能繼續接受命令,你可以將進程移到後台運行,使用如下命令運行程序: #假設要運行xmms
$xmms &
這樣打開xmms後,終端的提示又回來了。現在xmms在後台運行著呢;但萬一你運行程序時忘記使用“&”了,又不想重新執行;你可以先使用ctrl+z掛起程序,然後敲入bg命令,這樣程序就在後台繼續運行了。
概念:當前任務
如果後台的任務號有2個,[1],[2];如果當第一個後台任務順利執行完畢,第二個後台任務還在執行中時,當前任務便會自動變成後台任務號碼 “[2]”的後台任務。所以可以得出一點,即當前任務是會變動的。當用戶輸入“fg”、“bg” 和“stop”等命令時,如果不加任何引號,則所變動的均是當前任務。
察看jobs
使用jobs或ps命令可以察看正在執行的jobs。
jobs命令執行的結果,+表示是一個當前的作業,減號表是是一個當前作業之後的一個作業,jobs -l選項可顯示所有任務的PID,jobs的狀態可以是running, stopped, Terminated,但是如果任務被終止了(kill),shell 從當前的shell環境已知的列表中刪除任務的進程標識;也就是說,jobs命令顯示的是當前shell環境中所起的後台正在運行或者被掛起的任務信息;
進程的掛起
後台進程的掛起:
在solaris中通過stop命令執行,通過jobs命令查看job號(假設為num),然後執行stop %num;
在redhat中,不存在stop命令,可通過執行命令kill -stop PID,將進程掛起;
當要重新執行當前被掛起的任務時,通過bg %num 即可將掛起的job的狀態由stopped改為running,仍在後台執行;當需要改為在前台執行時,執行命令fg %num即可;
前台進程的掛起:
ctrl+Z;
進程的終止
後台進程的終止:
方法一:
通過jobs命令查看job號(假設為num),然後執行kill %num
方法二:
通過ps命令查看job的進程號(PID,假設為pid),然後執行kill pid
前台進程的終止:
ctrl+c
kill的其他作用
kill除了可以終止進程,還能給進程發送其它信號,使用kill -l 可以察看kill支持的信號。
SIGTERM是不帶參數時kill發送的信號,意思是要進程終止運行,但執行與否還得看進程是否支持。如果進程還沒有終止,可以使用kill -SIGKILL pid,這是由內核來終止進程,進程不能監聽這個信號。
===================
Unix/Linux下一般想讓某個程序在後台運行,很多都是使用 & 在程序結尾來讓程序自動運行。比如我們要運行mysql在後台:
/usr/local/mysql/bin/mysqld_safe --user=mysql &
但是我們很多程序並不象mysqld一樣可以做成守護進程,可能我們的程序只是普通程序而已,一般這種程序即使使用 & 結尾,如果終端關閉,那麼程序也會被關閉。為了能夠後台運行,我們需要使用nohup這個命令,比如我們有個start.sh需要在後台運行,並且希望在後台能夠一直運行,那麼就使用nohup:
nohup /root/start.sh &
在shell中回車後提示:
[~]$ appending output to nohup.out
原程序的的標准輸出被自動改向到當前目錄下的nohup.out文件,起到了log的作用。
但是有時候在這一步會有問題,當把終端關閉後,進程會自動被關閉,察看nohup.out可以看到在關閉終端瞬間服務自動關閉。
咨詢紅旗Linux工程師後,他也不得其解,在我的終端上執行後,他啟動的進程竟然在關閉終端後依然運行。
在第二遍給我演示時,我才發現我和他操作終端時的一個細節不同:他是在當shell中提示了nohup成功後還需要按終端上鍵盤任意鍵退回到shell輸入命令窗口,然後通過在shell中輸入exit來退出終端;而我是每次在nohup執行成功後直接點關閉程序按鈕關閉終端.。所以這時候會斷掉該命令所對應的session,導致nohup對應的進程被通知需要一起shutdown。
這個細節有人和我一樣沒注意到,所以在這兒記錄一下了。
附:nohup命令參考
nohup 命令
用途:不掛斷地運行命令。
語法:nohup Command [ Arg ... ] [ & ]
描述:nohup 命令運行由 Command 參數和任何相關的 Arg 參數指定的命令,忽略所有掛斷(SIGHUP)信號。在注銷後使用 nohup 命令運行後台中的程序。要運行後台中的 nohup 命令,添加 & ( 表示"and"的符號)到命令的尾部。
無論是否將 nohup 命令的輸出重定向到終端,輸出都將附加到當前目錄的 nohup.out 文件中。如果當前目錄的 nohup.out 文件不可寫,輸出重定向到 $HOME/nohup.out 文件中。如果沒有文件能創建或打開以用於追加,那麼 Command 參數指定的命令不可調用。如果標准錯誤是一個終端,那麼把指定的命令寫給標准錯誤的所有輸出作為標准輸出重定向到相同的文件描述符。
退出狀態:該命令返回下列出口值:
126 可以查找但不能調用 Command 參數指定的命令。
127 nohup 命令發生錯誤或不能查找由 Command 參數指定的命令。
否則,nohup 命令的退出狀態是 Command 參數指定命令的退出狀態。
nohup命令及其輸出文件
nohup命令:如果你正在運行一個進程,而且你覺得在退出帳戶時該進程還不會結束,那麼可以使用 nohup命令。該命令可以在你退出帳戶/關閉終端之後繼續運行相應的進程。nohup就是不掛起的意思( n ohang up)。
該命令的一般形式為:nohup command &
使用nohup命令提交作業
如果使用nohup命令提交作業,那麼在缺省情況下該作業的所有輸出都被重定向到一個名為 nohup.out的文件中,除非另外指定了輸出文件:
nohup command > myout.file 2>&1 &
在上面的例子中,輸出被重定向到myout.file文件中。
使用 jobs 查看任務。
使用 fg %n 關閉。
另外有兩個常用的ftp工具ncftpget和ncftpput,可以實現後台的ftp上傳和下載,這樣就可以利用這些命令在後台上傳和下載文件了。
簡單而有用的nohup命令在UNIX/LINUX中,普通進程用&符號放到後台運行,如果啟動該程序的控制台logout,則該進程隨即終止。
要實現守護進程,一種方法是按守護進程的規則去編程(本站有文章介紹過),比較麻煩;另一種方法是仍然用普通方法編程,然後用nohup命令啟動程序:
nohup<程序名>&
則控制台logout後,進程仍然繼續運行,起到守護進程的作用(雖然它不是嚴格意義上的守護進程)。
使用nohup命令後,原程序的的標准輸出被自動改向到當前目錄下的nohup.out文件,起到了 log的作用,實現了完整的守護進程功能。
ygwu @ 2005年04月18日 上午10:03
For example:
如何遠程啟動WebLogic服務?
用telnet遠程控制服務器,遠程啟動WEBLOGIC服務,啟動後關閉 telnet,WebLogic服務也跟著停止,這是因為使用telnet啟動的進程會隨著telnet進程的關閉而關閉。所以我們可以使用一些UNIX 下的命令來做到不關閉。
使用如下命令:
nohup startWeblogic.sh&
如果想要監控標准輸出可以使用:
tail -f nohup.out
當在後台運行了程序的時候,可以用jobs命令來查看後台作業的狀態。在有多個後台程序時,要使用來參數的fg命令將不同序號的後台作業切換到前台上運行。
當用戶啟動一個進程的時候,這個進程是運行在前台,使用與相應控制終端相聯系的標准輸入、輸出進行輸入和輸出。即使將進程的輸入輸出重定向,並將進程放在後台執行,進程仍然和當前終端設備有關系。正因為如此,在當前的登錄會話結束時,控制終端設備將和登錄進程相脫離,那麼系統就向所有與這個終端相聯系的進程發送SIGHUP的信號,通知進程線路已經掛起了,如果程序沒有接管這個信號的處理,那麼缺省的反應是進程結束。因此普通的程序並不能真正脫離登錄會話而運行進程,為了使得在系統登錄後還可以正常執行,只有使用命令nohup來啟動相應程序。
使用命令nohup當然可以啟動這樣的程序,但nohup啟動的程序在進程執行完畢就退出,而常見的一些服務進程通常永久的運行在後台,不向屏幕輸出結果。在Unix中這些永久的後台進程稱為守護進程(daemon)。守護進程通常從系統啟動時自動開始執行,系統關閉時才停止。
在守護進程中,最重要的一個是超級守護進程inetd,這個進程接管了大部分網絡服務,但並不是對每個服務都自己進行處理,而是依據連接請求,啟動不同的服務程序與客戶機打交道。inetd支持網絡服務種類在它的設置文件/etc/inet.conf中定義。inet.conf文件中的每一行就對應一個端口地址,當inetd接受到連接這個端口的連接請求時,就啟動相應的進程進行處理。使用inetd的好處是系統不必啟動很多守護進程,從而節約了系統資源,然而使用inetd啟動守護進程相應反應會遲緩一些,不適合用於被密集訪問的服務進程。