动易网站开发的主要技术,莱芜在线论坛最新消息,建立自己的网站平台需多少钱,深圳公司网站开发文章目录 Linux Shell任务控制1)信号通过键盘生成信号trap 命令捕获信号 2)在后台运行脚本命令后加 符使用nohub命令 3)作业控制4)调度优先级nice命令renice 命令 5)定时运行作业at定期执行命令reference 欢迎访问个人网络日志#x1f339;#x1f339;知行空间#x… 文章目录 Linux Shell任务控制1)信号通过键盘生成信号trap 命令捕获信号 2)在后台运行脚本命令后加 符使用nohub命令 3)作业控制4)调度优先级nice命令renice 命令 5)定时运行作业at定期执行命令reference 欢迎访问个人网络日志知行空间 Linux Shell任务控制
通常情况下运行脚本的方式就是以实时模式在命令行界面上直接运行除此之外还有很多其他的运行脚本的方式如后台运行定时运行等等。除运行方式外还可以对脚本程序的运行进行控制包括向脚本发送信号、修改脚本的优先级以及在脚本运行时从暂停切换到运行模式。
1)信号
Linux利用信号与运行在系统中的进程进行通信可以通过对脚本进行编程使其在收到特定信号时执行特定命令。
信号值描述1SIGHUP挂起进程2SIGINT终止进程3SIGQUIT停止进程9SIGKILL无条件终止进程15SIGTERM尽可能终止进程17SIGSTOP无条件停止进程但不是终止进程18SIGTSTP停止或暂停进程但不终止进程19SIGCONT继续运行停止的进程
默认情况下交互式shell终端本身的进程会忽略收到的任何 SIGQUIT (3) 和 SIGTERM (5) 信号因此其不会被意外终止。
如果bash shell收到了 SIGHUP 信号比如当要离开一个交互式shell时它就会退出。但在退出之前它会将 SIGHUP 信号传给所有由该shell所启动的进程。
通过键盘生成信号
CtrlC组合键会生成 SIGINT 信号并将其发送给当前在shell中运行的所有进程。
CtrlZ组合键会生成一个 SIGTSTP 信号停止shell中运行的任何进程。这样可以在进程运行期间暂停进程而无需终止它。这样可以在不终止进程的情况下使用户深入脚本内部一窥究竟。
停止进程会让程序继续保留在内存中并能从上次停止的位置继续运行。
要想启动停止的进程可以使用fg或bg在前台和后台启动。
$ sleep 100
# ^Z
# [1] 已停止 sleep 100方括号中的数字是shell分配的作业号 job number。
可以用 ps 命令来查看已停止的作业。
$ ps -l
# F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
# 0 T 1001 116014 113239 0 80 0 - 2791 do_sig pts/0 00:00:00 sleep在 S 列中进程状态 ps 命令将已停止作业的状态为显示为 T 。这说明命令要么被跟踪要么被停止了。
在有已停止作业存在的情况下退出shell会终止已停止作业。
trap 命令捕获信号
trap命令允许用户来指定shell脚本要监视并从shell中拦截的Linux信号。当脚本收到了 trap 命令中列出的信号会执行用户指定的操作。
trap命令的格式
trap commands signals示例
#!/bin/bashtrap echo Ctrl-C Pressed SIGINTecho This is a testc1
while [ $c -le 5 ]
doecho Loop #$csleep 1c$[ $c 1 ]
done执行
$ ./test.sh
# This is a test
# Loop #1
# Loop #2
# ^CCtrl-C Pressed
# Loop #3
# Loop #4
# Loop #5上面脚本中trap 命令会在每次检测到 SIGINT 信号时捕获这些信号阻止用户用bash shell组合键CtrlC来停止程序。
除了在shell脚本中捕获中断信号也可以在shell脚本退出时捕获退出信号EXIT。以在shell完成任务时执行特定的命令。
#!/bin/bashtrap echo Running Finished. EXITecho This is a testc1
while [ $c -le 5 ]
doecho Loop #$csleep 1c$[ $c 1 ]
done执行
$ ./test.sh
# This is a test
# Loop #1
# Loop #2
# Loop #3
# Loop #4
# Loop #5
# Running Finished.要修改移除捕获在脚本中的不同位置进行不同的捕获处理只需重新使用带有新选项的 trap 命令。
#!/bin/bashtrap echo Caught SIGINT SIGINTecho This is first caughtion of SIGINTc1
while [ $c -le 3 ]
doecho Loop #$csleep 1c$[ $c 1 ]
donetrap echo Redefine SIGINT SIGINT
echo This is Mutated caughtion of SIGINT
sleep 10执行
$ ./test.sh
# This is first caughtion of SIGINT
# Loop #1
# ^CCaught SIGINT
# Loop #2
# Loop #3
# This is Mutated caughtion of SIGINT
# ^CRedefine SIGINT修改了信号捕获之后脚本处理信号的方式就会发生变化。如果一个信号是在捕获被修改前接收到的那么脚本仍然会根据最初的 trap 命令进行处理。
想删除已设置好的捕获只需要在 trap 命令与希望恢复默认行为的信号列表之间加上两个破折号即可。
trap -- SIGINT2)在后台运行脚本
直接在命令行界面运行shell脚本脚本在运行时没法在终端会话里做别的事情。
在用 ps 命令时会看到运行在Linux系统上的一系列不同进程。这些进程显然都不是运行在当前的终端显示器上的这种模式称为在后台运行进程。在后台模式中进程运行时不会和终端会话上的 STDIN 、 STDOUT 以及 STDERR 关联。
命令后加 符
前面介绍过以后台模式运行shell脚本只要在命令后加个 符就行。
$ ./test.sh
# [1] 118347方括号中的数字是shell分配给后台进程的作业号。下一个数是Linux系统分配给进程的进程IDPID。当后台进程结束时它会在终端上显示出一条消息
# [1] 已完成 ./test.sh通过./test.sh 命令将脚本放在后台运行还存在两个问题一个是当前bash shell终端关闭时后台运行中的进程仍然会被终止第二个时放入后台的脚本输出仍然会显示在显示器上会与新输入命令的输入混淆在一起。
运行多个后台作业时通过 ps 命令可以看到 所有脚本处于运行状态。 ./test.sh ./test.sh $ ps
# F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
# 0 S 1001 118703 118697 0 80 0 - 3178 do_wai pts/3 00:00:00 test.sh
# 0 S 1001 118707 118703 0 80 0 - 2791 hrtime pts/3 00:00:00 sleep
# 0 S 1001 118714 118697 0 80 0 - 3178 do_wai pts/3 00:00:00 test.sh
# 0 S 1001 118718 118714 0 80 0 - 2791 hrtime pts/3 00:00:00 sleep使用nohub命令
当需要在终端会话中启动shell脚本然后让脚本一直以后台模式运行到结束且终端会话退出仍不影响脚本运行时前面介绍的符号的方式就不适合了这时需要使用nohub命令。
nohup 命令运行的后台任务会阻断所有发送给该进程的 SIGHUP信号这可以在退出终端会话时阻止进程退出。
nohup 命令的格式:
$ nohup ./test.sh
# [1] 119226
# nohup: 忽略输入并把输出追加到nohup.out由于 nohup 命令会解除终端与进程的关联进程也就不再同 STDOUT 和 STDERR 联系在一起。 为了保存该命令产生的输出 nohup 命令会自动将 STDOUT 和 STDERR 的消息重定向到一个名为 nohup.out的文件中。值得注意的是当在同个目录同时启动多个nohub命令时会输出到同一个nohub.out文件中。
3)作业控制
jobs 命令可以查看分配给shell的作业。
通过test.sh启动两个作业
$ ./test.sh
# This is first caughtion of SIGINT
# Loop #1
# ^Z
# [1] 已停止
$ ./test.sh test.out
# [2] 119480
$ jobs
# [1] 已停止 ./test.sh
# [2]- 运行中 ./test.sh test.out 要想查看作业的PID可以在 jobs 命令中加入 -l 选项。jobs 命令输出中的加号和减号的含义是带加号的作业会被当做默认作业在使用作业控制命令时如果未在命令行指定任何作业号该作业会被当成作业控制命令的操作对象。当前的默认作业完成处理后带减号的作业成为下一个默认作业。任何时候都只有一个带加 号的作业和一个带减号的作业。在前面介绍的重新启动停止的作业的命令fg/bg不带参数时启动的就是号对应的作业。
更多jobs命令的选项参数可以通过命令jobs --help查看。
4)调度优先级
调度优先级决定了内核分配给进程的CPU时间。在Linux系统中由shell启动的所有进程的调度优先级默认都是相同的都是0。调度优先级是个整数值从-20最高优先级到19最低优先级。
要改变一个shell脚本的优先级可以通过 nice 命令做到。
nice命令
nice 命令允许你设置命令启动时的调度优先级。要让命令以更低的优先级运行只要用 nice的 -n 命令行来指定新的优先级即可。
$ nice -n 10 ./test.sh test.out
# [2] 120413
$ ps -p 120413 -o pid,ppid,ni,cmd
# PID PPID NI CMD
# 120413 118697 10 /bin/bash ./test.sh通过ps命令可以看到调度优先级已经被调整到了10。
nice 命令阻止普通系统用户来提高命令的优先级需要使用root权限。
renice 命令
renice命令用来改变系统上已运行命令的优先级。通过指定运行进程的PID来改变它的优先级。
$ renice -n 10 -p 120756
# 120756 (process ID) 旧优先级为 0新优先级为 105)定时运行作业
Linux系统提供了多个在预选时间运行脚本的方法 at 命令和 cron 表。
at
at 命令允许指定Linux系统何时运行脚本相当于是预约执行任务。
at 的守护进程 atd 会以后台模式运行检查作业队列来运行作业。大多数Linux发行版会在启动时运行此守护进程。
atd 守护进程会检查系统上的一个特殊目录通常位于/var/spool/at来获取用 at 命令提交的作业。默认情况下 atd 守护进程会每60秒检查一下这个目录。有作业时 atd 守护进程会检查作业设置运行的时间。如果时间跟当前时间匹配 atd 守护进程就会运行此作业。
at 命令的基本格式:
at [-f filename] time-f 参数来指定用于读取命令脚本文件的文件名。time 参数指定了Linux系统何时运行该作业。
at 命令能识别多种不同的时间格式:
标准的小时和分钟格式比如22:15AM/PM指示符比如10:15 PM特定可命名时间比如now、noon、midnight或者teatime4 PM通过不同的日期格式指定特定的日期 标准日期格式比如MMDDYY、MM/DD/YY或DD.MM.YY文本日期比如Jul 4或Dec 25加不加年份均可指定时间增量:当前时间25 min。
$ at -f test.sh 21:23
# warning: commands will be executed using /bin/sh
# job 3 at Mon Jan 8 21:23:00 2024作业队列的字母排序越高作业运行的优先级就越低nice值更高。默认情况下 at 的作业会被提交到 a 作业队列。如果想以更高优先级运行作业可以用 -q 参数指定不同的队列字母。
在使用 at 命令时最好在脚本中对 STDOUT 和 STDERR 进行重定向。
atq 命令可以查看系统中有哪些作业在等待。
$ atq
# 1 Mon Jan 8 21:17:00 2024 rob
# 6 Tue Jan 9 20:24:00 2024 a rob
# 3 Mon Jan 8 21:23:00 2024 rob
# 4 Tue Jan 9 20:24:00 2024 a rob
# 5 Tue Jan 9 20:24:00 2024 a rob可以用 atrm 命令来删除等待中的作业。
$ atrm 6
$ atq
# 1 Mon Jan 8 21:17:00 2024 rob
# 3 Mon Jan 8 21:23:00 2024 rob
# 4 Tue Jan 9 20:24:00 2024 a rob
# 5 Tue Jan 9 20:24:00 2024 a rob定期执行命令
at 命令可以在预设时间安排脚本执行但如果需要脚本在每天的同一时间运行或是每周一次、每月一次就需要使用新方法。
Linux系统使用cron程序来安排要定期执行的作业。 cron程序会在后台运行并检查cron时间表以获知已安排执行的作业。
可以使用crontab -e来编辑cron时间表
$ crontab -e
# GNU nano 4.8 /tmp/crontab.hABXZo/crontab
# # Edit this file to introduce tasks to be run by cron.
# #
# # Each task to run has to be defined through a single line
# # indicating with different fields when the task will be run
# # and what command to run for the task
表中每一行表示一个定期执行的任务其格式为
# m h dom mon dow commandm表示分钟h表示小时dom表示几号mon表示月份dow表示星期几*表示任意日期。
分别是minute (m), hour (h), day of month (dom), month (mon),# and day of week (dow) or use * in these fields (for any)
示例
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/表示每周一凌晨5点将home.tgz解压到/home路径中。
每月最后一天执行的任务设置方式
# 00 12 * * * if [ date %d -d tomorrow 01 ] ; then ; command列出crontab中的任务
crontab -l如果待执行的脚本对精确的执行时间要求不高用预配置的cron脚本目录会更方便。在/etc/路径下有4个基本目录cron.hourly、daily、monthly和weekly。譬如如果脚本需要每天运行一次只要将脚本复制到daily目录cron就会每天执行它。
cron程序的唯一问题是它假定Linux系统是7×24小时运行的如果系统存在关机重启有可能会错误定时任务处理这种情况最好是能在开机时检查是否有错过的定时任务而cron并不会去检查很多Linux发行版还包含了anacron程序可以解决这个问题。
anacron程序只会处理位于cron目录的程序比如/etc/cron.monthly。它用时间戳来决定作业是否在正确的计划间隔内运行了。每个cron目录都有个时间戳文件该文件位于/var/spool/anacron。
$ sudo cat /var/spool/anacron/cron.monthly
# 20240104欢迎访问个人网络日志知行空间 reference 1.《Linux命令行与shell脚本编程大全》