【OS】Linux命令如何放到後臺執行

lhrbest發表於2017-07-27

【OS】Linux命令如何放到後臺執行


linux命令後臺執行

   有兩種方式:


   1. command & : 後臺執行,你關掉終端會停止執行
   2. nohup command & : 後臺執行,你關掉終端也會繼續執行


   


一、 簡介 
    Linux/Unix 區別於微軟平臺最大的優點就是真正的多使用者,多工。因此在任務管理上也有別具特色的管理思想。
我們知道,在 Windows 上面,我們要麼讓一個程式作為服務在後臺一直執行,要麼停止這個服務。而不能讓程式在前臺後臺之間切換。而 Linux 提供了 fg 和bg 命令,讓你輕鬆排程正在執行的任務。假設你發現前臺執行的一個程式需要很長的時間,但是需要幹其他的事情,你就可以用 Ctrl-Z ,掛起這個程式,然後可以看到系統提示:
[1]+ Stopped /root/bin/rsync.sh
然後我們可以把程式排程到後臺執行:(bg 後面的數字為作業號)
#bg 1
[1]+ /root/bin/rsync.sh &
用 jobs 命令檢視正在執行的任務:
#jobs
[1]+ Running /root/bin/rsync.sh &
如果想把它調回到前臺執行,可以用
#fg 1
/root/bin/rsync.sh
這樣,你在控制檯上就只能等待這個任務完成了。



& 將指令丟到後臺中去執行
[ctrl]+z 將前臺任務丟到後臺中暫停
jobs 檢視後臺的工作狀態
fg %jobnumber 將後臺的任務拿到前臺來處理
bg %jobnumber 將任務放到後臺中去處理
kill 管理後臺的任務


二、&

在Linux中,當在前臺執行某個作業時,終端被該作業佔據;而在後臺執行作業時,它不會佔據終端。可以使用&命令把作業放到後臺執行。實際上,這樣是將命令放入到一個作業佇列中了:


$ ./test.sh &
[1] 17208



$ jobs -l
[1]+ 17208 Running                 ./test.sh &
    在後臺執行作業時要當心:需要使用者互動的命令不要放在後臺執行,因為這樣你的機器就會在那裡傻等。不過,作業在後臺執行一樣會將結果輸出到螢幕上,干擾你的工作。如果放在後臺執行的作業會產生大量的輸出,最好使用下面的方法把它的輸出重定向到某個檔案中:
command >out.file 2>&1 &
在上面的例子中,2>&1表示所有的標準輸出和錯誤輸出都將被重定向到一個叫做out.file 的檔案中。 當你成功地提交程式以後,就會顯示出一個程式號,可以用它來監控該程式,或殺死它。 
例:查詢名為“httpd.conf”的檔案,並把所有標準輸出和錯誤輸出重定向到find.dt的檔案中: 
# find /etc/httpd/ -name "httpd.conf" -print >find.dt 2>&1 & 
[2] 7832 
成功提交該命令之後,系統給出了它的程式號7832。 對於已經在前臺執行的命令,也可以重新放到後臺執行,首先按ctrl+z暫停已經執行的程式,然後使用bg命令將停止的作業放到後臺執行,例如對正在前臺執行的tesh.sh使用ctrl+z掛起它:
$ ./test.sh
[1]+ Stopped                 ./test.sh



$ bg %1
[1]+ ./test.sh &



$ jobs -l
[1]+ 22794 Running                 ./test.sh &


但是如上方到後臺執行的程式,其父程式還是當前終端shell的程式,而一旦父程式退出,則會傳送hangup訊號給所有子程式,子程式收到hangup以後也會退出。如果我們要在退出shell的時候繼續執行程式,則需要使用nohup忽略hangup訊號,或者setsid將將父程式設為init程式(程式號為1)


$ echo $$
21734



$ nohup ./test.sh &
[1] 29016



$ ps -ef | grep test
515      29710 21734 0 11:47 pts/12   00:00:00 /bin/sh ./test.sh
515      29713 21734 0 11:47 pts/12   00:00:00 grep test
$ setsid ./test.sh &
[1] 409



$ ps -ef | grep test
515        410     1 0 11:49 ?        00:00:00 /bin/sh ./test.sh
515        413 21734 0 11:49 pts/12   00:00:00 grep test
上面的試驗演示了使用nohup/setsid加上&使程式在後臺執行,同時不受當前shell退出的影響。那麼對於已經在後臺執行的程式,該怎麼辦呢?可以使用disown命令:



$ ./test.sh &
[1] 2539



$ jobs -l
[1]+ 2539 Running                 ./test.sh &


$ disown -h %1


$ ps -ef | grep test
515        410     1 0 11:49 ?        00:00:00 /bin/sh ./test.sh
515       2542 21734 0 11:52 pts/12   00:00:00 grep test
另外還有一種方法,即使將程式在一個subshell中執行,其實這和setsid異曲同工。方法很簡單,將命令用括號() 括起來即可:


$ (./test.sh &)


$ ps -ef | grep test
515        410     1 0 11:49 ?        00:00:00 /bin/sh ./test.sh
515      12483 21734 0 11:59 pts/12   00:00:00 grep test
注:本文試驗環境為Red Hat Enterprise Linux AS release 4 (Nahant Update 5),shell為/bin/bash,不同的OS和shell可能命令有些不一樣。例如AIX的ksh,沒有disown,但是可以使用nohup -p PID來獲得disown同樣的效果。


還有一種更加強大的方式是使用screen,首先建立一個斷開模式的虛擬終端,然後用-r選項重新連線這個虛擬終端,在其中執行的任何命令,都能達到nohup的效果,這在有多個命令需要在後臺連續執行的時候比較方便:

$ screen -dmS screen_test


$ screen -list
There is a screen on:
        27963.screen_test       (Detached)
1 Socket in /tmp/uscreens/S-jiangfeng.


$ screen -r screen_test


三、 nohup 
    如果你正在執行一個程式,而且你覺得在退出帳戶時該程式還不會結束,那麼可以使用nohup命令。該命令可以在你退出帳戶之後繼續執行相應的程式。nohup就是不掛起的意思( no hang up)。 該命令的一般形式為: 
nohup conmmand &
如果使用nohup命令提交作業,那麼在預設情況下該作業的所有輸出都被重定向到一個名為nohup.out的檔案中,除非另外指定了輸出檔案:
nohup command > myout.file 2>&1 
在上面的例子中,輸出被重定向到myout.file檔案中。




四、.*,?,[...],[!...]等 
下面就是這些特殊字元: 
* 匹配檔名中的任何字串,包括空字串。 
? 匹配檔名中的任何單個字元。 
[...] 匹配[ ]中所包含的任何字元。 
[!...] 匹配[ ]中非感嘆號!之後的字元。 
當s h e l l遇到上述字元時,就會把它們當作特殊字元,而不是檔名中的普通字元,這樣使用者就可以用它們來匹配相應的檔名。

1)列出以i或o開頭的檔名:     #ls [io]*
2)列出log.開頭、後面跟隨一個數字、然後可以是任意字串的檔名: #ls log.[0-9]* 
3)與例二相反,列出log.開頭、後面不跟隨一個數字、然後可以是任意字串的檔名 : #ls log.[!0-9]* 
4)列出所有以LPS開頭、中間可以是任何兩個字元,最後以1結尾的檔名:#ls LPS??1
5)列出所有以大寫字母開頭的檔名:$ ls [A-Z]* 6)列出所有以. 開頭的檔名(隱含檔案,例如. profile、.rhosts、.histo ry等): $ ls .*


  • 其他相關命令:


jobs:檢視當前有多少在後臺執行的命令
fg:將後臺中的命令調至前臺繼續執行。如果後臺中有多個命令,可以用 fg %jobnumber將選中的命令調出,%jobnumber是透過jobs命令查到的後臺正在執行的命令的序號(不是pid)
bg:將一個在後臺暫停的命令,變成繼續執行。如果後臺中有多個命令,可以用bg %jobnumber將選中的命令調出,%jobnumber是透過jobs命令查到的後臺正在執行的命令的序號(不是pid)


  • 殺死程式

殺死已經啟動的程式和普通方式一樣:

  • pkill -9 name
  • killall name
  • kill pid



執行的指令

指令或符號

使用範例

說明

& % fasta & 在背景中執行程式
jobs % jobs 顯示送入背景之工作
kill % kill (job#) 移除指定之批次工作
ctrl-z   暫停前景中執行之程式
bg % bg 將暫停之工作送入背景執行
fg % fg 將背景之工作拉回前景執行



1.透過使用‘&’運算子讓Job在後臺執行
通常我們Linux的終端中,執行某一命令時,終端總是等待某一特定的命令或程式執行完以後,給出一個提示,然後我們才能繼續執行下一個命令。如果我們要執行一個比較耗時的命令,但是在該命令執行的同時還需要做另外的一些事,那該怎麼辦呢?
你可以透過在命令的後面加上一個‘&’運算子,來讓一個任務在後臺執行。(當然如果你是用GUI介面,你也可以重新開啟一個視窗執行新的命令或程式)
例如,我們需要複製一個比較大的檔案,在複製的同時,還要做其他一些事情,那麼在複製命令後面加上一個‘&’,讓它在後臺複製:
lennon@lennon-laptop:~$ cp /media/bigfile /home/lennon/Downloads/ &
[1] 3526
lennon@lennon-laptop:~$ 
此時,我們可以看到在終端中,執行了某一命令後,給出了一些資訊,然後就返回了,接著提示使用者可以出入下一個命令了,這樣程式或命令就在後臺執行了。
在顯示的資訊中,用方括號括起來的數字,表示系統分配給這個Job的Job Number,這裡'[1]'中的1,就是這個Job的Job Number。而後面一個比較大的數字,則是系統分配的程式ID(PID),這個PID在系統就代表這個程式。
在後臺執行的job,當其執行完成以後,且輸入回車後,會在終端中給出一個提示:
lennon@lennon-laptop:~$ rm Downloads/linux_11gR2_database_1of2.zip &
[1] 3666
lennon@lennon-laptop:~$ 
[1]+  Done                    rm Downloads/linux_11gR2_database_1of2.zip

2.使用jobs命令,來檢視當前系統中的Job
如果我們需要檢視當前系統中,有那些job,使用‘jobs’命令:
lennon@lennon-laptop:~$ jobs
[1]-  Running                 cp /media/bigfile /home/lennon/Downloads/ &
[2]+  Stopped                 cat
lennon@lennon-laptop:~$ 
如此時,顯示我的系統中有2個job,一個是剛才的正在執行的複製命令([1]標識),一個是停止執行的cat命令([2]表示)。這裡‘Running’、‘Stopped’表示任務的狀態

jobs命令參考
命令名稱:jobs
使用許可權:所有許可權
命令描述:列出系統中的job。注意:不是所有的shell都能使用此命令
語法:jobs [-p | -l] [-n] [-p] [-x] [job id]
引數:
-p | -l : Report the process group ID and working directory of the jobs.
-n      : Display only jobs that have stopped or exited since last notified.
-p      : Displays only the process IDs for the process group leaders of the selected jobs.
-x      : Replace any job_id found in command or arguments with the corresponding 
           process group ID, and then execute command passing it arguments.
job id  : The job id.

3.Suspend key 和 bg命令的使用(將一個正在執行的job放到後臺執行)
如果你在執行job前,並不知道該job的執行情況,但在job執行了以後,發現這個是耗時的任務,並想將其放入到後臺執行,這樣你可以在這個任務執行的同時,完成一些其他的事情,那麼你可以這樣做:
使用掛起鍵(Suspend Key,通常是Ctrl-Z)將該任務掛起(也就是暫停),然後使用‘bg’命令在後臺讓該job恢復執行。
lennon@lennon-laptop:~$ cp bigfile bigfile.bac
^Z
[1]+  Stopped                 cp bigfile bigfile.bac
lennon@lennon-laptop:~$ bg %1
[1]+ cp bigfile bigfile.bac &
lennon@lennon-laptop:~$
使用Ctrl-Z後,系統會將當前正在執行的job暫停,將其移至後臺,給出使用者改任務的提示(包括job number、狀態、job),然後提示使用者輸入下一個命令。
在job掛起後,可以使用‘bg’命令,讓job恢復到剛才中斷的地方繼續執行並將其放到後臺執行。使用‘bg %job number’來指定你需要對哪一個job進行操作,這裡‘%’告訴系統後面的數字是一個job number(不要‘%’可能也可以)。當然在系統中只有一個job的時候,你也可以忽略改引數。

bg命令參考:
命令名稱:bg
使用許可權:所有許可權
命令描述:在後臺恢復已停止的job繼續執行。注意該命令不能在所有的Unix的shell下執行
語法:bg [-l] [-p] [-x] [job]
引數:
-l    : Report the process group ID and working directory of the jobs.
-p    : Report only the process group ID of the jobs.
-x    : Replace any job_id found in command or arguments with the corresponding process  
         group ID, and then execute command passing it arguments.
job   : Specifies the job that you want to run in the background.

4.使用fg命令,將在後臺的job換到前臺
當你需要將在後臺的job換到前臺時,使用‘fg %job number’命令(也許不要‘%’也可以)。
lennon@lennon-laptop:~$ cp bigfile bigfile.bac &
[1] 3815
lennon@lennon-laptop:~$ fg 1
cp bigfile bigfile.bac

fg命令參考:
命令名稱:fg
使用許可權:所有許可權
命令描述:將後臺的任務移至前臺,如果是該任務處於暫停狀態,則恢復該任務的執行。
         注意該命令不是在所有的shell中都能執行。
語法:fg [%job]
引數:
%job : Specifies the job that you want to run in the foreground.

5.如何結束一個job
如果你想結束一個正在執行的job,可以使用中斷鍵(interrupt key,通常是Ctrl-C)來結束。
lennon@lennon-laptop:~$ cp bigfile bigfile.bac 
^C
lennon@lennon-laptop:~$ 
如果上面方法無法正常工作,那麼你可以考慮使用Ctrl-Z(Suspend key)來暫停job,使用'jobs'命令來檢視這個job的job number,然後透過'kill'命令來結束這個job.
lennon@lennon-laptop:~$ cp bigfile bigfile.bac 
^Z
[1]+  Stopped                 cp bigfile bigfile.bac
lennon@lennon-laptop:~$ jobs
[1]+  Stopped                 cp bigfile bigfile.bac
lennon@lennon-laptop:~$ kill %1
lennon@lennon-laptop:~$ 
[1]+  Terminated              cp bigfile bigfile.bac
'kill %1'中的'%'告訴系統,後面的數字是一個job number。預設情況下,kill將會向程式傳送一個termination signal(-TERM)。如果這個訊號不起作用,考慮使用'kill -kill %job number'來傳送一個kill signal(-KILL)。
'kill'命令的使用,就看man把,info也可以,這裡不說了,上面東西太多。不過常用的也就'kill %job number'、'kill -kill %job number'、'kill [-kill] PID'。


Linux下Ctrl-Z、Ctrl-C、Ctrl-D的具體含義
初識Linux,可能會對Ctrl-Z、Ctrl-C、Ctrl-D的具體含義混淆不清,因為這三個按鍵都能夠在一些情況下使shell退出正在執行的命令或程式,提示使用者輸入下一個命令,從而對初識者造成假象,認為三個鍵的功能一樣,但具體情況下哪個按鍵能起作用、起什麼作用卻拿捏不定。

    Ctrl-Z:該鍵是linux下面預設的掛起鍵(Suspend Key),當鍵入Ctrl-Z時,系統會將正在執行的程式掛起,然後放到後臺,同時給出使用者相關的job資訊。此時,程式並沒有真正的停止,使用者可以透過使用fg、bg命令將job恢復到暫停前的上下文環境,並繼續執行。
    Ctrl-C:該鍵是linux下面預設的中斷鍵(Interrupt Key),當鍵入Ctrl-C時,系統會傳送一箇中斷訊號給正在執行的程式和shell。具體的響應結果會根據程式的不同而不同。一些程式在收到這個訊號後,會立即結束並推出程式,一些程式可能會忽略這個中斷訊號,還有一些程式在接受到這個訊號後,會採取一些其他的動作(Action)。當shell接受到這個中斷訊號的時候,它會返回到提示介面,並等待下一個命令。
    Ctrl-D:該鍵是Linux下面標準輸入輸出的EOF。在使用標準輸入輸出的裝置中,遇到該符號,會認為讀到了檔案的末尾,因此結束輸入或輸出。




Linux下使Shell 命令脫離終端在後臺執行

 (2012-02-05 21:41:57)

你是否遇到過這樣的情況:從終端軟體登入遠端的Linux主機,將一堆很大的檔案壓縮為一個.tar.gz檔案,連續壓縮了半個小時還沒有完成,這時,突然你斷網了,你登入不上遠端Linux主機了,那麼前面的半個小時就會前功盡棄,你非常氣憤……

在Linux下,如果你要執行的shell命令耗時特別長,並且:(1)你的網路不穩定,隨時可能斷網;或者(2)你在執行了shell命令之後必須要關閉終端軟體(例如SecureCRT)。


那麼你就需要以脫離終端的方式在後臺執行這個shell命令。

方法如下:

(1)輸入命令:

nohup 你的shell命令 &

(2)回車,使終端回到shell命令列;

(3)輸入exit命令退出終端:

exit

(4)現在可以關閉你的終端軟體了,等過足夠的時間,讓你的shell命令執行完了再上去看結果吧。

其中,nohup命令可以讓你的shell命令忽略SIGHUP訊號,即可以使之脫離終端執行;“&”可以讓你的命令在後臺執行。

以脫離終端的方式在後臺執行shell命令有這樣幾個好處:只要你執行過了命令,那麼你的網路中斷不會對你有任何影響,並且你就可以關閉終端軟體了。

 

本篇文章來源於 Linux公社網站( 原文連結:

 

 

 

用運程終端登陸Linux後執行的程式,當關閉終端時程式也被終至,下面的方法可以讓程式在後臺執行。

Unix/Linux下一般比如想讓某個程式在後臺執行,很多都是使用 & 在程式結尾來讓程式自動執行。比如我們要執行mysql在後臺:

  /usr/local/mysql/bin/mysqld_safe --user=mysql &

 但是加入我們很多程式並不象mysqld一樣做成守護程式可能我們的程式只是普通程式而已,一般這種程式使用 & 結尾,但是如果終端關閉,那麼程式也會被關閉。但是為了能夠後臺執行,那麼我們就可以使用nohup這個命令,比如我們有個test.php需要在後臺執行,並且希望在後臺能夠定期執行,那麼就使用nohup:

  nohup /root/test.php &

  提示:

  [~]$ appending output to nohup.out

  嗯,證明執行成功,同時把程式執行的輸出資訊放到當前目錄的 nohup.out 檔案中去。


附: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就是不掛起的意思( no hang up)。

  該命令的一般形式為:nohup command &


使用nohup命令提交作業

  如果使用nohup命令提交作業,那麼在預設情況下該作業的所有輸出都被重定向到一個名為nohup.out的檔案中,除非另外指定了輸出檔案:

  nohup command > myout.file 2>&1 &

  在上面的例子中,輸出被重定向到myout.file檔案中。







Linux 技巧:讓程式在後臺可靠執行的幾種方法



我們經常會碰到這樣的問題,用 telnet/ssh 登入了遠端的 Linux 伺服器,執行了一些耗時較長的任務, 結果卻由於網路的不穩定導致任務中途失敗。如何讓命令提交後不受本地關閉終端視窗/網路斷開連線的干擾呢?下面舉了一些例子, 您可以針對不同的場景選擇不同的方式來處理這個問題。


nohup/setsid/&

場景:

如果只是臨時有一個命令需要長時間執行,什麼方法能最簡便的保證它在後臺穩定執行呢?

hangup 名稱的來由

在 Unix 的早期版本中,每個終端都會透過 modem 和系統通訊。當使用者 logout 時,modem 就會結束通話(hang up)電話。 同理,當 modem 斷開連線時,就會給終端傳送 hangup 訊號來通知其關閉所有子程式。

解決方法:

我們知道,當使用者登出(logout)或者網路斷開時,終端會收到 HUP(hangup)訊號從而關閉其所有子程式。因此,我們的解決辦法就有兩種途徑:要麼讓程式忽略 HUP 訊號,要麼讓程式執行在新的會話裡從而成為不屬於此終端的子程式。

1. nohup

nohup 無疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 訊號。讓我們先來看一下 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 即可,標準輸出和標準錯誤預設會被重定向到 nohup.out 檔案中。一般我們可在結尾加上"&"來將命令同時放入後臺執行,也可用">filename 2>&1"來更改預設的重定向檔名。

nohup 示例
[root@pvcent107 ~]# nohup ping  &
[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 
root      3067   984  0 21:06 pts/3    00:00:00 grep 3059
[root@pvcent107 ~]#

2。setsid

nohup 無疑能透過忽略 HUP 訊號來使我們的程式避免中途被中斷,但如果我們換個角度思考,如果我們的程式不屬於接受 HUP 訊號的終端的子程式,那麼自然也就不會受到 HUP 訊號的影響了。setsid 就能幫助我們做到這一點。讓我們先來看一下 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 
[root@pvcent107 ~]# ps -ef |grep 
root     31094 1 0 07:28 ?        00:00:00 ping 
root     31102 29217  0 07:29 pts/4    00:00:00 grep 
[root@pvcent107 ~]#

值得注意的是,上例中我們的程式 ID(PID)為31094,而它的父 ID(PPID)為1(即為 init 程式 ID),並不是當前終端的程式 ID。請將此例與nohup 例中的父 ID 做比較。

3。&

這裡還有一個關於 subshell 的小技巧。我們知道,將一個或多個命名包含在“()”中就能讓這些命令在子 shell 中執行中,從而擴充套件出很多有趣的功能,我們現在要討論的就是其中之一。

當我們將"&"也放入“()”內之後,我們就會發現所提交的作業並不在作業列表中,也就是說,是無法透過jobs來檢視的。讓我們來看看為什麼這樣就能躲過 HUP 訊號的影響吧。

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

從上例中可以看出,新提交的程式的父 ID(PPID)為1(init 程式的 PID),並不是當前終端的程式 ID。因此並不屬於當前終端的子程式,從而也就不會受到當前終端的 HUP 訊號的影響了。

disown

場景:

我們已經知道,如果事先在命令前加上 nohup 或者 setsid 就可以避免 HUP 訊號的影響。但是如果我們未加任何處理就已經提交了命令,該如何補救才能讓它避免 HUP 訊號的影響呢?

解決方法:

這時想加 nohup 或者 setsid 已經為時已晚,只能透過作業排程和 disown 來解決這個問題了。讓我們來看一下 disown 的幫助資訊:

disown [-ar] [-h] [jobspec ...]
	Without options, each jobspec is  removed  from  the  table  of
	active  jobs.   If  the -h option is given, each jobspec is not
	removed from the table, but is marked so  that  SIGHUP  is  not
	sent  to the job if the shell receives a SIGHUP.  If no jobspec
	is present, and neither the -a nor the -r option  is  supplied,
	the  current  job  is  used.  If no jobspec is supplied, the -a
	option means to remove or mark all jobs; the -r option  without
	a  jobspec  argument  restricts operation to running jobs.  The
	return value is 0 unless a jobspec does  not  specify  a  valid
	job.

可以看出,我們可以用如下方式來達成我們的目的。

靈活運用 CTRL-z

在我們的日常工作中,我們可以用 CTRL-z 來將當前程式掛起到後臺暫停執行,執行一些別的操作,然後再用 fg 來將掛起的程式重新放回前臺(也可用 bg 來將掛起的程式放在後臺)繼續執行。這樣我們就可以在一個終端內靈活切換執行多個任務,這一點在除錯程式碼時尤為有用。因為將程式碼編輯器掛起到後臺再重新放回時,游標定位仍然停留在上次掛起時的位置,避免了重新定位的麻煩。

  • disown -h jobspec來使某個作業忽略HUP訊號。
  • disown -ah 來使所有的作業都忽略HUP訊號。
  • disown -rh 來使正在執行的作業忽略HUP訊號。

需要注意的是,當使用過 disown 之後,會將把目標作業從作業列表中移除,我們將不能再使用jobs來檢視它,但是依然能夠用ps -ef查詢到它。

但是還有一個問題,這種方法的操作物件是作業,如果我們在執行命令時在結尾加了"&"來使它成為一個作業並在後臺執行,那麼就萬事大吉了,我們可以透過jobs命令來得到所有作業的列表。但是如果並沒有把當前命令作為作業來執行,如何才能得到它的作業號呢?答案就是用 CTRL-z(按住Ctrl鍵的同時按住z鍵)了!

CTRL-z 的用途就是將當前程式掛起(Suspend),然後我們就可以用jobs命令來查詢它的作業號,再用bg jobspec來將它放入後臺並繼續執行。需要注意的是,如果掛起會影響當前程式的執行結果,請慎用此方法。

disown 示例1(如果提交命令時已經用“&”將命令放入後臺執行,則可以直接使用“disown”)
[root@pvcent107 build]# cp -r testLargeFile largeFile &
[1] 4825
[root@pvcent107 build]# jobs
[1]+  Running                 cp -i -r testLargeFile largeFile &
[root@pvcent107 build]# disown -h %1
[root@pvcent107 build]# ps -ef |grep largeFile
root      4825   968  1 09:46 pts/4    00:00:00 cp -i -r testLargeFile largeFile
root      4853   968  0 09:46 pts/4    00:00:00 grep largeFile
[root@pvcent107 build]# logout
disown 示例2(如果提交命令時未使用“&”將命令放入後臺執行,可使用 CTRL-z 和“bg”將其放入後臺,再使用“disown”)
[root@pvcent107 build]# cp -r testLargeFile largeFile2

[1]+  Stopped                 cp -i -r testLargeFile largeFile2
[root@pvcent107 build]# bg %1
[1]+ cp -i -r testLargeFile largeFile2 &
[root@pvcent107 build]# jobs
[1]+  Running                 cp -i -r testLargeFile largeFile2 &
[root@pvcent107 build]# disown -h %1
[root@pvcent107 build]# ps -ef |grep largeFile2
root      5790  5577  1 10:04 pts/3    00:00:00 cp -i -r testLargeFile largeFile2
root      5824  5577  0 10:05 pts/3    00:00:00 grep largeFile2
[root@pvcent107 build]#

screen

場景:

我們已經知道了如何讓程式免受 HUP 訊號的影響,但是如果有大量這種命令需要在穩定的後臺裡執行,如何避免對每條命令都做這樣的操作呢?

解決方法:

此時最方便的方法就是 screen 了。簡單的說,screen 提供了 ANSI/VT100 的終端模擬器,使它能夠在一個真實終端下執行多個全屏的偽終端。screen 的引數很多,具有很強大的功能,我們在此僅介紹其常用功能以及簡要分析一下為什麼使用 screen 能夠避免 HUP 訊號的影響。我們先看一下 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 很方便,有以下幾個常用選項:

  • screen -dmS session name來建立一個處於斷開模式下的會話(並指定其會話名)。
  • screen -list 來列出所有會話。
  • screen -r session name來重新連線指定會話。
  • 用快捷鍵CTRL-a d 來暫時斷開當前會話。
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

當我們用“-r”連線到 screen 會話後,我們就可以在這個偽終端裡面為所欲為,再也不用擔心 HUP 訊號會對我們的程式造成影響,也不用給每個命令前都加上“nohup”或者“setsid”了。這是為什麼呢?讓我來看一下下面兩個例子吧。

1. 未使用 screen 時新程式的程式樹
[root@pvcent107 ~]# ping  &
[1] 9499
[root@pvcent107 ~]# pstree -H 9499
init─┬─Xvnc
     ├─acpid
     ├─atd
     ├─2*[sendmail] ├─sshd─┬─sshd───bash───pstree
     │  └─sshd───bash───ping

我們可以看出,未使用 screen 時我們所處的 bash 是 sshd 的子程式,當 ssh 斷開連線時,HUP 訊號自然會影響到它下面的所有子程式(包括我們新建立的 ping 程式)。

2. 使用了 screen 後新程式的程式樹
[root@pvcent107 ~]# screen -r Urumchi
[root@pvcent107 ~]# ping  &
[1] 9488
[root@pvcent107 ~]# pstree -H 9488
init─┬─Xvnc
     ├─acpid
     ├─atd ├─screen───bash───ping ├─2*[sendmail]

而使用了 screen 後就不同了,此時 bash 是 screen 的子程式,而 screen 是 init(PID為1)的子程式。那麼當 ssh 斷開連線時,HUP 訊號自然不會影響到 screen 下面的子程式了。

總結

現在幾種方法已經介紹完畢,我們可以根據不同的場景來選擇不同的方案。nohup/setsid 無疑是臨時需要時最方便的方法,disown 能幫助我們來事後補救當前已經在執行了的作業,而 screen 則是在大批次操作時不二的選擇了。




About Me

.............................................................................................................................................

● 本文整理自網路

● 本文在itpub(http://blog.itpub.net/26736162/abstract/1/)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文部落格園地址:http://www.cnblogs.com/lhrbest

● 本文pdf版、個人簡介及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● DBA寶典今日頭條號地址:

.............................................................................................................................................

● QQ群:230161599     微信群:私聊

● 聯絡我請加QQ好友(646634621),註明新增緣由

● 於 2017-07-01 09:00 ~ 2017-07-31 22:00 在魔都完成

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

.............................................................................................................................................

小麥苗的微店

小麥苗出版的資料庫類叢書http://blog.itpub.net/26736162/viewspace-2142121/

.............................................................................................................................................

使用微信客戶端掃描下面的二維碼來關注小麥苗的微信公眾號(xiaomaimiaolhr)及QQ群(DBA寶典),學習最實用的資料庫技術。

   小麥苗的微信公眾號          小麥苗的QQ群             小麥苗的微店

.............................................................................................................................................

【OS】Linux命令如何放到後臺執行
DBA筆試面試講解
歡迎與我聯絡



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2142674/,如需轉載,請註明出處,否則將追究法律責任。

相關文章