天天看點

linux shell程式設計指南第二十六章------shell 工具1

在使用者登入時,系統将會執行/ e t c / p r o f i l e檔案,根使用者不希望其他普通使用者打斷這一程序。

他通常通過設定t r a p來屏蔽信号1、2、3和1 5,然後在使用者讀當天的消息時重新打開這些信号。

最後仍然回到屏蔽這些信号的狀态。

在編寫腳本時也可以采用類似的辦法。在腳本運作的某些關鍵時刻,比如打開了很多文

件時,不希望該腳本被中斷,以免破壞這些檔案。通過設定t r a p來屏蔽某些信号就可以解決這

個問題。在這些關鍵性的處理過程結束後,再重新打開信号。

忽略信号的一般格式為(信号9除外):

trap""signal no:(s)

注意,在雙引号之間沒有任何字元,為了重新回到捕捉信号的狀态,可以使用如下的命

令:

trap"do something" signal no:(s)

下面我們來總結一下上述方法。

trap ""1 2 3 15:忽略信号。

關鍵性的處理過程

trap"my_exit" 1 2 3 15:重新回到捕捉信号的狀态,在捕捉到信号後調用m y e x i t函數。

下面就是一個這樣的例子,其中的“關鍵”過程實際上是一個w h i l e循環,但它能夠很好

地說明這種方法。在第一個循環中,通過設定t r a p來屏蔽信号,但是在第二個例子中,又回到

捕捉信号的狀态。

兩個循環都隻數到6,不過在循環中使用了一個s l e e p指令,這樣就可以有充分的時間來實

驗中斷該循環。

下面就是腳本。

[[email protected] huangcd]# cat trap_ignore 

#!/bin/bash

trap "" 1 2 3 15

LOOP=0

my_exit()

{

  echo "Received interrupt on count $LOOP"

  echo "Now exiting"

  exit 1

}

LOO=0

while :

do

  LOOP=`expr $LOOP + 1`

  echo "critical processing..$LOOP..you cannot interrupt me"

  sleep 1

  if [ "$LOOP" -eq 6 ]

     then

     break

  fi

done

LOOP=0

trap "my_exit"  1 2 3 15

while :

do

  LOOP=`expr $LOOP + 1`

  echo "no-critical processing..$LOOP..interrupt me if you want"

  sleep 1

  if [ "$LOOP" -eq 6 ]

     then

     break

  fi

done

[[email protected] huangcd]# sh trap_ignore 

critical processing..1..you cannot interrupt me

critical processing..2..you cannot interrupt me

critical processing..3..you cannot interrupt me

critical processing..4..you cannot interrupt me

critical processing..5..you cannot interrupt me

critical processing..6..you cannot interrupt me

no-critical processing..1..interrupt me if you want

Received interrupt on count 1

Now exiting

e v a l指令将會首先掃描指令行進行所有的置換,然後再執行該指令。該指令适用于那些一

次掃描無法實作其功能的變量。該指令對變量進行兩次掃描。這些需要進行兩次掃描的變量

有時被稱為複雜變量。不過我覺得這些變量本身并不複雜。

e v a l指令也可以用于回顯簡單變量,不一定是複雜變量。

[[email protected] huangcd]# NAME=honeysuckle

[[email protected] huangcd]# eval echo $NAME

honeysuckle

[[email protected] huangcd]# echo $NAME

honeysuckle

我們首先建立一個名為t e s t f的小檔案,在這個小檔案中含有一些文本。接着,将cat testf

賦給變量M Y F I L E,現在我們e c h o該變量,看看是否能夠執行上述指令。

[[email protected] huangcd]# cat testf

May Day, May Day

Going Down

現在我們将cat testf賦給變量M Y F I L E。

[[email protected] huangcd]# MYFILE="cat testf"

[[email protected] huangcd]# echo $MYFILE

cat testf

[[email protected] huangcd]# eval $MYFILE

May Day, May Day

Going Down

從上面的結果可以看出,使用e v a l指令不但可以置換該變量,還能夠執行相應的指令。第

一次掃描進行了變量置換,第二次掃描執行了該字元串中所包含的指令cat testf。

e v a l指令還可以用來顯示出傳遞給腳本的最後一個參數。現在來看下面的這個例子。

[[email protected] huangcd]# cat evalit 

#!/bin/bash

echo "Total number of arguments passed is $#"

echo "The process ID IS $$"

echo "Last argument is "$(eval echo \$$#)

[[email protected] huangcd]# sh evalit huang cheng du

Total number of arguments passed is 3

The process ID IS 5351

Last argument is du

可以給一個值一個變量名。下面我對此做些解釋,假定有一個名為d a t a的檔案:

[[email protected] huangcd]# cat data

PC                  486

MONITOR     svga

NEWWORD  yes

你希望該檔案中的第一列成為變量名,第二列成為該變量的值,這樣就可以:

我們用d a t a檔案的第一行來解釋上述腳本的執行過程,該腳本讀入“ P C”和“4 8 6”兩個

詞,把它們分别賦給變量N A M E和T Y P E。E v a l指令的第一次掃描把N A M E和T Y P E分别置換

為“P C”和“4 8 6”,第二次掃描時将P C作為變量,并将“4 8 6”作為變量的值。

下面是運作上述腳本的結果:

[[email protected] huangcd]# cat eval_it

#!/bin/bash

while read NAME TYPE

do

  eval `echo "${NAME}=${TYPE}"`

done < data

echo "you have a $PC,with a $MONITOR monitor"

echo "and are you network?$NEWWORK"

[[email protected] huangcd]# sh eval_it

you have a 486,with a svga monitor

and are you network?yes

系統中含有相當多的日志檔案。其中的一個日志檔案叫作m e s s a g e s,它通常位于/ v a r / a d m

或/ v a r / l o g目錄下。一個名為s y s l o g的配置檔案可以用來定義記錄在m e s s a g e s檔案中的消息,這

些消息有一定的格式。如果想知道系統中的相應配置,可以檢視/ e t c / s y s l o g . c o n f檔案。該檔案

中包含了用于發送各種不同類型消息的工具及它們的優先級。

這裡我們并不想深入探讨U N I X和L I N U X是如何向該檔案中記錄資訊的。我們現在隻要知

道這些消息有不同的級别,從資訊性的消息到關鍵性的消息。

還可以使用l o g g e r指令向該檔案發送消息。在使用該指令之前,最好查閱連機手冊,因為

在不同供應商所提供的作業系統上該指令的文法也有所不同。

不過,由于這裡隻涉及到資訊性的消息,是以不必擔心下面的指令不安全。

你可能會出于下列的原因向該檔案中發送消息:

• 在某一個特定的時間段出現的通路或登入。

• 你的某些執行關鍵任務的腳本運作失敗。

• 監控腳本的報告。

下面是/ v a r / a d m / m e s s a g e s檔案的例子。在系統上所看到的相應檔案可能和下面的例子有

少許差别。

[[email protected] huangcd]# cat /var/log/messages|more

Dec 11 09:49:29 localhost syslogd 1.4.1: restart.

Dec 11 09:49:44 localhost vmsvc[3122]: [ warning] [guestinfo] RecordRoutingInfo:

 Unable to collect IPv4 routing table. 

Dec 11 09:50:44 localhost last message repeated 2 times

Dec 11 09:52:14 localhost last message repeated 3 times

Dec 11 09:53:44 localhost last message repeated 3 times

Dec 11 09:55:14 localhost last message repeated 3 times

Dec 11 09:56:44 localhost last message repeated 3 times

Dec 11 09:58:14 localhost last message repeated 3 times

Dec 11 09:59:44 localhost last message repeated 3 times

Dec 11 10:01:14 localhost last message repeated 3 times

Dec 11 10:02:44 localhost last message repeated 3 times

Dec 11 10:04:14 localhost last message repeated 3 times

Dec 11 10:05:44 localhost last message repeated 3 times

l o g g e r指令的一般形式為:

logger -p -I message

其中:

- p:為優先級,這裡隻涉及到提示使用者注意的優先級,這也是預設值。

- i:在每個消息中記錄發送消息的程序号。

可以使用如下指令向message檔案寫入一下資料,可能要幾分鐘以後才能看到:

[[email protected] huangcd]# logger -p notice "this id a test message.ignore $LOGNAME"

[[email protected] huangcd]# tail /var/log/messages

Dec 15 18:02:47 localhost syslogd 1.4.1: restart.

Dec 15 18:03:00 localhost vmsvc[3157]: [ warning] [guestinfo] RecordRoutingInfo: Unable to collect IPv4 routing table. 

Dec 15 18:04:00 localhost last message repeated 2 times

Dec 15 18:04:02 localhost root: this id a test message.ignore root

如你所見,發送這一消息的使用者也被記錄了下來。

向日志檔案中發送資訊的一個更為合理的用途就是用于腳本非正常退出時。如果希望向

日志檔案中發送消息,隻要在捕獲信号的退出函數中包含l o g g e r指令即可。

在下面的清除腳本中,如果該腳本捕獲到信号2、3或1 5的話,就向該日志檔案發送一個

消息。

[[email protected] huangcd]# cat cleanup1

#!/bin/bash

trap "my_exit" 2 3 15

my_exit()

{

  logger -p notice "`basename $0`:was killed whilst cleaning up system log"

  exit 1

}

while [ "1" -lt "2" ]

do

  sleep 1

done

[[email protected] huangcd]# sh cleanup1

[[email protected] huangcd]# cat /var/log/messages

Dec 15 18:02:47 localhost syslogd 1.4.1: restart.

Dec 15 18:03:00 localhost vmsvc[3157]: [ warning] [guestinfo] RecordRoutingInfo: Unable to collect IPv4 routing table. 

Dec 15 18:04:00 localhost last message repeated 2 times

Dec 15 18:04:02 localhost root: this id a test message.ignore root

Dec 15 18:04:30 localhost vmsvc[3157]: [ warning] [guestinfo] RecordRoutingInfo: Unable to collect IPv4 routing table. 

Dec 15 18:20:30 localhost last message repeated 3 times

Dec 15 18:21:00 localhost vmsvc[3157]: [ warning] [guestinfo] RecordRoutingInfo: Unable to collect IPv4 routing table. 

Dec 15 18:21:06 localhost root: cleanup1:was killed whilst cleaning up system log

Dec 15 18:21:30 localhost vmsvc[3157]: [ warning] [guestinfo] RecordRoutingInfo: Unable to collect IPv4 routing table. 

Dec 15 18:21:37 localhost root: cleanup1:was killed whilst cleaning up system log

繼續閱讀