farmer-logo.gif (14959 bytes) cshell-logo.gif (19625 bytes)
ch-3.gif (10141 bytes)
main-b.gif (271 bytes)
 

 

3-7-3 背景工作的控制管理

當我們將數個工作放到背景工作執行時,我們要如何去管理這些背景工作呢?又如何知道背景工作的執行情況?如何終止或暫時停止背景工作的執行?不要急先讓我們來丟幾個指令到背景工作去執行,再來逐一說明:

6 % du -a /user > user.data &
[1] 237
7 % find / -name core -type f -ls > core.data &
[2] 238
8 % grep '^[^:]*::' /etc/passwd > nopasswd &
[3] 239

如上我們將 3 個指令放到背景(background)中執行。用指令 jobs -l 顯示背景工作的執行情況如下:

% jobs -l
[1] + 237 Running du -a /user > user.data
[2] - 238 Running find / -name core -type f -ls > core.data
[3] 239 Running grep '^[^:]*::' /etc/passwd > nopasswd

首先我們為你介紹一個工作控制特有的名辭:current job。再上例中的 current job 是相信讀者一定能一眼看出是“du -a /user > user.data”,也就是背景工作號碼“[1]”。如果當第一個背景工作順利執行完畢,第二個與第三個背景工作均還在執行中時,current job 便會自動變成是背景工作號碼“[2]”的背景工作。所以 current job 是會變動的。當你下 fg、bg、stop 等指令時,如果不加任何引數則所變動的均是 current job,關於這點在下指令時千萬得注意。同時代表 current job 的特殊符號也有是多個如“%”“%+”或“%%”,選一個習慣的運用便可。

管理背景工作處理程序

終止背景工作

指令總是有下錯或下了而又發覺不必要了的時候,當這樣的情況,當這樣的指令是產生在已執行的背景工作時,你可用 C Shell 的內建指令 kill來終結它,而且還有很多種方式呢。在例子中,假如你想要“終結”背景工作“du -a /user > user.data”。見下面幾種指令 kill 的用法:

內建指令 kill 使用語法:
kill pid_number 將某個號碼的處理程序終止執行
kill % 終止執行 current job
kill %+ 同上
kill %- 終止執行 previous job
kill %m 終止執行第 m 個背景工作
kill %string 搜尋以 string 為開頭的背景工作並將它終止執行(為避免錯誤,此法少用)

瞭解上述的情況後,要終止第一個背景工作就很簡單了。隨便以底下的每一行指令均可將它終止。

% kill 237 (237為第一個背景工作的PID號碼)
% kill %1

如果想終止第二個背景工作,以下兩種方法均可。

% kill %2
% kill %-

前景、背景工作的停止及再繼續執行

有些時候在工作中,手邊正做到一半的事,時常會被打斷,要求你先處理別的事。譬如你正用 vi 編輯某個檔案或用指令 find 在整理檔案系統的過時檔案,你的主管十萬火急地跑過來,馬上要你處理一份資料,因為他的主管馬上要,人又坐在你旁邊,好罷!把正在處理的工作先佔停下來,先做他的吧。請想想,你是如何暫時停止你的工作的?在這個時候,我們可使用 control-z 來暫停工作。且我們會得到一個訊息,如下:

Stopped
20 %

暫停的工作已被 C Shell 放入背景工作中了,且保留原狀態停止執行。這時便可以馬上做你主管插入的高優先工作,假設如下:

20 % cd ~/acct
21 % lpr mooon.acct

這時候你雖然把工作目錄更改了,但其實並不要緊。你可以先用 C Shell 的內建指令 jobs 來顯示剛才被暫停的工作是第幾個背景工作,假設你就只有那一個背景工作,則你將見到類似下列的訊息:

22 % jobs
[1] + Stopped vi home.data

這時你可以不用顧慮工作目錄改變的問題,因為 C Shell 的工作控制會幫你處理的,你只管用 C Shell 的內建指令 fg 來把背景工作切換到前景來執行便可。如下:

23 % fg (註:指令後不加引數既代表current job)
vi home.data (wd: ~/test)

上面訊息“(wd: ~/test)”便是告訴你 vi 的工作目錄,請放心它絕對與你當初的工作目錄相同。這訊息出現的時間很短,馬上便回到你原來的 vi 模式中,當你編輯完後,存檔後會出現下面的訊息:

(wd now: /home1/acct)
24 %

工作目錄又回到你所改變的目錄去了。自己好好試一試,碰上時可幫你解決不少困擾。

以上為你介紹的是暫停前景工作,接下來我們來談談如何暫停背景工作的執行。 C shell 的內建指令 stop 可用來暫停背景工作。語法如下:

stop 指令使用語法:
stop % 停止第一個背景工作執行
stop %n 停止第 n 個背景工作執行

瞭解指令 stop 的語法後,你便可將想要停止的背景工作暫時停止執行,譬如你要將一份整年度的月報表用 nroff 指令整理,因為資料量龐大,所以你將它放到背景中執行。指令如下示:

% nroff -ms moonth[1-12].acct > year93.acct &
[4] 240

當你處理到一半的時候發覺 moonth12.acct 檔案是舊的需要更新,這時你用 jobs 指令查看到背景工作“[4]”還在執行中,但無法知道指令以處理到那一個月份時,你可馬上下 stop 指令,將背景工作“[4]”先暫時停止執行再說:

% stop %4

然後馬上查看檔案 year93.acct 的尾部判斷是否以處理到第 12 月份,如果還沒有執行到,馬上將 moonth12.acct 檔案資料更新。再用指令 bg 來將已被暫時停止執行的背景工作“[4]”再接著繼續執行下去。這樣非但可更正錯誤檔案,又不用將已處理完的工作放棄,重新重頭再執行一次。可說是一舉數得。這是工作控制中最令人“感激”的一項功德無量的功能。千萬不可不知。

指令 stty 設定的影響

在一般的環境下,背景工作的輸出均會直接出現在螢幕上,如果想要讓背景工作的輸出不直接插入到前景工作中,用指令 stty 來設定可解決這項問題。指令 stty 有一項參數叫“tostop”它的作用是將背景工作的輸出不直接輸出到前景去,只送出訊息告訴前景說某背景工作有輸出訊息。並且它會將那個背景工作先暫時停止執行。當你知道某背景工作有訊息輸出時,可用指令 fg 來將該背景工作叫回前景觀看其輸出訊息,同時該工作將會繼續執行。如果你想再將這個工作送回背景去執行,你可以用 control-z 先暫停,再用 bg 將該工作放入背景中繼續執行。這種運用方式僅適用於輸出訊息少的工作,訊息輸出量大且頻繁的工作可能就不適合。因為當一有訊息要輸出,該工作便會停止執行,等待你去查看後才會再繼續執行,前景、後景這樣切換多次會叫人受不了的。讓我們來看一下實際的例子:

如果你不知 stty 指令現在的設定,可用鍵入 stty 來顯示設定值,如下:

% stty
speed 38400 baud; evenp
-inpck imaxbel -tabs
iexten crt

顯示的參數中可看到並無“tostop”,於是下指令來設定它:

% stty tostop
% stty
speed 38400 baud; evenp
-inpck imaxbel -tabs
iexten crt tostop

在這樣的環境設定下,我們將一個指令放入背景中執行,如下:

% find / -name Cshrc -ls &

當背景工作找到檔案時,會在你前景出現以下的訊息:

[1] + Stopped (tty output) find / -name Cshrc -ls

這時你便可用指令 fg 將該背景工作叫回前景,便可看見輸出內容,如下示:

% fg
find / -name Cshrc -ls
24255 3 -rw-r--r-- 1 bin staff 2897 Jul 24 1992 /usr/lib/Cshrc

此時你可以將它 control-z 暫停,再以指令 bg 送回背景中執行。就可在前景繼續工作,並等待下一個輸出訊息出現。

如果你想將“tostop”這個參數去掉,指令語法如下:

% stty -tostop
% stty
speed 38400 baud; evenp
-inpck imaxbel -tabs
iexten crt

指令 notify 與預設變數 $notify 的運用

C shell 的工作控制對於背景工作的執行結果通知,通常是在前景中等待你任何一次 return 的時候,順便將訊息輸出到螢幕上。譬如當你在前景中用 vi 在 編輯檔案時,某個背景工作的執行結束了,這項訊息會一直等待你編輯完檔案退出 vi 模式後,才有機會將會訊息輸出到螢幕上。這個好處是不影響你編輯檔案,但也可能延誤你對需最優先工作的處理時效。如果你要改變這項工作控制的執行特性, C Shell 提供了內建指令 notify 與預設變數 $notify 來供你運用。先來看指令 notify 的用法。比方說你把一個指令放到背景中執行,如下:

% cc -o backup backup.c &

當指令放入背景中執行時,如果你想讓它在執行結束時馬上通知你,你可運用內建指令 notify 來做到這點,如下鍵入指令:

% notify

這時指令不加引數是因為該背景工作是 current job,如果不是 current job,你下指令時便得加背景工作號碼的引數,如下:

% notify %3 (假設背景工作號碼為3)

當你下完指令 notify 之後,便去做另一個程式的編輯工作,當該背景工作執行完畢時,如果你還未離開 vi 模式,輸出訊息便會插入螢幕中,插入的訊息僅是通知你背景工作的情況,並不會加入你的 vi buffer 中,這點請放一百個心。訊息如下:

[1] Done cc -o backup backup.c

以上是使用指令的方式,如果使用模式比較適合你的使用習慣的話,建議你不妨改用設定預設變數 $notify 的方式,將下行加入“~/.cshrc”檔案中,則你每個背景工作均會以此方式通知你其執行情況。

set notify


mail.gif (2925 bytes)

b-line.gif (2092 bytes)