ssh 關閉後仍保持當前運行的進程

ssh 關閉後仍保持當前運行的進程

因爲各類緣由,須要經過ssh登陸linux或者unix主機,不少時候咱們須要經過ssh的終端啓動一 些服務或者運行一些程序,可是默認狀況下,當咱們關閉ssh終端鏈接,隨之啓動的程序也會關閉。緣由是:SSH會話關閉時,ssh所關聯的pty關閉,系 統會給這個pty所關聯的session中的全部進程發送SIGHUP信號,SIGHUP的默認信號處理程序是終止進程,除非進程本身處理了 SIGHUP。html

解決方法以下:mysql

使用現成的命令nohup,可讓指定的程序在pty關閉以後繼續運行。linux

運行方法:sql

#nohup program &shell

如今就能夠正常關閉ssh了,你會發現你的服務依然存在運行編程


當SecureCRT異常關閉後,後臺進程一同關閉的現象罪魁禍首 Signup信號
做者: 2hei 發表於2009年5月19日 22:24 版權聲明: 能夠轉載, 轉載時務必以超鍊形式標明文章原始出處和做者信息及版權聲明 http://www.2hei.net/mt/2009/05/securecrt-closed-and-sighup.html

症狀:使用SecureCRT工具ssh遠程鏈接linux,不退出ssh,而是強行關閉終端(合上筆記本走人)狀況下,後臺啓動的應用也會關閉。
後果:男人哭吧哭吧不是罪!

測試案例:
很明顯的是關閉終端後,前臺運行的程序會被隨之關閉,可是後臺進程也會由於終端異常關閉而關掉,以下是一個簡單的測試結果:
一、後臺執行程序,正常關閉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的進程依然存在

二、後臺執行程序,非正常關閉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登陸,後臺程序依舊運行。
此外,對於與終端脫離關係的守護進程,這個信號用於通知它從新讀取配置文件。

如下是網絡的相關資料
http://hi.baidu.com/xingfengsoft/blog/item/fedbd05c4d8c7e45faf2c0c8.html
—— secureCRT異常退出和執行exit的區別?
若是直接關閉secureCRT(此處假設是使用ssh登陸終端的),那麼對於被登陸的系統來講,就是遠端程序異常斷連。和咱們忽然斷網掉線是同樣的效果。
這 種狀況下,用戶並無信號發送,而是sshd服務檢測到對端響應超時,而後向以前創建起的鏈接以及該鏈接下(ssh登陸後會分配一個bash給用戶)的進 程發送結束信號。若是部分進程忽略sshd發送的信號,進程不退出,在分配給用戶的bash退出後,該進程將被init進程接管。

終端異常退出後,後臺進程不關閉的解決辦法:
一、使用nohup命令: nohup <command> [argument…] &  nohup能夠屏蔽SIGHUP信號!
二、使用 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

參考資料:
http://www.ibm.com/developerworks/cn/linux/l-cn-screen

Linux Jobs等先後臺運行命令解

A,Shell支持做用控制,有如下命令:
1. command& 讓進程在後臺運行
2. jobs 查看後臺運行的進程
3. fg %n 讓後臺運行的進程n到前臺來
4. bg %n 讓進程n到後臺去;  
  PS:"n"爲jobs查看到的進程編號.

B.下列轉:http://blog.chinaunix.net/u/1604 /showart_1079559.html

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啓動守護進程相應反應會遲緩一些,不適合 用於被密集訪問的服務進程
bash

相關文章
相關標籤/搜索