【OS】Linux命令如何放到後臺運行
php
有兩種方式:mysql
1. command & : 後臺運行,你關掉終端會中止運行 linux
2. nohup command & : 後臺運行,你關掉終端也會繼續運行 sql
1、 簡介 shell
Linux/Unix 區別於微軟平臺最大的優勢就是真正的多用戶,多任務。所以在任務管理上也有別具特點的管理思想。 windows
咱們知道,在 Windows 上面,咱們要麼讓一個程序做爲服務在後臺一直運行,要麼中止這個服務。而不能讓程序在前臺後臺之間切換。而 Linux 提供了 fg 和bg 命令,讓你輕鬆調度正在運行的任務。假設你發現前臺運行的一個程序須要很長的時間,可是須要幹其餘的事情,你就能夠用 Ctrl-Z ,掛起這個程序,而後能夠看到系統提示: bash
[1]+ Stopped /root/bin/rsync.sh 服務器
而後咱們能夠把程序調度到後臺執行:(bg 後面的數字爲做業號) 網絡
#bg 1 session
[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 管理後臺的任務
2、&
在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
3、 nohup
若是你正在運行一個進程,並且你以爲在退出賬戶時該進程還不會結束,那麼可使用nohup命令。該命令能夠在你退出賬戶以後繼續運行相應的進程。nohup就是不掛起的意思( no hang up)。 該命令的通常形式爲:
nohup conmmand &
若是使用nohup命令提交做業,那麼在缺省狀況下該做業的全部輸出都被重定向到一個名爲nohup.out的文件中,除非另外指定了輸出文件:
nohup command > myout.file 2>&1
在上面的例子中,輸出被重定向到myout.file文件中。
4、.*,?,[...],[!...]等
下面就是這些特殊字符:
* 匹配文件名中的任何字符串,包括空字符串。
? 匹配文件名中的任何單個字符。
[...] 匹配[ ]中所包含的任何字符。
[!...] 匹配[ ]中非感嘆號!以後的字符。
當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。在使用標準輸入輸出的設備中,遇到該符號,會認爲讀到了文件的末尾,所以結束輸入或輸出。
(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公社網站(www.linuxidc.com) 原文連接:http://www.linuxidc.com/Linux/2011-05/35723.htm
用運程終端登錄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文件中。
咱們常常會碰到這樣的問題,用 telnet/ssh 登陸了遠程的 Linux 服務器,運行了一些耗時較長的任務, 結果卻因爲網絡的不穩定致使任務中途失敗。如何讓命令提交後不受本地關閉終端窗口/網絡斷開鏈接的干擾呢?下面舉了一些例子, 您能夠針對不一樣的場景選擇不一樣的方式來處理這個問題。
若是隻是臨時有一個命令須要長時間運行,什麼方法能最簡便的保證它在後臺穩定運行呢?
在 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 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 無疑能經過忽略 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 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 ~]#
值得注意的是,上例中咱們的進程 ID(PID)爲31094,而它的父 ID(PPID)爲1(即爲 init 進程 ID),並非當前終端的進程 ID。請將此例與nohup 例中的父 ID 作比較。
3。&
這裏還有一個關於 subshell 的小技巧。咱們知道,將一個或多個命名包含在「()」中就能讓這些命令在子 shell 中運行中,從而擴展出不少有趣的功能,咱們如今要討論的就是其中之一。
當咱們將"&"也放入「()」內以後,咱們就會發現所提交的做業並不在做業列表中,也就是說,是沒法經過jobs來查看的。讓咱們來看看爲何這樣就能躲過 HUP 信號的影響吧。
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 ~]#
從上例中能夠看出,新提交的進程的父 ID(PPID)爲1(init 進程的 PID),並非當前終端的進程 ID。所以並不屬於當前終端的子進程,從而也就不會受到當前終端的 HUP 信號的影響了。
回頁首
咱們已經知道,若是事先在命令前加上 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 來將當前進程掛起到後臺暫停運行,執行一些別的操做,而後再用 fg 來將掛起的進程從新放回前臺(也可用 bg 來將掛起的進程放在後臺)繼續運行。這樣咱們就能夠在一個終端內靈活切換運行多個任務,這一點在調試代碼時尤其有用。由於將代碼編輯器掛起到後臺再從新放回時,光標定位仍然停留在上次掛起時的位置,避免了從新定位的麻煩。
須要注意的是,當使用過 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]#
回頁首
咱們已經知道了如何讓進程免受 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 示例
[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 www.google.com & [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 www.ibm.com & [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 則是在大批量操做時不二的選擇了。