在Linux中,利用Shell的作業控制是比較常用的操作,在這一節中我們將探究作業控制相關的操作。為了方便我們查看區分不同的進行,我們編寫如下程序,其功能是每間隔2秒輸出一次自己的編號。
1 /* 2 ** Test puting a running program into backgound 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 7 int main(int argc, char* argv[]) 8 { 9 if (argc != 2){ 10 printf("Usage : bgtest number\n"); 11 return -1; 12 } 13 14 while (1){ 15 printf("Task [%d] Wait 2 seconds.\n", atoi(argv[1])); 16 sleep(2); 17 } 18 }
1 將進程放入後台
在shell編程環境中,可以使用組合鍵CTRL+Z將前台正在運行的程序放入後台,但是程序會暫停執行。示例如下:
linuxidc@linuxidc:~/Documents/Shell$ ./bgtest 2000 Task [2000] Wait 2 seconds. ^Z [1]+ Stopped ./bgtest 2000 linuxidc@linuxidc:~/Documents/Shell$ ./bgtest 2001 Task [2001] Wait 2 seconds. ^Z [2]+ Stopped ./bgtest 2001 linuxidc@linuxidc:~/Documents/Shell$ ./bgtest 2002 Task [2002] Wait 2 seconds. ^Z [3]+ Stopped ./bgtest 2002
如上所示,我們運行了3個進程,並且給每個進程指定一個不同的編號,如2000、 2001、 2002,借此我們可以知道當前哪一個進程在運行。當我們按下Ctrl+Z組合鍵後,進程會被放到後台並且暫停,同時我們可以看到輸出了一行字符串,類似於“[1]+ Stopped ./bgtest 2000”,要注意中括號[]中的數字就是系統自動生成的後台任務編號。
2 查看後台程序
在前面,我們已經將3個進程放到後台了,但是我們如何查看呢?可以使用jobs命令,用法如下:
linuxidc@linuxidc:~/Documents/Shell$ jobs [1] Stopped ./bgtest 2000 [2]- Stopped ./bgtest 2001 [3]+ Stopped ./bgtest 2002
該命令輸出有3列,第一列為任務編號,第二列為任務的狀態,第三列為程序名。我們可以看到,所有的進程被放入到後台以後全部都暫停了。
3 後台運行程序
如何讓後台被暫停的程序重新運行呢?我們可以使用命令“bg 任務編號”來讓程序在後台運行,如下所示就是讓任務編號為1的程序重新運行。
linuxidc@linuxidc:~/Documents/Shell$ bg 1 [1] ./bgtest 2000 & linuxidc@linuxidc:~/Documents/Shell$ Task [2000] Wait 2 seconds. Task [2000] Wait 2 seconds. joTask [2000] Wait 2 seconds. bs [1] Running ./bgtest 2000 & [2]- Stopped ./bgtest 2001 [3]+ Stopped ./bgtest 2002
我們可以看到,程序會繼續輸出字符串,但是,真個並不影響我們接著執行其他命令,比如我們這是繼續使用jobs命令,可以查看到後台運行的程序的狀態,也看到任務1的狀態改為了“Running”。
4 讓程序前台運行
當然,我們也可以讓被放到後台的程序重新回到前台運行,可以執行“fg 任務編號”,如下所示:
linuxidc@linuxidc:~/Documents/Shell$ fg 3 ./bgtest 2002 Task [2002] Wait 2 seconds. Task [2002] Wait 2 seconds. Task [2002] Wait 2 seconds. jobTask [2002] Wait 2 seconds. s Task [2002] Wait 2 seconds. jos Task [2002] Wait 2 seconds. Task [2002] Wait 2 seconds. Task [2002] Wait 2 seconds. ^Z [3]+ Stopped ./bgtest 2002
可以看到,程序在前台運行時,如果我們輸入其他命令是不能響應的,整個前台被當前運行的任務3獨占。我們必須將其重新放入到後台才能夠輸入其他命令。
5 殺死前台進程
殺死前台進程比較容易,我們可以直接使用組合鍵Ctrl+C終止前台運行的進程。
linuxidc@linuxidc:~/Documents/Shell$ fg 3 ./bgtest 2002 Task [2002] Wait 2 seconds. ^C linuxidc@linuxidc:~/Documents/Shell$ ps -u Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 1000 9301 0.0 0.6 9868 6332 pts/0 Ss 09:47 0:01 -bash 1000 10685 0.0 0.0 2008 284 pts/0 T 13:24 0:00 ./bgtest 2000 1000 10687 0.0 0.0 2008 280 pts/0 T 13:24 0:00 ./bgtest 2001 1000 10769 0.0 0.1 4944 1156 pts/0 R+ 13:43 0:00 ps -u
在我們使用命令“ps -u”查看當前用戶進程時,可以發現任務3已經被殺死了。
6 殺死後台進程
我們知道,可以利用“kill 進程號”的方式來殺死正在運行的進程,但是對於暫停的進程能不能起作用呢?我們做了如下嘗試,結果發現任務2並沒有被殺死。
linuxidc@linuxidc:~/Documents/Shell$ kill 10687 linuxidc@linuxidc:~/Documents/Shell$ ps -u Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 1000 9301 0.0 0.6 9868 6332 pts/0 Ss 09:47 0:01 -bash 1000 10685 0.0 0.0 2008 284 pts/0 T 13:24 0:00 ./bgtest 2000 1000 10687 0.0 0.0 2008 280 pts/0 T 13:24 0:00 ./bgtest 2001 1000 10780 0.0 0.1 4944 1156 pts/0 R+ 13:45 0:00 ps -u
由此,我們只能夠先使用fg命令將進程放到前台執行,然後再使用Ctrl+C來殺死該前台進程。