您的位置:首页 > 运维架构 > Shell

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

2013-12-14 11:17 351 查看
任何脚本都应该能够创建临时文件或日志文件。在运行脚本做备份时,最好是保存一个

日志文件。这些日志文件通常在文件系统中保留几周,过时将被删除。

在开发脚本的时候,可能总要创建一些临时的文件。在正常运行脚本的时候,也要使用

临时文件保存信息,以便作为另外一个进程的输入。可以使用c a t命令来显示一个临时文件的

内容或把它打印出来。

在创建日志文件时,最好能够使它具有唯一性,可以按照日志文件创建的日期和时间来

识别这些文件。我们可以使用d a t e命令做到这一点。这样就能够使日期和时间成为日志文件名

中的一部分。

为了改变日期和时间的显示格式,可以使用如下的命令:

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,我们前面在创建. l o g o u t文件时已经遇到过。该信号为“退出s h e l l”信号。为

了发出信号0,只要从命令行键入e x i t,或在一个进程或命令行中使用< C T R L - D >即可。

发送信号可以使用如下的格式:

kill [-signal no:| signal name] process ID

使用k i l l命令时不带任何信号或名字意味着使用缺省的信号1 5。

可以使用如下的命令列出所有的信号:

[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将使一个进程重新读入配置文件。例如,你在运行域名服务( D N S)守护进程

n a m e d,现在你对域名数据库文件做了某些修改,这时不需要杀死该守护进程再重新启动,只

需使用kill -1命令向其发送信号1。N a m e d进程将重新读入它的配置文件。

如果系统不支持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) 捕获该信号,并采取相应的行动。

大多数的脚本都使用第一种处理方法,这也是到目前为止本书中所有脚本所采取的处理

方法。

t r a p可以使你在脚本中捕捉信号。该命令的一般形式为:

trap name signal(s)

其中,n a m e是捕捉到信号以后所采取的一系列操作。实际生活中, n a m e一般是一个专门

用来处理所捕捉信号的函数。N a m e需要用双引号(“ ”)引起来。S i g n a l就是待捕捉的信号。

脚本在捕捉到一个信号以后,通常会采取某些行动。最常见的行动包括:

1) 清除临时文件。

2) 忽略该信号。

3) 询问用户是否终止该脚本的运行。

下表列出了一些最常见的t r a p命令用法:

trap "" 2 3 忽略信号2和信号3,用户不能终止该脚本

trap "commands" 2 3 如果捕捉到信号2或3,就执行相应的c o m m a n d s命令

trap 2 3 复位信号2和3,用户可以终止该脚本

也可以使用单引号(‘’)来代替双引号(“”);其结果是一样的。

下面的例子一经运行就开始计数直至用户按< C t r l - 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后将会向用户提供一个选择,询问用户是否真的要

退出。这里使用c a s e语句来决定采取何种操作。

如果用户希望退出,他或她可以选择1,此时当前函数会以状态1退出,而另一个清除进

程将会据此启动。如果用户并不希望退出,那么可以选择2或不做任何选择,此时c a s e语句将

会使用户退回到脚本中原来的地方。在c a s e语句中一定要包含用户输入空字符串的情况。

下面的函数在收到信号后,将会向用户提供选择:

当上面的脚本运行时,只要在输入任何域时按下< C T R L - 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

下面的脚本是另一个捕获信号的例子。该脚本名为l o c k i t,它将使用一个连续不断的w h i l e

循环锁住终端。在该脚本中, t r a p命令捕捉信号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"

}

S***EDSTTY=`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 $S***EDSTTY

[root@localhost huangcd]# sh lockit

Enter your password to lock /dev/pts/1:starting\nwrong password and terminal is locked

unlocking
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: