key words :处理信号(生成、捕获)、以后台模式运行脚本、作业控制(jobs、bg、nice 、at 、batch 、cron )、开机运行的脚本
一、处理信号
1
、常见信号介绍
Linux使用信号与系统上运行的进程进行通信,系统和应用程序可以生成30多个Linux信号。以下是Linux编程中常用的系统信号:
信号
值
描述
1
SIGHUP 挂起进程
2
SIGINT 中断进程
3
SIGQUIT 停止进程
9
SIGKILL 无条件终止进程
15
SIGTERM 如果可能的话就终止进程
17
SIGSTOP 无条件停止,但不终止进程
18
SIGTSTP 停止或暂停进程,但不终止它
19
SIGCONT 重新启动停止的进程
默认情况下,bash shell 会
忽略它接收到的任何
SIGQUIT
(
3
)和
SIGTERM
(
15
)信号(以防止互交shell的意外终止)。但是bash shell 会处理它收到的任何SIGHUP(1)和SIGINT(2)信号。
如果bash shell收到 一个SIGHUP信号,它会退出,并在退出前将SIGHUP信号传递给shell启动的任意进程。收到SIGINT信号,shell会立即中断。
2、生成信号
主要两对组合键:
Ctrl + C 组合生成SIGINT信号,终止当前正在shell中运行的进程
[root@localhost ~]# sleep 100
[root@localhost ~]#
Ctrl+Z组合生成SIGTSTP信号,暂停正在允许的进程
[root@localhost ~]# sleep 100
[1]+ Stopped sleep 100
[root@localhost ~]#
这时候如果exit shell 会提示:
[root@localhost ~]# exit
exit
There are stopped jobs.
[root@localhost ~]#
ps -au
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.7/FAQ
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 3599 0.0 0.0 1664 444 tty1 Ss+ 20:35 0:00 /sbin/mingetty
root 3600 0.0 0.0 1664 428 tty2 Ss+ 20:35 0:00 /sbin/mingetty
root 3601 0.0 0.0 1664 428 tty3 Ss+ 20:35 0:00 /sbin/mingetty
root 3602 0.0 0.0 1664 424 tty4 Ss+ 20:35 0:00 /sbin/mingetty
root 3603 0.0 0.0 1664 424 tty5 Ss+ 20:35 0:00 /sbin/mingetty
root 3604 0.0 0.0 1664 428 tty6 Ss+ 20:35 0:00 /sbin/mingetty
root 3705 0.9 0.9 16948 9880 tty7 Rs+ 20:35 0:35 /usr/bin/Xorg :
root 5680 0.1 0.1 4916 1456 pts/0 Ss 21:38 0:00 bash
root 5709 0.0 0.0 3960 472 pts/0 T 21:39 0:00 sleep 100
root 5723 0.0 0.0 4504 952 pts/0 R+ 21:39 0:00 ps -au
T表示该命令正在被跟踪或者已经停止
再次exit 就可以退出shell,并停止shell中的所有进程。
3、捕获信号
trap命令可以指定能够通过shell脚本监控和拦截的Linux信号。如果脚本收到在trap命令中列出的信号,它将保护该信号不被shell处理,并在本地处理它。
trap命令格式:
trap
commands signals
在trap命令行中,只需要列出希望shell执行的命令,以及希望捕获的信号列表。
[root@localhost ~]# cat test
#!/bin/bash
trap "echo haha" SIGINT SIGTERM
捕获到这两个信号就输出haha
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 program"
[root@localhost ~]# ./test
this is a test program
loop 1
haha
这个是我输入Ctrl+C的结果
loop 2
loop 3
haha
loop 4
haha
loop 5
haha
loop 6
loop 7
loop 8
loop 9
loop 10
this is the end of the program
移除捕获:
trap -
signal
二、以后台模式运行脚本
有些脚本需要运行很长时间,如果让其在前台运行的话,命令行需要等待很长时间都不能执行其他操作,所以我们需要让一些程序脚本在后台运行。使用
ps
命令可以看到
Linux
系统上运行着许多不同的进程,很明显,这些都不是把运行过程显示在
monitor
上的后台运行的程序。在后台模式中,运行程序时与
STDIN
、
STDOUT
、
STDERR
无关。
1、运行有台作业
很简单,在命令后加一个
&即可
例:
[root@localhost ~]# ./test
&
[2] 7674
[root@localhost ~]# this is a test program
loop 1
[root@localhost ~]# ls
\ Desktop Mail test wlt
aa errorfile messages.110720 testerr wzp
anaconda-ks.cfg free.rd messages.110725 testfile
bb install.log messages.110729 testout
count install.log.syslog messages.110730 test.txt
delusers log normalfile useradd
[root@localhost ~]# loop 2
loop 3
[root@localhost ~]#
这个时候按
Ctrl+C
键不起作用,脚本不会停止
[root@localhost ~]# loop 4
this is the end of the program
[2]- Done ./test
[root@localhost ~]#
可以看到脚本运行的时候仍然可以执行其他命令,但它仍然使用monitor显示STDOUT和STDERR
2、退出控制台后脚本仍然运行
一般情况下退出控制台时当前允许的脚本也会被退出,nohup命令运行另一个命令阻塞发送到进程的任何SIGHUP信号。可以防止在退出终端会话时退出进程。
例:
[root@localhost ~]#
nohup ./test &
[2] 8034
[root@localhost ~]# nohup: appending output to “nohup.out”
[2]- Done nohup ./test
使用nohup命令时,关闭会话后脚本将忽略任何终端发送来的SIGHUP信号,因为nohup命令将进程与终端分开,所以进程诶有STDOUT和STDERR输出链接,nohup命令自动将这两种消息重定向到nohup.out文件中
[root@localhost ~]# cat nohup.out
this is a test program
loop 1
loop 2
loop 3
loop 4
this is the end of the program
三、作业控制
job control :重启、停止、终止和恢复程序的操作
1、查看作业
命令:
jobs
-l :列出进程的PID和作业编号
-n:列出从上一次shell通知以来已经更改状态的作业
-p: 仅列出作业的PID
-r:仅列出正在运行的作业
-s:仅列出停止的作业
[root@localhost ~]# ./test
&
this is a test program
loop 1
[1]+ Stopped ./test&
[root@localhost ~]# ./test &
运行两次test脚本,并在运行结束前停止脚本
this is a test program
loop 1
[2]+ Stopped ./test&
[root@localhost ~]#
jobs -l
[1]- 4040 停止 ./test&
[2]+ 4058 停止 ./test&
[root@localhost ~]#
kill -9 4040
[root@localhost ~]# jobs -l
[1]- 4040 已杀死 ./test&
[2]+ 4058 停止 ./test&
2、重启已经停止的作业
只需在
bg 命令后面加
作业编号
例:接上例,作业1被杀死,重启作业2
[root@localhost ~]# bg 2
[2]+ ./test &
[root@localhost ~]# loop 2
loop 3
loop 4
[root@localhost ~]# jobs
[1]+ Running ./test &
3、更改命令优先级
在多任务系统中,内核负责为系统中运行的每个进程分配CPU时间,实际上CPU中每次只能运行一个进程,因此内核轮流向每个进程分配CPU使用时间。
默认情况下,在shell中启动的所有Linux进程在系统上的调度优先级都一样。调度优先级指的是内核相对其他进程分配给某个进程的CPU时间量。其值从-20到20,数值越小优先级越高。bash shell默认启动所有优先级为0的进程。这样子的话,所有脚本进程获得的CPU时间段相同,会造成CPU资源浪费,所以我们可以适当设定或更改特定命令的优先级,以合理分配CPU使用时间。
1)
nice -n 指定命令的调度优先级
2)
renice -p 更加PID号更改进程调度优先级
例:
[root@localhost ~]# nice -n -10 ./test &
[1] 5363
[root@localhost ~]# renice 10 -p 5363
5363: old priority -10, new priority 10
注意:
nice命令不允许普通系统用户增加命令的优先级,这是个安全特性
用户只能对自己拥有的进程使用
renice命令
只能使用
renice命令将进程调至更低的优先级
根用户无以上限制,可以完全控制
4、在指定的时间运行脚本
Linux中有三种方法预定运行脚本的时间:
at
命令
batch 命令
cron 命令
1
)
at
格式: at [-f filename] time
-f 指定at从哪里读取命令
time:运行时间
at 可以识别各种时间格式:
*标准的小时和分钟格式,例如22:30
*AM/PM格式,例如10:30PM
*具体指定时间格式,例如:now、noon、midnight、teetime(4PM)
*指定时间增量,例如now+25 minutes、22:00PM tomorrow、10:00+7days
*文本日期格式,例如Jul4、Dec25,有没有年份都可以
*标准日期格式,例如MMDDYY、MM/DD/YY或者DD.MM.YY
例:
[root@localhost ~]# at -f test 9:45
job 1 at 2011-08-01 09:45
Can't open /var/run/atd.pid to signal atd. No atd running?
atd
进程还没启动
[root@localhost ~]# service atd start
启动 atd: [确定]
[root@localhost ~]# at -f test 9:45
job 2 at 2011-08-01 09:45
[root@localhost ~]# at 10:12
at> date
(ctrl+d保存,ctrl+c中止)
at> <EOT>
job 7 at 2011-08-01 10:12
at计划任务只能运行一次,如果设定的时间比当前时间晚,则在第二天这个时间运行。命令运行在后台,前台没有任何显示,如果运行结果有输出系统会生成一个电子邮件将输出发给运行命令的人。 使用
-m参数可以设定无论有没有输出都发送邮件告知作业已完成。
查看和移除作业:
[root@localhost ~]#
atq
1 2011-08-01 09:45 a root
3 2011-08-01 09:47 a root
5 2011-08-01 09:51 a root
2 2011-08-01 09:45 a root
4 2011-08-01 09:49 a root
[root@localhost ~]#
atrm 1 3 4
[root@localhost ~]# atq
5 2011-08-01 09:51 a root
2 2011-08-01 09:45 a root
2)、
batch
batch
命令的作用是安排脚本在系统使用率较低、负载较低时运行,如果系统处于高负载水平,
batch
命令将延迟提交作业的运行,知道系统负载降低为止。这对于服务器是个很好的特性,因为服务器在白天和夜晚的负载水平不同,你可以安排脚本在低负载的时候运行而不需要知道确切的时间。
batch检查系统当前的平均负载水平,如果低于0.8就运行任何正在等待的作业
格式跟at一样:
batch [-f filename] [time]
time也是可选的,指定batch命令应该尝试运行脚本的最早时间
3)、cron
crontab服务:运行在后台,前台没有显示,计划任务可以重复运行。
配置文件:
/etc/crontab:crond服务的主配置文件。
/etc/cron.deny:访问控制文件,不允某些用户使用crontab命令。
/etc/cron.hourly:每小时运行的脚本,在此目录下。
/etc/cron.daily:每天运行的脚本,在此目录下。
/etc/cron.monthly:每月运行的脚本,在此目录下。
/etc/cron.weekly:每周运行的脚本,在此目录下。
[root@localhost ~]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
将计划任务的结果通过邮件发送给root。
HOME=/
# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly
crontab计划任务编写的步骤:
1、启动crontab服务
service crond start|restart
2、编写计划任务
crontab -e (或者其它的方法)
service crond restart
3、查看cron日志。
tail -f /var/log/cron
crontab参数:
-e 编辑
-u <username> 以指定的用户身份编写脚本。crontab -e -u kk
-l 显示计划任务
-r 删除计划任务
默认脚本存放在/var/spool/cron/<username>
时间格式:
分钟(0-59)
小时(0-24)
天(1-31)
月(1-12)
周(0-7)
命令
41 3 8 7 *
*/15 * * * *
每隔十五分钟
5,7,10,15,20,33,45,50
* * * *
每个小时的这些分钟
30 5 1,3,7,10,12,19,22,28
* *
每个月的这些这日子的五点三十分
例:
在每天的九点三十分备份一次
messages
日志文件,备份名为当天的日期
[root@localhost ~]# cat log
#!/bin/bash
today=`date +%y%m%d`
cat /var/log/messages > messages.$today
[root@localhost ~]# crontab -e
[root@localhost ~]# crontab -l
30 9 * * * ./log
5、开机自动运行的脚本
首先看看系统启动过程:系统开机后,
Linux
内核加载到内存并运行。最先运行的程序是
init
程序,
PID
固定为
1
。然后
init
程序负责启动系统中的其他进程。
init读取/etc/inittab文件,这个文件列出了init程序以不同的运行级别启动的脚本。
Linux系统通过rc 脚本确定以哪种运行级别启动那些程序和脚本,但是不同的发行版本放置启动脚本的位置不同,常见的有/etc/rc.d
/etc/init.d /etc/init.d/rc.d
大部分发行版专门提供一个本地启动文件允许系统管理员输入在启动时运行的脚本或命令
如:
Debian :/etc/init.d/rc.local
fedora :/etc/rc.d/rc.local
opensuse: /etc/init.d/boot.local
Linux
开机自动运行的脚本:
/etc/rc.local:用户在未登录前运行,在所有服务之后运行。
/etc/profile:用户个人配置文件,在每一个用户登录后自动执行,
一般结合~/.bash_profile文件一起执行。针对所有用户而言,在用户登录,su -切换用户
时,此文件会执行。
/etc/bashrc:bash的初始化脚本。(rc结尾,初始化),针对所有用户而言,用户在登录,打开终
端,su切换用户时,此文件会执行。
~/.bash_profile:针对某个用户登录后自动运行的脚本。
~/.bashrc:bash的初始化脚本,针对某个特定的用户。
各个脚本启动顺序:/etc/profile->/etc/bashrc->.bashrc->.bash_profile