Linux通过信号在运行在系统的进程之间通信,用信号来停止启动及无条件终止进程。同样也可以用信号来控制shell脚本的运行。
1.Linux系统信号
Linux系统和应用程序可以生成30多个信号,最常见的有:
信号 | 值 | 描述 |
1 | SIHUP | 挂起进程 |
2 | SIGINT | 终止进程 |
3 | SIGQUIT | 停止进程 |
9 | SIGKILL | 无条件终止进程 |
15 | SIGTERM | 可能的话终止进程 |
17 | SIGSTOP | 无条件停止,但不是终止进程 |
18 | SIGTSTP | 停止或暂停,但不终止 |
19 | SIGCONT | 继续运行停止的进程 |
bash shell 会忽略信号3和15,会处理1和2.
1.1产生信号
bash shell 允许键盘上的组合生成两种基本linux信号:
Ctrl+C会生成SIGINT信号——终止进程
Ctrl+Z会生成SIGTSTP信号——暂停进程
注:shell中每个运行的进程称为作业,每个作业有唯一的作业号,shell会给第一个作业分配作业号1,第二个2,以此类推。
1.2捕捉信号trap
trap可以捕获Linux的信号,并从shell中拦截。
trap命令格式:trap command signals 其中command是捕获信号后想要执行的命令,singals是一组用空格分开的信号,可以用数值或信号名来指定。
eg:trap “echo 'Sorry! I have trapped Ctrl+C'" SIGINT SIGTERM 注:双引号必须有,否则无法执行命令。
也可以捕获脚本的退出:trap ”echo finish“ EXIT 当退出脚本时就会输出finish。
移除捕获:trap -EXIT ,一但信号捕获被移除,脚本会忽略该信号。
2.后台运行脚本——./shell.sh &
2.1简单后台模式,脚本输出在显示器,后台进程都绑定到了终端会话上
在后台模式中,进程运行时不会和终端会话上的STDIN STDOUT STDERR关联。
要在后台运行脚本,只需在命令后加个&.
$./shell_filename &
[1] 1968
.....
脚本的输出
.....
[1]+ done ./shell_filename
显示的第一行是 [1] 1968 方括号中是进程的作业号,之后是进程ID (PID)。
当后台程序运行结束时,会再终端显示一条命令 [1]+ done ./shell_filename
注:当后台进程仍在运行时,它仍会使用终端显示器来显示STDOUT和STDERR。当退出终端时,后台进程也结束运行。
2.2非控制台下运行脚本
nohup命令 实现进程一直后台运行,知道进程结束,即使关闭终端,进程也不会停止。
$ nohup ./shell_filename &
[1] 19832
$ nohup: ignoring input and appending output to 'nohup.out'
nohup将进程输出的消息重定向到 nohup.out文件中。若再用nohup命令运行另一个进程,则输出会追加到统一nohup.out文件中。
3.作业控制
3.1查看作业——jobs命令
jobs命令允许查看shell当前正在处理的作业,jobs 命令参数:
参数 | 描述 |
-l | 列出进程的PID及作业号 |
-n | 只列出上次shell发出的通知后改变了状态的作业(new作业) |
-p | 只列出作业的PID |
-r | 只列出运行中的作业 |
-s | 只列出已停止的作业 |
caishu@lab403-1F:~/scripts$ cat sh1.sh
#!/bin/bash
#testing job control
echo "This is a test program $$" #使用 $$ 显示 PID
count=1
while [ $count -le 10 ]
do
echo "Loop #$count"
sleep 5
count=$[ $count + 1 ]
done
echo "This is the end of the test program"
caishu@lab403-1F:~/scripts$ ./sh1.sh
This is a test program 12292
Loop #1
Loop #2
^Z
[1]+ 已停止 ./sh1.sh
caishu@lab403-1F:~/scripts$ ./sh1.sh
This is a test program 13629
Loop #1
^Z
[2]+ 已停止 ./sh1.sh
caishu@lab403-1F:~/scripts$ ./sh1.sh >sh1.out
^Z
[3]+ 已停止 ./sh1.sh > sh1.out
caishu@lab403-1F:~/scripts$ jobs -l #jobs命令使用显示正在运行或停止的进程
[1] 12292 停止 ./sh1.sh
[2]- 13629 停止 ./sh1.sh
[3]+ 17736 停止 ./sh1.sh > sh1.out
caishu@lab403-1F:~/scripts$ kill -9 17736
caishu@lab403-1F:~/scripts$ jobs -l
[1]- 12292 停止 ./sh1.sh
[2]+ 13629 停止 ./sh1.sh
注意:jobs命令输出中的作业带有+和 - ;带+号的是默认作业(是最后启动的那个进程),带 - 的作业是下一个默认作业,当带+的作业完成后,带-的作业会变成+;任何时候都只有一个带+的作业,和一个带- 的作业。
3.2重启停止的作业 bg fg
bg 数字 ——以后台模式重启一个作业,如bg 2,重启第二个作业
fg 数字 ——以前台模式重启一个作业,如fg 2,重启第二个作业
3.3 程序的谦让度(优先级)
默认情况下,从shell启动的所有进程在linux系统上都有同样的调度优先级0。调度优先级是个整数,从-20(高)到+20(低)
nice -n 数字 进程 ——可以改变优先级 普通用户只让进程优先级能变的更低,不能变高
renice 数字 -p PID ——改变已运行命令的优先级
限制:只能对自己的进程执行renice;只能通过renice降低优先级;root用户可调整任何进程的任何优先级。
4.定时运行脚本
4.1用at命令来计划执行作业
at命令允许指定Linux系统何时运行脚本。at命令会将作业提交到队列中,at的守护进程atd会以后台模式运行,并检查作业队列来运行作业。 atd守护进程每隔60s会检查/var/spool/at目录,获取at提交的作业,如果作业设置的是时间跟当前时间匹配,则运行此作业。
at命令格式:
at [ -f filename ] time
time设置:1)标准的小时和分钟格式,10:15 ; 2)~AM/~PM指示符, 10:15~PM ; 3)特定可命名的时间,now 、noon、midnight、teatime ; 4)标准日期格式 ,MMDDYY、MM/DD/YY、DD.MM.YY ; 5)文本日期,Jul 4或 May 5 6)时间增量,当前时间+25min、明天10:15~PM、10:15+7天
at命令会针对不同的优先级将命令存于a~z26中不同的作业队列中。可以用-q参数指定队列
4.2 作业的输出
Linux系统会将提交改作业的用户的E-mail地址作为STDOUT和STDERR ,输出通过邮件系统发送给用户,用户可以用mail命令查看。
atq 命令可以列出等待的作业
caishu@lab403-1F:~/scripts$ atq
61 Mon Oct 18 15:29:00 2015 a user
作业号 时间 队列 用户
atrm 作业号 ——命令删除作业 如:atrm 61 删除61号作业
4.3计划定期执行脚本cron
Linux程序使用cron程序来计划要定期执行的作业,cron程序在后台运行并检查cron table,来获得计划执行的作业。
1)cron时间表
时间表格式:min hour dayofmonth month dayofweek command
例如: 15:10 * * * /home/caishu/scripts/sh1.sh >sh1.out 每天10:15执行sh1.sh
dayofmonth每月几号执行;特殊的每月最后一天可以用if then和date判断
00 12 * * * if [ `date +%d -d tomorrow` = 01 ] ; then; command
dayofweek每周几,可以是(mon、tue、wed、thu、fri、sat、sun)也可以(1、2、3、4、5、6、0)
2)构建cron时间表——crontab 命令
每个系统用户都可以用自己的cron时间表来运行计划好的任务。
crontab -l 列出已有的cron时间表,默认情况下不存在。可以用crontab -e命令创建自己的时间表。
3)cron目录 /etc/cron.*ly
当创建的脚本不要求有精确的执行时间时,用系统预配置的cron脚本目录更方便。只要把脚本放到相应的目录内,cron就会按时执行它
/etc/cron.daily /etc/cron.hourly /etc/cron.monthly /etc/cron.weekly
4)anacron程序 (不会处理运行时间少于一天的脚本)
如果cron时间表中的作业在计划时间未得到运行(因为系统关机等原因),当系统开机时cron不会去运行此作业,anacron程序会尽快运行错过的作业。(用于日志维护的脚本)
anacron只会处理位于cron目录的程序,比如/etc/cron.daily 。它用时间戳来决定作业是否在适当的计划间隔内运行了。每个cron目录都有个时间戳文件,位于/var/spool/anacron目录。anacron程序有自己用来检查作业目录的表,位于/etc/anacrontab
root@lab403-1F:/etc# cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root
# These replace cron's entries
1 5 cron.daily run-parts --report /etc/cron.daily
7 10 cron.weekly run-parts --report /etc/cron.weekly
@monthly 15 cron.monthly run-parts --report /etc/cron.monthly
root@lab403-1F:/etc#
anacron时间表的基本格式为:period delay identifier command period定义了作业多久运行一次,单位是天;delay指定系统启动多少分钟后anacron程序开始运行错过的脚本。command包含了一个run_parts程序和一个cron脚本目录名。run_parts程序负责运行目录中传给它的任何脚本。identifier 是一种特别的非空白字符串,如cron-weekly,用于唯一识别日志消息和错误E-mail中的作业。
5.系统启动时运行脚本
5.1 Linux开机过程
开始Linux系统时,Linux内核会加载到内存中并运行。首先是开始UNIX System V init过程或Upstart init 过程(取决于linux版本),然后这个过程将负责启动Linux系统上的所有其他进程。
1)System V init过程
System V init过程会读取/etc/inittab文件。inittab文件会列出系统的运行级,不同的运行级启动不同的脚本。
Linux运行及——red hat 发行版
运行级 | 描述 |
0 | 关机 |
1 | 单用户模式 |
2 | 多用户模式,通常不支持网络 |
3 | 全功能的多用户模式,支持网络 |
4 | 可定义用户 |
5 | 多用户模式,支持网络和图形话X Window会话 |
6 | 重启 |
但一些基于debian的发行版,比如Ubuntu,不区分2~5级。2~5级都是 多用户模式,支持网络和图形话X Window会话。
每个运行级将会定义System V init过程启动或停止哪些脚本。这些开机脚本都是shell脚本,通过必要的环境变量来启动应用程序。
不同的Linux发行版存放开机脚本的位置略有不同,主要存放于/etc/rc#.d目录,#代表运行级;/etc/init.d目录;/etc.init.d/rc.d目录等。
2)Upstart init 过程
Upstart init 过程是管理进程服务的一个新标准。不关注运行级,只关注事件。如开机事件
Upstart 使用位于/etc/event.d或/etc/init目录下的文件来启动程序。
5.2定义自己的开机脚本
自己的开机脚本最好不要和已有的脚本文件混合,大多数Linux提供了一个本地开机文件专门让系统管理员来添加开机时运行的脚本。
Linux本地开机文件位置
发行版 | 文件位置 |
debian | /etc/init.d/rc.local |
Fedora | /etc/rc.d/rc.local |
Mandriva | /etc/rc.local |
openSuse | /etc/init.d/boot.local |
Ubuntu | /etc/rc.local |
5.3在新shell中启动
每个用户主目录下有两个文件:.bash_profile 和 .bashrc 。bash shell会用它们来自动启动脚本并设置环境变量。
当新shell是新的登陆生成的话,bash shell会运行.bash_profile ,可以把任何登陆时要运行的脚本放到该文件中。
shell启动时,bash shell会运行.bashrc。可以在.bashrc文件中添加,想要显示在shell中的语句
若要为所有用户设置,可以更改/etc/bashrc文件。
来源:oschina
链接:https://my.oschina.net/u/2712705/blog/678577