shell脚本可以有多种不同的执行方式,如界面显示、后台运行、定时运行等。
1.处理信号
linux使用信号与系统上运行的进程进行通信。也可以使用信号来控制shell脚本的运行,只需要让shell脚本在接收到来自于linux系统的特定信号时执行命令即可。
默认情况下,bash shell会忽略它接受的任何SIGQUIT(3)和SIGTERM(15)信号(以防止交互的shell意外终止)。会处理受到的任何SIGHUP(1)和SIGINT(2)信号。
如果bash shell收到了一个SIGHUP信号,它会退出,在退出之前,它将SIGHUP信号传递给shell启动的任意进程(如shell脚本)。收到SIGINT信号,shell会立即中断。Linux内核停止向shell提供CPU上的处理时间。在这种情况下,shell将SIGINT信号传递给由shell启动的任意进程以通知他们这种情况。
2.生成信号
bash shell使用键盘组合键生成两个基本信号
(1)中断进程 ctrl + c
(2)暂停进程 ctrl + z
jason@Ubuntu:~$ ./test.sh
input you name: ^Z
[1]+ 已停止 ./test.sh
方括号中的数字为shell分配的作业编号。shell以作业的形式引用shell中运行的每个进程,向每个作业分配唯一的作业编号。它向第一个启动的进程分配作业编号1,向第二个分配作业编号2.。。。
使用 ps au查看停止的作业
jason@Ubuntu:~$ ps au
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1003 0.0 0.0 4632 868 tty4 Ss+ 08:16 0:00 /sbin/getty -8
root 1009 0.0 0.0 4632 872 tty5 Ss+ 08:16 0:00 /sbin/getty -8
root 1020 0.0 0.0 4632 872 tty2 Ss+ 08:16 0:00 /sbin/getty -8
root 1021 0.0 0.0 4632 872 tty3 Ss+ 08:16 0:00 /sbin/getty -8
root 1023 0.0 0.0 4632 860 tty6 Ss+ 08:16 0:00 /sbin/getty -8
root 1076 1.8 1.9 88572 40024 tty7 Ssl+ 08:16 3:57 /usr/bin/X :0 -
root 1233 0.0 0.0 4632 864 tty1 Ss+ 08:16 0:00 /sbin/getty -8
jason 1939 0.0 0.1 8892 3836 pts/0 Ss 08:17 0:00 bash
jason 3014 0.0 0.0 6616 1108 pts/0 T 11:53 0:00 /bin/bash ./tes
jason 3015 0.0 0.0 6368 1172 pts/0 R+ 11:55 0:00 ps au
有停止的任何时,如果想要退出,会发出警告。
jason@Ubuntu:~$ exit
exit
有停止的任务。
再次键入exit可以无视 警告,仍然退出。shell退出,则终止停止的进程。或者通过ps au知道了进程的pid,可以通过kill 命令终止停止的进程。
3.捕获信号
trap命令可以指定能够通过shell脚本监控和拦截的linux信号。如果脚本收到在trap命令中列出的信号,它将保护该信号不被shell处理,并在本地处理它。
trap commands signals
在trap命令行中,只需要列出希望shell执行的命令,以及希望捕获的信号列表(以空格分隔)。指定信号可以通过他们的数值或linux信号名实现。
示例:使用trap命令忽略SIGINT信号和SIGTERM信号。
" SIGINT SIGTERM
echo "this is a test program"
count=1
while [ $count -le 10 ]
do
echo "Loop #$count"
sleep 10
count=$[$count+1]
done
echo "This is the end of the test program"
在本例子中,trap命令每次检测到SIGINT和SIGTERM信号时显示一个简单的文本消息。如果捕获了这些信号,在用户试图使用bash shell键盘ctrl + c命令停止进程时,脚本不受影响, 而执行 command的命令 “echo haha”即输出haha。
4.捕获脚本退出 EXIT信号
除了在shell脚本中捕获信号之外,还可以在shell脚本退出时捕获他们。这是一种在shell完成作业时执行命令的便捷方式。
要捕获shell脚本退出,只需要向trap命令添加EXIT信号。
trap "echo byebye" EXIT
echo "this is a test program"
count=1
while [ $count -le 10 ]
do
echo "Loop #$count"
sleep 1
count=$[$count+1]
done
在上面的例子中,如果脚本执行结束退出(或者使用ctrl + c 发送SIGINT信号将脚本程序中断退出),会发送EXIT信号,在trap中进行捕获,执行echo byebye。
5.移除捕获
要移除捕获,使用破折号作为命令和想要恢复正常行为的信号列表
trap "echo byebye" EXIT
echo "this is a test program"
count=1
while [ $count -le 10 ]
do
echo "Loop #$count"
sleep 1
count=$[$count+1]
done
trap - EXIT
echo "I just removed the exit signal"
信号捕获移除后,脚本将忽略信号,但是,如果在移除捕获之前收到信号,脚本仍然根据trap命令处理该信号。
6.以后台模式运行脚本
shell脚本执行时间过长,则可以使用后台进程模式,实现在shell中继续进行其他操作。在后台模式中,进程运行时与终端会话的STDIN, STDOUT, STDERR无关。
6-1 以后台模式运行
要通过命令行界面以后台模式运行shell脚本,只需要在命令后加一个&符号。
$ ./test.sh &
将 & 符号放在命令之后,它将bash shell与命令相分离,并以独立的后台进程形式在系统上运行。
[1] 4661
Loop #1
Loop #2
^C
jason@Ubuntu:~$ Loop #3
Loop #4
Loop #5
I just removed the exit signal
^C
[1]+ 完成 ./test.sh果。
Nohup.out文件中的输出与在命令行运行的进程输出没有区别!! 如果使用nohup运行另一个命令,输出将添加到nohup.out文件。当从同一个目录运行多个命令时要小心,因为所有的输出都将发送到同一个nohup.out 文件,可能造成混淆。
8.作业控制
8-1查看作业
输入jobs命令,查看shell处理的当前作业。参数 -l 列出进程的pid和作业编号, -p仅仅列出作业的pid, -r 列出运行的作业, -s 列出停止的作业。
jason@Ubuntu:~$ jobs
[1]+ 运行中 nohup ./test.sh &
jason@Ubuntu:~$ jobs -l
[1]+ 4845 运行中 nohup ./test.sh &
jason@Ubuntu:~$ jobs -p
4845
jason@Ubuntu:~$ jobs -s
[1]+ 完成 nohup ./test.sh
jason@Ubuntu:~$ jobs -r
方框中的为作业号,作业号后面的加号或者减号。带加号的作业视为默认作业,如果命令行没有指定作业编号,则它应该是任何作业控制命令引用的作业。带有减号的作业是在处理完当前默认作业之后将成为默认作业的作业。在某个时间点,只能有一个带有加号的作业,也只能有一个带有减号的作业。
8-2 重新启动停止的作业
在bash作业控制下,能够以后台进程或前台进程的形式重新启动任何停止的作业。前台进程控制正在处理的终端,因此需要谨慎操作。
要以后台模式重新启动作业,可以使用带有作业编号的bg命令。
$bg 2 //将 2号作业 后台重新运行
// 后台模式重新运行作业, 因此出现了命令行界面提示符,以继续运行
[2] + ./test.sh &
xxx
xxx
要以前台模式重新启动作业,可以使用带有作业编号的fg命令
$ jobs
[1] + stopped
$fg 1
./test4
作业现在以前台模式运行,因此在作业完成前无法使用命令行界面提示符。
9. 优先级调控
从shell启动的进程默认情况下,都被分配了相同的优先级。可以重新设置程序的优先级,调度优先级是一个整数值,从-20(最高优先级)到+20(最低优先级)。默认情况下,bash shell启动所有优先级为0的进程。
9-1 nice命令
nice命令可以在启动命令时设置它的调度优先级。要让命令在更低的优先级下运行,只需要使用nice的-n命令行选项指定一个新的优先级水平。
$ nice -n 10 ./test.sh > testout &
nice命令不允许普通用户增加命令的优先级,这是为了防止以高优先级启动所有命令。
9-2 renice命令
如果需要更改已经在系统中运行的命令的优先级。能够指定运行进程的pid以更改优先级。
$ renice 10 -p 2342
2342: old priority 0, new priority 10
几个限制:
(1)只能对拥有的进程使用renice命令
(2)只能使用renice命令将进程调到更低的优先级
(3)根用户可以使用renice命令将任何进程调到任何优先级
如果要完全控制运行进程,则必须以根账户登陆。
10.指定时间运行脚本
10-1 使用at命令调度作业
at命令将作业提交到一个队列,并指示shell在何时运行该作业。另一个命令atd以后台模式运行,并检查作业队列以运行作业。atd命令检查系统上的特殊目录(通常是/var/spool/at),以便运行使用at命令提交的作业。默认情况下,atd命令每个60秒检查一次目录。如果存在作业,atd'命令检查运行作业的时间。如果时间与当前时间匹配,则atd命令将运行该作业。
At的命令格式
at [-f filename] time
默认情况下,at命令将STDIN的输入提交到队列。可以使用-f参数指定用于读取命令的文件名(脚本文件)。
time参数指定希望linux系统运行作业的时间。At命令可以识别多种时间格式:
(1)标准的小时分钟格式: 10:15
(2)AM/PM指示符, 10:15PM
(3)具体指定的时间,如now、noon、midnight等
(4)标准的日期格式:MMDDYY、MM/DD/YY、DD.MM.YY
(5)还可以指定时间增量
Now + 25 minutes
10:15PM tomorrow
10:15 + 7 days
使用at命令,将作业提交到任务队列中。作业队列保存at命令提交的作业以便处理。有26种不同的作业队列可用于不同的优先级水平。使用小写字母a到z引用作业队列。
默认情况下,所有的at作业都被提交到作业队列a,即最高优先级队列。如果希望以较低优先级运行作业,可以使用-q参数指定字母。
获取作业输出
作业在linux系统运行时,没有与该作业关联的监视器。linux使用提交作业的用户的电子邮件地址作为STDOUT和STDERR。任何以STDOUT和STDERR为目的地的输出都通过电子邮件发送给用户。
test.sh脚本内容
time=`date`
echo "this script run at $time"
echo "this is the end of the script" >&2
jason@Ubuntu:~$ at -f test.sh 19:24
warning: commands will be executed using /bin/sh
job 2 at Tue Dec 3 19:24:00 2013
///at命令生成一个警告消息,之处系统使用什么shell执行脚本,分配给作业的作业编号和作业计划运行的时间。
jason@Ubuntu:~$ mail
"/var/mail/jason": 1 message 1 new
>N 1 Jason 二 12月 3 19: 13/447 Output from your job
?
Return-Path: <jason@Ubuntu>
X-Original-To: jason
Delivered-To: jason@Ubuntu
Received: by Ubuntu (Postfix, from userid 1000)
id 6DC6F1E18B0; Tue, 3 Dec 2013 19:30:00 +0800 (CST)
Subject: Output from your job 4
To: jason@Ubuntu
Message-Id: <20131203113000.6DC6F1E18B0@Ubuntu>
Date: Tue, 3 Dec 2013 19:30:00 +0800 (CST)
From: jason@Ubuntu (Jason)
this script run at 2013年 12月 03日 星期二 19:30:00 CST
this is the end of the script
///使用mail命令查看收到邮件情况。
列出排队的作业
使用atq命令能够查看系统中排队的作业。
jason@Ubuntu:~$ atq
2 Tue Dec 3 19:24:00 2013 a jason
移除队列中的作业
使用atrm 作业号 命令移除队列中的作业
10-2 调度定期脚本
linux系统使用cron程序调度需定期运行的作业。cron程序在后台运行,他从特殊表格(cron表格)中查找需要调度运行的作业。
(1)cron表格
cron表格使用特殊格式指定作业运行的时间。Corn表格的格式如下:
min hour dayofmonth month dayofweek command
cron表格可以将条目指定为具体指、一定范围的值(如1-5)或通配符(星号)。
如果希望每天10:15执行命令,可以使用 15 10 * * * command
如果希望每周一下午4:15执行command命令,可以 15 16 * * 1 command
可以将dayofweek指定为3字符的文本值(mon、tue、wed、thu、fri、sat、sun)或数字值,使用0表示周日,6表示周六。
dayofmonth指示在每个月的某天执行,如果希望在每个月的最后一天执行,由于每个月的天数不同,常用的解决方法是:00 12 * * * if [`date + %d -d tomorrow` = 01]; then; command
表示在每天12点检查本日是否为该月的最后一天,如果是,他要运行命令。
命令列表必须指定要运行的命令或shell脚本的完整路径名。可以根据需要添加任何命令行参数或者重定向符号,就像常规命令一样:
15 10 * * * /home/jason/test.sh > test3
(2)构建cron表格
每个系统用户都可以拥有自己的cron表格(包括根用户),以运行安排好的作业。linux提供了crontab命令处理cron表格。要列出cron表格,可以使用corntab -l 命令。
jason@Ubuntu:~$ crontab -l
no crontab for jason
(3)anacron程序
使用cron程序存在的唯一问题是,他假定linux系统不停运转,只有在服务器环境中运行linux才有可能发生这种情况。
如果在使用cron调度作业运行时linux系统处于关闭状态,则作业将无法运行。corn程序无法在系统打开后重新运行错过的作业。为了解决该问题,许多linux发行版提供了anacron程序。
anacron程序使用时间戳确定调度的作业是否在正确的时间间隔运行,如果他确定某个作业错过了调度运行时间,他将自动尽快运行该作业。这意味着,如果linux机器关闭了好几天,当它再次开启之后,任何计划在系统关闭期间运行的作业都将自动运行。
11.系统启动时运行脚本
(系统启动时运行脚本)在启动时启动脚本的方法通常保留供特殊的脚本使用,这些脚本执行系统功能,比如配置网络接口或者启动服务器进程。但是,如果您是linux系统管理员,在每次linux系统启动时也可能需要执行一些任务,比如重置自定义日志文件或者启动自定义应用程序等。
(bash shell启动时运行脚本)每次用户启动新的bash shell时(甚至在特定用户启动bash shell时),运行脚本的功能也很有用,经常会需要设置shell特性以进行shell会话,有时需要确定已经设置了特定的文件。
(1)系统启动时运行脚本
启动过程:
打开linux系统之后,linux加载到内存并运行。最先执行的是init程序(位于/sbin/init),因为init进程总是第一个运行,所以内核总是分配他的PID为1.然后,init进程负责启动linux系统的所有其他进程。
启动过程中,init程序读取 /etc/inittab文件。inittab文件列出了init程序以不同的运行级别启动的脚本。linux运行级别定义linux系统的操作状态。不同的运行级别启动不同的程序和脚本。Linux运行级别主要有:
级别0 停止; 级别1 单用户模式; 级别2 多用户模式,通常没有网络支持; 级别3 完全多用户模式,有网络; 级别4 未使用; 级别5 多用户模式,有网络和图形X window会话; 级别6 重启
每个运行级别都定义init程序启动或终止的脚本。图形linux系统的常见运行级别是5. 服务器系统以级别3启动。
linux系统通过rc脚本确定以哪种运行级别启动哪些程序。rc脚本确定当前系统的运行级别并在该运行级别上运行相应的脚本。
Linux系统使用 启动脚本 启动应用程序。启动脚本为启动应用程序的shell脚本,为系统的程序提供必要的环境变量。
不同linux发行版的启动脚本存放的位置不同。方式有
(1)启动脚本放在/etc/rc.d目录, 每种运行级别使用不同的目录
(2)启动脚本放在/etc/init.d目录
(3)启动脚本放在/etc/init.d/rc.d目录
定义脚本
大部分linux发行版提供了一个本地启动文件,允许系统管理员输入在启动时运行的脚本。当然,该文件的名称和位置岁linux发行版的不同而不同。
(1)Debian 存放位置 /etc/init.d/rc.local
(2)Fedora 存放位置/etc/rc.d/rc.local
(3)openSuse 存放位置/etc/init.d/boot.local
(4)Ubuntu 存放位置/etc/init.d
(2)随新shell一起启动
每个用户的主目录都包含两个文件,bash shell使用这两个文件自动启动脚本和设置环境变量。
.bash_profile 文件
.bashrc 文件
bash shell在由于新用户登陆而运行新的shell时运行.bash_profile 文件。在该文件中放置任何您希望登录时运行的脚本
bash shell在每次启动新的shell时(包括新用户登陆)运行.bashrc 文件。
linux学习(八) shell脚本(5)
最新推荐文章于 2022-08-14 21:12:07 发布