使程式在Linux下後臺執行,程式執行前後臺切換
一、為什麼要使程式在後臺執行
我們計算的程式都是週期很長的,通常要幾個小時甚至一個星期。我們用的環境是用Xshell遠端連線到Linux伺服器。所以使程式在後臺跑有以下兩個好處:
1:我們這邊是否關機不影響伺服器的程式執行。(不會像以前那樣,我們這網路一斷開,或一關機,程式就斷掉或找不到資料,跑了幾天的程式只能重頭再來,很是煩惱)
2:讓程式在後臺跑後,不會佔據終端,我們可以用終端做別的事情。
二、怎麼樣使程式在後臺執行
方法有很多,這裡主要列舉兩種。假如我們有程式pso.cpp,通過編譯後產生可執行檔案pso,我們要使pso在linux伺服器後臺執行。當客戶端關機後重新登入伺服器後繼續檢視本來在終端輸出的執行結果。(假設操作都在當前目錄下)
方法1. 在終端輸入命令:
./pso > pso.file 2>&1 &
解釋:將pso直接放在後臺執行,並把終端輸出存放在當前目錄下的pso.file檔案中。
當客戶端關機後重新登陸伺服器後,直接檢視pso.file檔案就可看執行結果
cat pso.file
這種方法有時候關閉終端也會導致程式中斷,有另一種更保險的方法,如下:
方法2. 在終端輸入命令:
nohup ./pso > pso.file 2>&1 &
解釋:nohup就是不掛起的意思,將pso直接放在後臺執行,並把終端輸出存放在當前目錄下的pso.file
cat pso.file
三、常用任務管理命令
# 檢視任務,返回任務編號n和程序號
jobs -l
# 掛起當前任務
ctrl+z
# 將編號為n的任務轉後臺執行
bg %n
# 將編號為n的任務轉前臺執行
# fg %n
# 結束當前任務
ctrl+c
# 設定程式父程序為1,不中斷
setsid ./test.sh &
# 檢視指定任務詳細
ps -ef | grep test
# 顯示當視窗父程序ID
echo $$
注:如果要使在前天執行任務放到後臺執行,則先要用ctrl+z掛起該任務,然後用bg %n使之後臺執行。
附:操作例項
在Linux中,如果要讓程序在後臺執行,一般情況下,我們在命令後面加上&即可,實際上,這樣是將命令放入到一個作業佇列中了:
# 執行任務並放入後臺
./test.sh &
# 會顯示如下PID,任務的程序號
# [1] 17208
# 檢視當前終端下的任務列表
jobs -l
# 會顯示任務編號,當前還是歷史任務,執行狀態,命令名稱
# [1]+ Running ./test.sh &
前臺執行的命令放到後臺執行
首先按ctrl+z暫停已經執行的程序,然後使用bg %1 命令將停止的作業放到後臺執行:
# 執行一個程式
./test.sh
# Ctrl+z掛起程式並顯示編號
# [1]+ Stopped ./test.sh
# 程式轉後臺
bg %1
但是如上方到後臺執行的程序,其父程序還是當前終端shell的程序,而一旦父程序退出,則會發送hangup訊號給所有子程序,子程序收到hangup以後也會退出。如果我們要在退出shell的時候繼續執行程序,則需要使用nohup忽略hangup訊號,或者setsid將將父程序設為init程序(程序號為1)
顯示當前父程序ID
echo $$
# 顯示如:21734
檢視指定任務詳細
ps -ef | grep test
執行結果如下:2列為子進展,3列為你程序
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不中斷執行程式,父程序為1
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
上面的試驗演示了使用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的用法
還有一種更加強大的方式是使用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
linux 程式執行前後臺切換
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環境中所起的後臺正在執行或者被掛起的任務資訊;
程序的掛起
後臺程序的掛起:
在redhat中,不存在stop命令,可通過執行命令kill -stop PID,將程序掛起;
當要重新執行當前被掛起的任務時,通過bg %num 即可將掛起的job的狀態由stopped改為running,仍在後臺執行;當需要改為在前臺執行時,執行命令fg %num即可;