歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> SHELL編程

linuxshell編程指南第二十六章------shell工具

任何腳本都應該能夠創建臨時文件或日志文件。在運行腳本做備份時,最好是保存一個日志文件。這些日志文件通常在文件系統中保留幾周,過時將被刪除。

在開發腳本的時候,可能總要創建一些臨時的文件。在正常運行腳本的時候,也要使用臨時文件保存信息,以便作為另外一個進程的輸入。可以使用cat命令來顯示一個臨時文件的內容或把它打印出來。

在創建日志文件時,最好能夠使它具有唯一性,可以按照日志文件創建的日期和時間來識別這些文件。我們可以使用date命令做到這一點。這樣就能夠使日期和時間成為日志文件名中的一部分。

為了改變日期和時間的顯示格式,可以使用如下的命令:
date option + %format

使用加號‘+’可以設置當前日期和時間的顯示格式。下面的例子將日期以日、月、年的格式顯示:

注意,如果希望在日期和時間的顯示中包含空格,要使用雙引號。
[root@localhost huangcd]# date +%d%m%y
141213
[root@localhost huangcd]# date +%d-%m-%y
14-12-13
[root@localhost huangcd]# date +%A%e" "%B" "%Y
星期六14 十二月 2013
[root@localhost huangcd]# date +%R
09:29
[root@localhost huangcd]# date +%T
09:30:05

在文件名中含有日期的一個簡單辦法就是使用置換。把含有你所需要的日期格式的變量附加在相應的日志文件名後面即可。

在下面的例子中我們創建了兩個日志文件,一個使用了d d,m m,y y的日期格式,另一個使用了d d,h h,m m的時間格式。
[root@localhost huangcd]# ls -al |grep "mylog*"
-rw-r--r-- 1 root root 0 12-14 09:38 mylog1.141213
-rw-r--r-- 1 root root 0 12-14 09:37 mylog2.1409:37
-rw-r--r-- 1 root root 0 12-14 09:38 mylog2.1409:38
[root@localhost huangcd]# cat log
#!/bin/bash
MYDATE=`date +%d%m%y`
LOGFILE=/home/huangcd/mylog1.$MYDATE
>$LOGFILE
MYTIME=`date +%d%R`
LOGFILE2=/home/huangcd/mylog2.$MYTIME
>$LOGFILE2

在本書的前面討論特殊變量時,曾介紹變量$ $,該變量中保存有你所運行的當前進程的進程號。可以使用它在我們運行的腳本中創建一個唯一的臨時文件,因為該腳本在運行時的進程號是唯一的。我們只要創建一個文件並在後面附加上$ $即可。在腳本結束時,只需刪除帶有$ $擴展的臨時文件即可。S h e l l將會把$ $解析為當前的進程號,並刪除相應的文件,而不會影響以其他進程號做後綴的文件。

下面的例子中,創建了兩個臨時文件,並進行了相應的操作,最後在結束時刪除了這些文件。
[root@localhost huangcd]# echo $$
7771
[root@localhost huangcd]# ls -al |grep "hold*"
-rw-r--r-- 1 root root 77 12-14 09:45 hold1.12461
-rw-r--r-- 1 root root 77 12-14 09:45 hold2.12461
[root@localhost huangcd]# cat tempfiles
#!/bin/bash
HOLD1=/home/huangcd/hold1.$$
HOLD2=/home/huangcd/hold2.$$
df -tk >$HOLD1
cat $HOLD1 >$HOLD2
#rm /home/huangcd/*.$$

記住,該進程號只在當前進程中唯一。例如,如果我再次運行上面的腳本,將會得到一個新的進程號,因為我已經創建了一個新的進程。
\

如果文件有特殊用途的話,那麼創建含有日期的文件,就可以使你很容易地查找到它們。而且還可以很容易地按照日期刪除文件,因為這樣一眼就能看出哪個文件是最新的,哪個文件是最“舊”的。

信號就是系統向腳本或命令發出的消息,告知它們某個事件的發生。這些事件通常是內存錯誤,訪問權限問題或某個用戶試圖停止你的進程。信號實際上是一些數字。下表列出了最常用的信號及它們的含義還有信號0,我們前面在創建. logout文件時已經遇到過。該信號為“退出shell”信號。為了發出信號0,只要從命令行鍵入exit,或在一個進程或命令行中使用<CTRL-D>即可。

發送信號可以使用如下的格式:
kill [-signal no:| signal name] process ID

使用kill命令時不帶任何信號或名字意味著使用缺省的信號15。

可以使用如下的命令列出所有的信號:
[root@localhost huangcd]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

發送信號1將使一個進程重新讀入配置文件。例如,你在運行域名服務(DNS)守護進程named,現在你對域名數據庫文件做了某些修改,這時不需要殺死該守護進程重新啟動,只需使用kill -1命令向其發送信號1。Named進程將重新讀入它的配置文件。

如果系統不支持ps -ef命令,那麼可以使用ps xa。為了殺死該進程,我可以使用下面的兩種方法之一:
kill -9 157


kill -s SIGKILL 157

在有些系統中,不必使用- s,例如:kill SIGKILL 157。

有些信號可以被應用程序或腳本捕獲,並依據該信號采取相應的行動。另外一些信號不能被捕獲。例如,如果一個命令收到了信號9,就無法再捕捉其他信號。

在編寫s h e l l腳本時,只需關心信號1、2、3和1 5。當腳本捕捉到一個信號後,它可能會采取下面三種操作之一:

1) 不采取任何行動,由系統來進行處理。

2) 捕獲該信號,但忽略它。

3) 捕獲該信號,並采取相應的行動。

大多數的腳本都使用第一種處理方法,這也是到目前為止本書中所有腳本所采取的處理方法。

trap可以使你在腳本中捕捉信號。該命令的一般形式為:
trap name signal(s)

其中,name是捕捉到信號以後所采取的一系列操作。實際生活中, name一般是一個專門用來處理所捕捉信號的函數。Name需要用雙引號(“ ”)引起來。Signal就是待捕捉的信號。

腳本在捕捉到一個信號以後,通常會采取某些行動。最常見的行動包括:

1) 清除臨時文件。

2) 忽略該信號。

3) 詢問用戶是否終止該腳本的運行。

下表列出了一些最常見的trap命令用法:

trap "" 23 忽略信號2和信號3,用戶不能終止該腳本

trap "commands" 2 3 如果捕捉到信號2或3,就執行相應的commands命令

trap 23 復位信號2和3,用戶可以終止該腳本

也可以使用單引號(‘’)來代替雙引號(“”);其結果是一樣的。

下面的例子一經運行就開始計數直至用戶按<Ctrl-C>(信號2)。這時該腳本將會顯示出當前的循環數字,然後退出。

在本例中t r a p命令的格式為:
trap "do_something" signal no:(s)

下面就是該腳本:
[root@localhost huangcd]# sh trap1
1
2
3
4
you just hit ctrl+d ,at number 4
I will now exit
[root@localhost huangcd]# cat trap1
#!/bin/bash
trap "my_exit" 2
LOOP=0
my_exit()
{
echo "you just hit ctrl+d ,at number $LOOP"
echo "I will now exit"
exit 1
}
while :
do
LOOP=`expr $LOOP + 1`
echo $LOOP
sleep 3
done

在下面的例子中,在腳本捕捉到信號2後將會向用戶提供一個選擇,詢問用戶是否真的要退出。這裡使用case語句來決定采取何種操作。

如果用戶希望退出,他或她可以選擇1,此時當前函數會以狀態1退出,而另一個清除進程將會據此啟動。如果用戶並不希望退出,那麼可以選擇2或不做任何選擇,此時case語句將會使用戶退回到腳本中原來的地方。在case語句中一定要包含用戶輸入空字符串的情況。
下面的函數在收到信號後,將會向用戶提供選擇:

當上面的腳本運行時,只要在輸入任何域時按下<CTRL-C>,就會得到一個選擇:是繼續運行還是退出。
[root@localhost huangcd]# cat trap4
#!/bin/bash
trap "my_exit" 1 2 3 15
LOOP=0
HOLD1=/home/huangcd/HOLD1.$$
HOLD2=/home/huangcd/HOLD2.$$
my_exit()
{
echo -e "\nRecieved interrupt....."
echo "Do you wish to really exit???"
echo "Y:yes"
echo "N:no"
echo -n "Your choice [Y..N]>"
read ANS
case $ANS in
Y|y) exit 1;;
N|N) ;;
esac
}
echo -n "Enter your name:"
read NAME
echo -n "Enter your age:"
read AGE
[root@localhost huangcd]# sh trap4
Enter your name:huang chengdu
Enter your age:24
[root@localhost huangcd]# sh trap4
Enter your name:huang
Enter your age:
Recieved interrupt.....
Do you wish to really exit???
Y:yes
N:no
Your choice [Y..N]>y
[root@localhost huangcd]# sh trap4
Enter your name:
Recieved interrupt.....
Do you wish to really exit???
Y:yes
N:no
Your choice [Y..N]>n
huang
Enter your age:12

下面的腳本是另一個捕獲信號的例子。該腳本名為lockit,它將使用一個連續不斷的while循環鎖住終端。在該腳本中, trap命令捕捉信號2、3和1 5。如果一個用戶試圖中斷該腳本的運行,將會得到一個不成功的提示。

在腳本初次執行時,將會被提示輸入一個口令。在解鎖終端時沒有任何提示,可以直接輸入口令並按回車鍵。該腳本會從終端讀入所輸入的口令,並與預先設置的口令做比較,如果一致就解鎖終端。

如果忘記了自己的口令,那麼只好登錄到另一個終端上並殺死該進程。在本例中沒有對口令的長度加以限制—這完全取決於你。

如果你從另外一個終端上殺死了該進程,當再次回到這個終端時,可能會遇到終端設置問題,例如回車鍵不起作用。這時可以試著使用下面的命令,這樣可以解決大部分問題。
$ stty sane

下面就是該腳本。
[root@localhost huangcd]# cat lockit
#!/bin/bash
trap "nice_try" 2 3 15
TTY=`tty`
nice_try()
{
echo "Nice try,the terminal stays locked"
}
SAVEDSTTY=`stty -g`
stty -echo
echo -n "Enter your password to lock $TTY:"
read PASSWORD
echo -n "starting\n"
while :
do
read RESPONSE
if [ "$RESPONSE" = "$PASSWORD" ]
then
echo "unlocking"
break
fi
echo "wrong password and terminal is locked"
done
stty $SAVEDSTTY
[root@localhost huangcd]# sh lockit
Enter your password to lock /dev/pts/1:starting\nwrong password and terminal is locked
unlocking

Copyright © Linux教程網 All Rights Reserved