Linux中國

10個 Linux/Unix下 Bash 和 KSH shell 的作業控制實例

LinuxUnix 屬於多任務的操作系統,也就是說一個系統在同一時間段內能運行多重任務(進程)。在這個新的博客系列,我將會列出相關的 LinuxUnix 作業(job)控制的命令,你可以通過這些命令在 Bash 或 Korn 還有 POSIX shell 下實現執行多重任務。

什麼是作業控制

作業控制不只是能夠停止/掛起(stop/suspend)正在執行的進程(命令),也可以繼續/喚醒(continue/resume)執行你需要的每一個進程。這完全可以用你的操作系統和 bash/ksh 之類的 shell 或 POSIX shell 完成。

誰給作業控制的提供了環境?

Bash / Korn shell,或者是 POSIX shell 提供給了作業控制的環境。

跟作業表打個招呼吧

你的 shell 會留有一張當前作業的表單,稱為作業表。當你鍵入命令時,shell 會給它分配一個 jobID(也稱作 JOBSPEC)。一個 jobID 或 JOBSPEC只是很小的整數數值。

1: 創建你的首個 Linux/Unix 作業

我要運行一個名為 xeyes 的命令,它會在屏幕上顯示兩個橢圓的眼睛,輸入: $ xeyes &

輸出樣例:

Fig.01: 在後台運行 xeyes 命令

我使用&符號讓一個 job 在後台運行。shell 會列印一行信息類似如下:

[1] 6891

在這個例子中,有兩個數字輸出,分別表示:

  • 1 : 在後台執行的 xeyes 任務的作業號為 1。
  • 6891 : 作業1的進程ID。

我在多執行一些 job:

## 啟動一個文本編輯器,X 的系統負載顯示,和 sleep 命令 ##
gedit /tmp/hello.c &
xload &
sleep 100000 &

2: 列出當前的作業

查看當前 shell 的激活的任務狀態,輸入:

$ jobs
$ jobs -l

輸出如下:

[1]   9379 Running                 xeyes &
[2]   9380 Running                 gedit /tmp/hello.c &
[3]-  9420 Running                 xload &
[4]+  9421 Running                 sleep 100000 &

簡要描述如下:

欄位 描述 示例
1 [1] jobIDJOB_SPEC - 工作號要與fg, bg, wait, kill和其他shell命令一起使用。你必須在工作號前綴添加一個百分號:(**%**)。加號 (+) 標識著默認的或是現在的作業。減號 (-) 標識著前一個作業。 %1fg %1kill %2
2 9379 進程 ID - 系統自動為每個進程創建並分配地獨有的身份標誌號。 kill 9379
3 Running 狀態 - 關於作業的狀態:**Running** - 該 作業正在運行,還沒有被外部信號掛起。**Stopped** - 該作業已經被掛起。 N/A
4 xeyes & command - 由shell給出的命令。 script &firefox url&

你也可以用 ps 命名列出當前系統正在運行的進程:

$ ps

3: 停止或掛起正在運行的作業

按下[Ctrl]-[Z]鍵或使用kill 命令,如下所示:

kill -s stop PID

舉個例子,啟動ping 命令,然後用 Ctrl-Z 鍵來停止 ping 命令作業:

Animated gif 01: 掛起 ping 命令作業

4: 在前台恢復 掛起的/停止的作業

讓我們恢復處於停止狀態下的作業,讓它回到前台繼續運行,要將其變成當前作業,必須藉助fg 命令。具體語法如下:

## ping 命令的作業號的值為5 ##
fg %5

我也可以規定命令行開端符合字元串"ping"的作業[譯註:不能出現不明確的字元串,例如如果後台有兩個 vim 進程而你敲入 fg %vim 會報錯。]:

## %String ##
fg %ping

輸出樣例:

64 bytes from www.cyberciti.biz (75.126.153.206): icmp_req=3 ttl=53 time=265 ms
64 bytes from www.cyberciti.biz (75.126.153.206): icmp_req=4 ttl=53 time=249 ms
64 bytes from www.cyberciti.biz (75.126.153.206): icmp_req=5 ttl=53 time=267 ms
^C

5: 在後台恢復 掛起/停止狀態的作業

在這個例子中,我使用yum 命令更新所有安裝在 Redhat 或 CentOS Linux 生產伺服器上的軟體包並置於後台作業。

# yum -y update &>/root/patch.log &

然而,由於一些原因(例如,過載問題)我決定停止這個作業20分鐘:

# kill -s stop %yum

輸出樣例:

[7]+  Stopped                 yum -y update &>/root/patch.log &

用 bg 重啟停止在後台的 yum 進程

現在,我將要恢復停止的 yum -y update &>/root/patch.log & 作業,鍵入:

# bg %7

或者:

# bg %yum

輸出樣例:

[7]+ yum -y update &>/root/patch.log &

6: 殺死作業/進程

殺死yum 命令進程,輸入如下kill 命令及其作業號 7:

# kill %7

或者

# kill 進程ID

輸出樣例:

[7]+  Terminated              yum -y update &>/root/patch.log &

在 Linux/FreeBSD/OS X Unix 下你也可以使用 killall 命令通過名字殺死進程或是 jobID 而不是通過 PID

7 為什麼當我登出後 shell 會清除我的所有後台作業

在這個例子中,我將會啟動 pdfwriter.py 來批量生成這個站點的 pdf 文件:

~/scripts/www/pdfwriter.py --profile=faq --type=clean --header=logo
--footer-left "nixCraft is GIT UL++++ W+++ C++++ M+ e+++ d-" 
--footer-right "Page [of] of [total]" &

一旦當我登出shell時,pdfwriter.py 作業就會被我的 shell 殺死。為了克服這個問題需要使用shell的內置命令 disown 來告訴 shell 不要發送 HUP 信號,鍵入:

$ ~/scripts/www/pdfwriter.py --profile=faq .... &
$ disown
$ exit

8 使用一個名為 nohup 的外部命令阻止在登出時殺死作業

你也可以使用nohup 命令在你退出 shell 後執行作業:

$ nohup ~/scripts/www/pdfwriter.py --profile=faq .... &
$ exit

9: 查找最後的作業的 PID

為了查找最近在後台執行的(非同步)命令的進程ID,可使用 bash shell 的特殊參數 $!

$ gedit foo.txt &
$ echo "最近在後台執行的job 的PID - $!" 

輸出樣例:

最近在後台執行的job 的PID - 9421

10: 等候作業完成

wait 命令會等候給予的進程ID 或 作業ID指定的進程,然後報告它的終止狀態。語法如下:

/path/to/large-job/command/foo &
wait $!
/path/to/next/job/that-is-dependents/on-foo-command/bar

這是我的一個工作腳本:

#!/bin/bash
# A shell script wrapper to create pdf files for our blog/faq section
########################################################################
# init() - Must be run first 
# Purpose - Create index file in $_tmp for all our wordpress databases 
########################################################################
init(){
 _php="/usr/bin/php"
 _phpargs="-d apc.enabled=0"
 _base="~/scripts"
 _tmp="$_base/tmp"
 _what="$1"
 for i in $_what
 do
        [[ ! -d "$_tmp/$i" ]] && /bin/mkdir "$_tmp/$i"
        $_php $_phpargs -f "$_base/php/rawsqlmaster${i}.php" >  "$_tmp/$i/output.txt"
 done
}

#####################################################
# Without index file, we can out generate pdf files
#####################################################
init blog

###########################################################
# Do not run the rest of the script until init() finished
###########################################################
wait $!

## Alright, create pdf files 
~/scripts/www/pdfwriter.py --profile=blog --type=clean --header=logo
--footer-left "nixCraft is GIT UL++++ W+++ C++++ M+ e+++ d-" 
--footer-right "Page [of] of [total]"

Linux 和 Unix 作業控制命令總結列表

命令 描述 示例
**&** 將作業置入後台 命令 &
**%n** 設置作業號為 n (數字)的作業 命令 %1
**%Word** 引用命令行開端包含 Word 的作業 命令 %yum
**%?Word** 引用命令行包含 Word 的作業 命令 %?ping
**%%****%+** 引用當前作業 kill %%kill %+
**%-** 引用先前作業 bg %-
**CTRL-Z**kill -s stop jobID | 掛起或停止作業 | kill -s stop %ping
**jobs**jobs -l | 列出活動的作業 | jobs -l
**bg** 將 作業置入後台 bg %1bg %ping
**fg** 將作業置入前台 fg %2fg %apt-get

關於 shell 內置命令和外部命令的小注

運行下面的 type 命令找出給予命令是否屬於內部或外部的。

type -a fg bg jobs disown

輸出樣式:

fg is a shell builtin
fg is /usr/bin/fg
bg is a shell builtin
bg is /usr/bin/bg
jobs is a shell builtin
jobs is /usr/bin/jobs
disown is a shell builtin

在幾乎所有情況下,你都需要使用 shell 的內置命令。所有外部命令例如 /usr/bin/fg 或 /usr/bin/jobs 工作在一個不同的 shell 環境下,而不能用在父 shell 的環境下。

總結

我希望你能喜歡這篇博文系列(rss 訂閱),我建議你閱讀下面的更多信息:

我會計劃在這個系列添加更多深入的教程。若果你需要看到具體的主題,請在下方評論讓我知道。

via: http://www.cyberciti.biz/howto/unix-linux-job-control-command-examples-for-bash-ksh-shell/

譯者:Luoxcat 校對:wxy

本文由 LCTT 原創翻譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國