知识屋:更实用的电脑技术知识网站
所在位置:首页 > 操作系统 > linux

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

发布时间:2014-09-05 13:34:31作者:知识屋

任何脚本都应该能够创建临时文件或日志文件。在运行脚本做备份时,最好是保存一个日志文件。这些日志文件通常在文件系统中保留几周,过时将被删除。

在开发脚本的时候,可能总要创建一些临时的文件。在正常运行脚本的时候,也要使用临时文件保存信息,以便作为另外一个进程的输入。可以使用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

(免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)
收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜