命名管道是一種先進先出(FIFO)的數據結構,它答應兩個進程通過管道聯接實現信息交換。在Unix系統中,命名管道是一種非凡類型的文件,因此可以對命名管道進行讀寫操作;當然,同樣也會有讀寫和執行等權限的限制。 通過下面的命令可以創建一個命名管道: /etc/mknod pipe_name p 其中“pipe_name”是要創建的命名管道的名字,參數p 必須出現在命名管道名字之后。 命名管道文件被創建后,一些進程就可以不斷地將信息寫入命名管道文件里,而另一些進程也可以不斷地從命名管道文件中讀取信息。對命名管道文件的讀寫操作是可以同時進行的。下面的例子顯示命名管道的工作過程。 進程A、B、C中運行的程序只是一條簡單的echo命令,它們不斷地把信息寫入到命名管道文件/tmp/pipe1中。與此同時,程序中的“read msg” 命令不斷地從命名管道文件/tmp/pipe1中讀取這些信息,從而實現這些進程間的信息交換。 程序執行時,首先創建命名管道文件,此時程序處于等待狀態,直到A、B、C進程中某一個進程往命名管道中寫入信息時,程序才繼續往下執行。使用rm命令可以刪除命名管道文件從而清除已設置的命名管道。 下面是一個用于記錄考勤的例子: 在主機上運行的程序/tmp/text產生命名管道/tmp/pipe1,并不斷地從命名管道中讀取信息送屏幕上顯示。 /tmp/text程序: if [ ! -p /tmp/pipe1 ] then /etc/mknode /tmp/pipe1 p fi while : do read msg if [ “$msg" = “" ] then continue else echo “$msg" fi done /dev/$tty read name today=‘date’ echo “$name/t$today" done > /tmp/pipe1 當雇員從終端上輸入自己的姓名后,運行/tmp/text程序的主機將顯示類似下面的結果: wang Thu Jan 28 09:29:26 BTJ 1999 he Thu Jan 28 09:29:26 BTJ 1999 cheng Thu Jan 28 09:30:26 BTJ 1999 zhang Thu Jan 28 09:31:26 BTJ 1999 二、使用kill命令和trap語句
trap command_list signal_list command_list: 由一個或多個命令(或命令組)構成的命令列表。當命令列表中含有多個命令時要用單引號或雙引號括起來,并且各命令間要用分號隔開。 signal_list:由一個或多個信號值構成的信號列表,各信號值間要用空格分開。 在一個shell程序(父程序)中重新設置信號的陷阱并不改變被這個程序所調用的子程序中同名信號的陷阱。同樣,在子程序中設置的信號陷阱也不影響父程序中同名信號的陷阱。 shell在讀取trap語句時,要掃描一次命令列表,以便設置陷阱。在捕捉信號后,shell再次掃描命令 列表,執行已設置好的陷阱程序(命令或命令組)。因此,假如命令列表中含有變量置換或命令置換表達 式,shell在第一次掃描命令列表時就會用當前的變量值或命令結果置換這些表達式,使得在捕捉到信號而 去執行陷阱程序時,陷阱程序已經不是原來設置的陷阱程序了。為了避免這種情況發生,使用單引號而不是 使用雙引號把trap語句中含有變量置換或命令置換表達式的命令列表括起來;因為單引號可以消除所有字符 的非凡含義,這樣避免了shell在第一次掃描時執行任何置換或替代操作,直到命令列表被執行時才進行置換或替代。 向一個程序或進程傳遞信號方法很多,比如在程序執行時按下Ctrl+c鍵或Del鍵,將向程序傳遞一個SIGINT信號,執行該信號的系統陷阱將終止程序執行。使用kill命令傳遞信號是shell語言編程中最為常用 的方法。 kill命令的基本格式是: kill [ - signal ] PID 通常kill命令用來終止一個進程。但假如使用了帶有短劃線“-”的信號作為參數時,kill命令就發送 該信號給PID指示的一個或多個進程,而不是終止進程。當trap語句捕捉到這個信號后便執行設定的信號陷程序,實現進程間的相互通訊。 下面的例子顯示了程序master和slave1、slave2間如何利用信號機制實現相互通訊的。首先在后臺運行 程序slave1和slave2,然后運行程序master。在文件/tmp/PRo_list中記錄了這三個程序的進程號。 程序slave1首先設置信號15的陷阱,然后把自己的當前進程寫入文件/tmp/pro_list;在獲得master進號后,進入循環狀態。當接收到master發出的信號15時,執行陷阱程序,顯示相關信息后,向master發出信15。 程序slave2執行情況與slave1相似。 程序master也是首先設置信號15的陷阱,然后把自己的當前進程寫入文件/tmp/pro_list。在取得所有 slave程序進程號后,向這些slave程序發出信號15,然后進入循環等待。當接收到slave1或slave2發出的信 br> 號15時,執行陷阱程序,顯示相關信息,殺死所有slave進程,清空文件/tmp/pro_list,然后退出。 程序/tmp/slave1: slave() { echo “slave1 has received sighal from master" echo “Request master to kill slave1 process" kill -15 $master_pid } trap slave 15 echo “slave1_pid $$" >> /tmp/pro_list sleep 1 while : do master_pid=‘awk ’$1 ~/master/ {print $2}‘/tmp/pro_list’ if [ “$master_pid" != “" ] then break fi done while : do sleep 1 done 程序/tmp/slave2: slave() { echo “slave2 has received sighal from master" echo “Request master to kill slave2 process" kill -15 $master_pid } trap slave 15 echo “slave2_pid $$" >> /tmp/pro_list sleep 1 while : do master_pid=‘awk ’$1 ~/master/ {print $2}‘/tmp/pro_list’ if [ “$master_pid" != “" ] then break fi done while : do sleep 1 done 程序/tmp/master: kill_slave() { echo “Master has received signals from slave processes" echo “End all slave processes" kill -9 $slave_list >/tmp/pro_list exit 0 } trap kill_slave 15 echo “master_pid $$" >> /tmp/pro_list sleep 1 slave_list=‘awk ’$1 ~/slave/ {print $2}‘/tmp/pro_list’ echo “Current slave processes are:" echo “$slave_list" kill -15 $slave_list while : do sleep 1 done 執行程序: $ cd /tmp $ ./slave1& 15638 $ ./slave2& 16831 $ ./master Current slave processes are: 15638 16831 slave1 has received signal 15 from master Request master to kill slave1 process slave2 has received signal 15 from master Request master to kill slave2 process Master has received signals from slave processes End all slave processes 15638 Killed 16831 Killed $ 三、使用點命令“.”
“.”點命令是shell的一個內部命令,它從指定的shell 文件中讀入所有命令語句并在當前進程中執行。 因此當多個shell進程(父子進程或無關進程均可)共享一組變量值時,就可以將這些變量賦值語句定義到一個shell文件里,并在需要這些變量值的程序中使用點語句來引用這個shell文件,從而實現變量值共享(對這些變量值的修改僅涉及到這個shell文件)。但要注重的是,這個shell文件不能包括含有位置參數的語句,即不能接受$1、$2等命令行參數。 下面是一個在超市中發布每日商品價格的示范程序片段。發布每日商品價格統一由程序/tmp/jiage來執行,它為每種商品價格賦值,并把相應的賦值語句寫入文件/tmp/jiagebiao中。在各終端上運行的收款程序/tmp/shoukuan將讀入文件 /tmp/jiagebiao中所有賦值語句并在當前進程中執行,從而獲取在 程序/tmp/jiage中設定的價格。 價格設定程序/tmp/jiage: echo “Enter the price of chicken, dUCk and fish: /c" read chicken duck fish exec 3>/tmp/jiagebiao echo “chicken_price=$chicken" >&3 echo “duck_price=$duck" >&3 echo “fish_price=$fish" >&3 執行/tmp/jiage程序后,文件/tmp/jiagebiao中將有如下內容: chicken_price=5.4 duck_price=2.5 fish_price=4.2 收款程序/tmp/shoukuan: . /tmp/jiagebiao count=0 while : do echo “Enter the trade name and quantities or input q to sum: /c" read trade$count quantity$count eval a=/$trade$count if [ “$a" = “q" ] then if [ $count -gt 0 ] then count=‘expr $count - 1’ fi break fi count=‘expr $count + 1 ’ done echo “/n‘date’" echo “trade name/tquantity/tsum" while [ “$count" -ge 0 ] do eval trade=“/${trade$count}" eval trade_price=“${trade}_price" eval danjia=/${$trade_price} eval quantity=“/${quantity$count}" sum=‘echo “scale=2; $danjia *$quantity"bc’ echo “$trade/t/t$quantity/t/t$sum" count=‘expr $count - 1 ’ done 在終端上執行程序/tmp/shoukuan將有如下顯示: Enter the trade name and quantities or input q to sum: chicken 2 Enter the trade name and quantities or input q to sum: fish 3 Enter the trade name and quantities or input q to sum: duck 4 Enter the trade name and quantities or input q to sum: q Thu Jan 28 09:29:29 BJT 1999: duck 4 10 fish 3 12.6 chicken 2 10.8 四、使用export語句
通常shell變量是局部變量,無論是通過賦值操作還是通過命令賦值,其變量值只在當前進程中有效。但是經過export語句說明的shell變量就成為一個全局性變量,其變量名和變量值可以傳遞給子進程及其后代進程。在子進程中可以修改這個變量的值,但并不影響這個變量在父進程中的取值。 下面的例子中,父進程(/tmp/text)將賦值后的變量 pro_name傳遞給子進程(/tmp/text_child), 在子進程中對變量pro_name所賦的新值并不影響父進程中該變量的值。 /tmp/text程序: pro_name=“PARENT" echo “The variable pro_name is $pro_name in parent process" export pro_name /tmp/text_child echo “The variable pro_name is $pro_name after retund to parent process" /tmp/text_child程序: echo“The variable pro_name ($pro_name) is transmited to child process" pro_name=“CHILD" echo “To change the variable pro_name to $pro_name in child process" 執行程序/tmp/text: $ /tmp/text The variable pro_name is PARENT in parent process The variable pro_name (PARENT) is transmited to child process To change the variable pro_name to CHILD in child process The variable pro_name is PARENT after retund to parent process $ right">(出處:清風軟件下載學院)