成長(zhǎng)空間

          MiLife

          常用鏈接

          統(tǒng)計(jì)

          積分與排名

          Automation Testing Development

          最新評(píng)論

          轉(zhuǎn)貼: 讓進(jìn)程在后臺(tái)可靠運(yùn)行的幾種方法

          讓進(jìn)程在后臺(tái)可靠運(yùn)行的幾種方法

          想讓進(jìn)程在斷開連接后依然保持運(yùn)行?如果該進(jìn)程已經(jīng)開始運(yùn)行了該如何補(bǔ)救? 如果有大量這類需求如何簡(jiǎn)化操作?

              我們經(jīng)常會(huì)碰到這樣的問題,用 telnet/ssh 登錄了遠(yuǎn)程的 Linux 服務(wù)器,運(yùn)行了一些耗時(shí)較長(zhǎng)的任務(wù), 結(jié)果卻由于網(wǎng)絡(luò)的不穩(wěn)定導(dǎo)致任務(wù)中途失敗。如何讓命令提交后不受本地關(guān)閉終端窗口/網(wǎng)絡(luò)斷開連接的干擾呢?下面舉了一些例子, 您可以針對(duì)不同的場(chǎng)景選擇不同的方式來(lái)處理這個(gè)問題。

              nohup/setsid/&

              場(chǎng)景:

              如果只是臨時(shí)有一個(gè)命令需要長(zhǎng)時(shí)間運(yùn)行,什么方法能最簡(jiǎn)便的保證它在后臺(tái)穩(wěn)定運(yùn)行呢?

              解決方法:

              我們知道,當(dāng)用戶注銷(logout)或者網(wǎng)絡(luò)斷開時(shí),終端會(huì)收到 HUP(hangup)信號(hào)從而關(guān)閉其所有子進(jìn)程。因此,我們的解決辦法就有兩種途徑:要么讓進(jìn)程忽略 HUP 信號(hào),要么讓進(jìn)程運(yùn)行在新的會(huì)話里從而成為不屬于此終端的子進(jìn)程。

              1. nohup

              nohup 無(wú)疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup(在 Unix 的早期版本中,每個(gè)終端都會(huì)通過 modem 和系統(tǒng)通訊。當(dāng)用戶 logout 時(shí),modem 就會(huì)掛斷(hang up)電話。 同理,當(dāng) modem 斷開連接時(shí),就會(huì)給終端發(fā)送 hangup 信號(hào)來(lái)通知其關(guān)閉所有子進(jìn)程。) 信號(hào)。讓我們先來(lái)看一下 nohup 的幫助信息
          NOHUP(1)                        User Commands                        NOHUP(1)

          NAME
                 nohup - run a command immune to hangups, with output to a non-tty

          SYNOPSIS
                 nohup COMMAND [ARG]...
                 nohup OPTION

          DESCRIPTION
                 Run COMMAND, ignoring hangup signals.

                 --help display this help and exit

                 --version
                        output version information and exit 


              可見,nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤缺省會(huì)被重定向到 nohup.out 文件中。一般我們可在結(jié)尾加上"&"來(lái)將命令同時(shí)放入后臺(tái)運(yùn)行,也可用">filename 2>&1"來(lái)更改缺省的重定向文件名。

              nohup 示例

             [root@pvcent107 ~]# nohup ping www.ibm.com &
          [1] 3059
          nohup: appending output to `nohup.out'
          [root@pvcent107 ~]# ps -ef |grep 3059
          root      3059   984  0 21:06 pts/3    00:00:00 ping www.ibm.com
          root      3067   984  0 21:06 pts/3    00:00:00 grep 3059
          [root@pvcent107 ~]#


              2。setsid

              nohup 無(wú)疑能通過忽略 HUP 信號(hào)來(lái)使我們的進(jìn)程避免中途被中斷,但如果我們換個(gè)角度思考,如果我們的進(jìn)程不屬于接受 HUP 信號(hào)的終端的子進(jìn)程,那么自然也就不會(huì)受到 HUP 信號(hào)的影響了。setsid 就能幫助我們做到這一點(diǎn)。讓我們先來(lái)看一下 setsid 的幫助信息:

              
          SETSID(8) Linux Programmer’s Manual SETSID(8) NAME setsid - run a program in a new session SYNOPSIS setsid program [ arg ... ] DESCRIPTION setsid runs a program in a new session. 


              可見 setsid 的使用也是非常方便的,也只需在要處理的命令前加上 setsid 即可。

              setsid 示例

           [root@pvcent107 ~]# setsid ping www.ibm.com
          [root@pvcent107 ~]# ps -ef |grep www.ibm.com
          root     31094     1  0 07:28 ?        00:00:00 ping www.ibm.com
          root     31102 29217  0 07:29 pts/4    00:00:00 grep www.ibm.com
          [root@pvcent107 ~]#   


              值得注意的是,上例中我們的進(jìn)程 ID(PID)為31094,而它的父 ID(PPID)為1(即為 init 進(jìn)程 ID),并不是當(dāng)前終端的進(jìn)程 ID。請(qǐng)將此例與nohup 例中的父 ID 做比較。

              3。&
              這里還有一個(gè)關(guān)于 subshell 的小技巧。我們知道,將一個(gè)或多個(gè)命名包含在“()”中就能讓這些命令在子 shell 中運(yùn)行中,從而擴(kuò)展出很多有趣的功能,我們現(xiàn)在要討論的就是其中之一。

              當(dāng)我們將"&"也放入“()”內(nèi)之后,我們就會(huì)發(fā)現(xiàn)所提交的作業(yè)并不在作業(yè)列表中,也就是說(shuō),是無(wú)法通過jobs來(lái)查看的。讓我們來(lái)看看為什么這樣就能躲過 HUP 信號(hào)的影響吧。

              subshell 示例

               [root@pvcent107 ~]# (ping www.ibm.com &)
          [root@pvcent107 ~]# ps -ef |grep www.ibm.com
          root     16270     1  0 14:13 pts/4    00:00:00 ping www.ibm.com
          root     16278 15362  0 14:13 pts/4    00:00:00 grep www.ibm.com
          [root@pvcent107 ~]#   


              從上例中可以看出,新提交的進(jìn)程的父 ID(PPID)為1(init 進(jìn)程的 PID),并不是當(dāng)前終端的進(jìn)程 ID。因此并不屬于當(dāng)前終端的子進(jìn)程,從而也就不會(huì)受到當(dāng)前終端的 HUP 信號(hào)的影響了
          screen

              場(chǎng)景:

              我們已經(jīng)知道了如何讓進(jìn)程免受 HUP 信號(hào)的影響,但是如果有大量這種命令需要在穩(wěn)定的后臺(tái)里運(yùn)行,如何避免對(duì)每條命令都做這樣的操作呢?

              解決方法:

              此時(shí)最方便的方法就是 screen 了。簡(jiǎn)單的說(shuō),screen 提供了 ANSI/VT100 的終端模擬器,使它能夠在一個(gè)真實(shí)終端下運(yùn)行多個(gè)全屏的偽終端。screen 的參數(shù)很多,具有很強(qiáng)大的功能,我們?cè)诖藘H介紹其常用功能以及簡(jiǎn)要分析一下為什么使用 screen 能夠避免 HUP 信號(hào)的影響。我們先看一下 screen 的幫助信息:

               SCREEN(1)                                                           SCREEN(1)

          NAME
                 screen - screen manager with VT100/ANSI terminal emulation

          SYNOPSIS
                 screen [ -options ] [ cmd [ args ] ]
                 screen -r [[pid.]tty[.host]]
                 screen -r sessionowner/[[pid.]tty[.host]]

          DESCRIPTION
                 Screen  is  a  full-screen  window manager that multiplexes a physical
                 terminal between several  processes  (typically  interactive  shells).
                 Each  virtual  terminal provides the functions of a DEC VT100 terminal
                 and, in addition, several control functions from the  ISO  6429  (ECMA
                 48,  ANSI  X3.64)  and ISO 2022 standards (e.g. insert/delete line and
                 support for multiple character sets).  There is a  scrollback  history
                 buffer  for  each virtual terminal and a copy-and-paste mechanism that
                 allows moving text regions between windows.


              使用 screen 很方便,有以下幾個(gè)常用選項(xiàng):

              用screen -dmS session name 來(lái)建立一個(gè)處于斷開模式下的會(huì)話(并指定其會(huì)話名)。
              用screen -list 來(lái)列出所有會(huì)話。
              用screen -r session name 來(lái)重新連接指定會(huì)話。
              用快捷鍵CTRL-a d 來(lái)暫時(shí)斷開當(dāng)前會(huì)話。

              screen 示例

               [root@pvcent107 ~]# screen -dmS Urumchi
          [root@pvcent107 ~]# screen -list
          There is a screen on:
                  12842.Urumchi   (Detached)
          1 Socket in /tmp/screens/S-root.

          [root@pvcent107 ~]# screen -r Urumchi


              當(dāng)我們用“-r”連接到 screen 會(huì)話后,我們就可以在這個(gè)偽終端里面為所欲為,再也不用擔(dān)心 HUP 信號(hào)會(huì)對(duì)我們的進(jìn)程造成影響,也不用給每個(gè)命令前都加上“nohup”或者“setsid”了。這是為什么呢?讓我來(lái)看一下下面兩個(gè)例子吧。

              1. 未使用 screen 時(shí)新進(jìn)程的進(jìn)程樹

               [root@pvcent107 ~]# ping www.google.com &
          [1] 9499
          [root@pvcent107 ~]# pstree -H 9499
          init─┬─Xvnc
               ├─acpid
               ├─atd
               ├─2*[sendmail]
               ├─sshd─┬─sshd───bash───pstree
               │      └─sshd───bash───ping
                      


              我們可以看出,未使用 screen 時(shí)我們所處的 bash 是 sshd 的子進(jìn)程,當(dāng) ssh 斷開連接時(shí),HUP 信號(hào)自然會(huì)影響到它下面的所有子進(jìn)程(包括我們新建立的 ping 進(jìn)程)。

              2. 使用了 screen 后新進(jìn)程的進(jìn)程樹

               [root@pvcent107 ~]# screen -r Urumchi
          [root@pvcent107 ~]# ping www.ibm.com &
          [1] 9488
          [root@pvcent107 ~]# pstree -H 9488
          init─┬─Xvnc
               ├─acpid
               ├─atd
               ├─screen───bash───ping
               ├─2*[sendmail]


              而使用了 screen 后就不同了,此時(shí) bash 是 screen 的子進(jìn)程,而 screen 是 init(PID為1)的子進(jìn)程。那么當(dāng) ssh 斷開連接時(shí),HUP 信號(hào)自然不會(huì)影響到 screen 下面的子進(jìn)程了。

              總結(jié)

              現(xiàn)在幾種方法已經(jīng)介紹完畢,我們可以根據(jù)不同的場(chǎng)景來(lái)選擇不同的方案。nohup/setsid 無(wú)疑是臨時(shí)需要時(shí)最方便的方法,disown 能幫助我們來(lái)事后補(bǔ)救當(dāng)前已經(jīng)在運(yùn)行了的作業(yè),而 screen 則是在大批量操作時(shí)不二的選擇了

          posted on 2009-01-10 13:48 Picasso 閱讀(285) 評(píng)論(0)  編輯  收藏 所屬分類: Unix

          主站蜘蛛池模板: 邵阳县| 义乌市| 诏安县| 淮安市| 赣榆县| 彰化市| 兖州市| 孝义市| 邵阳市| 德昌县| 陵水| 高碑店市| 岑巩县| 石棉县| 甘泉县| 时尚| 山阴县| 阳原县| 舒城县| 华安县| 通化市| 东乌珠穆沁旗| 抚远县| 邢台县| 永靖县| 田林县| 黄冈市| 泊头市| 嘉义县| 海南省| 全州县| 宿迁市| 布拖县| 蕉岭县| 辽源市| 兴业县| 静乐县| 秭归县| 山东| 崇礼县| 汝南县|