歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> linux shell編程指南------shell工具

linux shell編程指南------shell工具

日期:2017/3/1 13:50:55   编辑:SHELL編程

在用戶登錄時,系統將會執行/etc/profile文件,根用戶不希望其他普通用戶打斷一進程。他通常通過設置trap來屏蔽信號1、2、3和1 5,然後在用戶讀當天的消息時重新打開這些信號。最後仍然回到屏蔽這些信號的狀態。

在編寫腳本時也可以采用類似的辦法。在腳本運行的某些關鍵時刻,比如打開了很多文件時,不希望該腳本被中斷,以免破壞這些文件。通過設置trap來屏蔽某些信號就可以解決這個問題。在這些關鍵性的處理過程結束後,再重新打開信號。

忽略信號的一般格式為(信號9除外):
trap""signal no:(s)

注意,在雙引號之間沒有任何字符,為了重新回到捕捉信號的狀態,可以使用如下的命令:
trap"do something" signal no:(s)

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

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

關鍵性的處理過程trap"my_exit" 1 2 3 15:重新回到捕捉信號的狀態,在捕捉到信號後調用myexit函數。下面就是一個這樣的例子,其中的“關鍵”過程實際上是一個while循環,但它能夠很好地說明這種方法。在第一個循環中,通過設置trap來屏蔽信號,但是在第二個例子中,又回到捕捉信號的狀態。

兩個循環都只數到6,不過在循環中使用了一個sleep命令,這樣就可以有充分的時間來實驗中斷該循環。

下面就是腳本。
[root@localhost 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
[root@localhost 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

eval命令將會首先掃描命令行進行所有的置換,然後再執行該命令。該命令適用於那些一次掃描無法實現其功能的變量。該命令對變量進行兩次掃描。這些需要進行兩次掃描的變量有時被稱為復雜變量。不過我覺得這些變量本身並不復雜。

eval命令也可以用於回顯簡單變量,不一定是復雜變量。
[root@localhost huangcd]# NAME=honeysuckle
[root@localhost huangcd]# eval echo $NAME
honeysuckle
[root@localhost huangcd]# echo $NAME
honeysuckle

我們首先創建一個名為testf的小文件,在這個小文件中含有一些文本。接著,將cat testf0賦給變量MYFILE,現在我們echo該變量,看看是否能夠執行上述命令。

[root@localhost huangcd]# cat testf
May Day, May Day
Going Down

現在我們將cat testf賦給變量M Y F I L E。
[root@localhost huangcd]# MYFILE="cat testf"
[root@localhost huangcd]# echo $MYFILE
cat testf
[root@localhost huangcd]# eval $MYFILE
May Day, May Day
Going Down

從上面的結果可以看出,使用eval命令不但可以置換該變量,還能夠執行相應的命令。第一次掃描進行了變量置換,第二次掃描執行了該字符串中所包含的命令cat testf。

eval命令還可以用來顯示出傳遞給腳本的最後一個參數。現在來看下面的這個例子。
[root@localhost huangcd]# cat evalit
#!/bin/bash
echo "Total number of arguments passed is $#"
echo "The process ID IS $$"
echo "Last argument is "$(eval echo \$$#)
[root@localhost 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的文件:

[root@localhost huangcd]# cat data
PC 486
MONITOR svga
NEWWORD yes

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

我們用data文件的第一行來解釋上述腳本的執行過程,該腳本讀入“PC”和“486”兩個詞,把它們分別賦給變量NAME和TYPE。Eval命令的第一次掃描把NAME和TYPE分別置換為“PC”和“486”,第二次掃描時將PC作為變量,並將“486”作為變量的值。
下面是運行上述腳本的結果:
[root@localhost 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"
[root@localhost huangcd]# sh eval_it
you have a 486,with a svga monitor
and are you network?yes

系統中含有相當多的日志文件。其中的一個日志文件叫作messages,它通常位於/var/adm或/var/log目錄下。一個名為syslog的配置文件可以用來定義記錄在messages文件中的消息,這些消息有一定的格式。如果想知道系統中的相應配置,可以查看/etc/syslog.conf文件。該文件中包含了用於發送各種不同類型消息的工具及它們的優先級。

這裡我們並不想深入探討UNIX和LINUX是如何向該文件中記錄信息的。我們現在只要知道這些消息有不同的級別,從信息性的消息到關鍵性的消息。

還可以使用logger命令向該文件發送消息。在使用該命令之前,最好查閱連機手冊,因為在不同供應商所提供的操作系統上該命令的語法也有所不同。

不過,由於這裡只涉及到信息性的消息,因此不必擔心下面的命令不安全。

你可能會出於下列的原因向該文件中發送消息:

在某一個特定的時間段出現的訪問或登錄。

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

監控腳本的報告。

下面是/ v a r / a d m / m e s s a g e s文件的例子。在系統上所看到的相應文件可能和下面的例子有少許差別。
[root@localhost 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

logger命令的一般形式為:
logger -p -I message

其中:

- p:為優先級,這裡只涉及到提示用戶注意的優先級,這也是缺省值。

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

可以使用如下命令向message文件寫入一下數據,可能要幾分鐘以後才能看到:
[root@localhost huangcd]# logger -p notice "this id a test message.ignore $LOGNAME"
[root@localhost 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的話,就向該日志文件發送一個消息。
[root@localhost 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
[root@localhost huangcd]# sh cleanup1
[root@localhost 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

Copyright © Linux教程網 All Rights Reserved