19.Linux Shell任务控制

文章目录

  • 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所启动的进程。

通过键盘生成信号

Ctrl+C组合键会生成 SIGINT 信号,并将其发送给当前在shell中运行的所有进程

Ctrl+Z组合键会生成一个 SIGTSTP 信号,停止shell中运行的任何进程。这样可以在进程运行期间暂停进程,而无需终止它。这样可以在不终止进程的情况下使用户深入脚本内部一窥究竟。

停止进程会让程序继续保留在内存中,并能从上次停止的位置继续运行。

要想启动停止的进程可以使用fgbg在前台和后台启动

$ 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 testc=1
while [ $c -le 5 ]
doecho "Loop #$c"sleep 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组合键Ctrl+C来停止程序。

除了在shell脚本中捕获中断信号,也可以在shell脚本退出时捕获退出信号EXIT。以在shell完成任务时执行特定的命令。

#!/bin/bashtrap "echo 'Running Finished.'" EXITecho This is a testc=1
while [ $c -le 5 ]
doecho "Loop #$c"sleep 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 SIGINT"c=1
while [ $c -le 3 ]
doecho "Loop #$c"sleep 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 -- SIGINT

2)在后台运行脚本

直接在命令行界面运行shell脚本,脚本在运行时,没法在终端会话里做别的事情。

在用 ps 命令时,会看到运行在Linux系统上的一系列不同进程。这些进程显然都不是运行在当前的终端显示器上的,这种模式称为在后台运行进程。在后台模式中,进程运行时不会和终端会话上的 STDINSTDOUT 以及 STDERR 关联。

命令后加 & 符

前面介绍过,以后台模式运行shell脚本,只要在命令后加个 & 符就行

$ ./test.sh &
# [1] 118347

方括号中的数字是shell分配给后台进程的作业号。下一个数是Linux系统分配给进程的进程ID(PID)。当后台进程结束时,它会在终端上显示出一条消息:

# [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 命令会解除终端与进程的关联,进程也就不再同 STDOUTSTDERR 联系在一起。
为了保存该命令产生的输出, nohup 命令会自动将 STDOUTSTDERR 的消息重定向到一个名为
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,新优先级为 10

5)定时运行作业

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:15
  • AM/PM指示符,比如10:15 PM
  • 特定可命名时间,比如nownoonmidnight或者teatime(4 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 命令时,最好在脚本中对 STDOUTSTDERR 进行重定向

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   command

m表示分钟,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、monthlyweekly。譬如,如果脚本需要每天运行一次,只要将脚本复制到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脚本编程大全》


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/606597.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8 Ultralytics:使用Ultralytics框架进行姿势估计

YOLOv8 Ultralytics:使用Ultralytics框架进行姿势估计 前言相关介绍前提条件实验环境安装环境项目地址LinuxWindows 使用Ultralytics框架进行姿势估计参考文献 前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可…

HarmonyOS4.0系统性深入开发13根据卡片状态刷新不同内容

根据卡片状态刷新不同内容 相同的卡片可以添加到桌面上实现不同的功能,比如添加两张桌面的卡片,一张显示杭州的天气,一张显示北京的天气,设置每天早上7点触发定时刷新,卡片需要感知当前的配置是杭州还是北京&#xff…

计算机创新协会冬令营——暴力枚举题目06

我给大家第一阶段的最后一道题就到这里了,下次得过段时间了。所以这道题简单一点。但是足够经典 下述题目描述和示例均来自力扣:两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target …

Transformer简略了解

Transformer出自论文:《Attention Is All You Need》 该论文的提出,对RNN循环神经网络产生了冲击,席卷了自然语言处理(NLP)领域,后续的GPT4.0版本也是根据其进行训练优化的 一、Transformer主体架构 可以简化分为Encoders和Decod…

nginx部署前端项目自动化脚本

文章目录 配置入口服务器nginx的conf.d使用docker创建一个nginx配置自动化脚本 前言 将项目 通过nginx 部署到 新的服务器 通过nginx反向代理出去 配置入口服务器nginx的conf.d 一般在这个文件夹下 找不到使用 find / -name nginx 2>/dev/null 找到nginx 的位置如果有些没有…

WPF 导航界面悬浮两行之间的卡片 漂亮的卡片导航界面 WPF漂亮渐变颜色 WPF漂亮导航头界面 UniformGrid漂亮展现

在现代应用程序设计中,一个漂亮的WPF导航界面不仅为用户提供视觉上的享受,更对提升用户体验、增强功能可发现性和应用整体效率起到至关重要的作用。以下是对WPF漂亮导航界面重要性的详尽介绍: 首先,引人入胜的首页界面是用户与软…

QLabel文字两端对齐解决方案

QLabel文字两端对齐解决方案 Qt本身是支持文字两端对齐的,但需要同时使用Qt::AlignJustify和Qt::TextJustificationForced两个设置。但这两个设置入口不一样。 Qt::AlignJustify用于setAlignment、setTextAlignment等接口,Qt::TextJustificationForced…

【Flet教程】使用Flet以Python创建TODO应用程序

Flet是基于Python实现的Flutter图形界面GUI。除了使用Python,具备美观、简洁、易用,还有Flutter本身的跨平台(安卓、iOS、Win、Mac、Web)、高性能、有后盾的特点。下面是0.18版官方TODO APP教程,为了准确,保…

Hyperledger Fabric Java App Demo

编写一个应用程序来连接到 fabrc 网络中,通过调用智能合约来访问账本. fabric gateway fabric gateway 有两个项目,一个是 fabric-gateway-java , 一个是 fabric-gateway。 fabric-gateway-java 是比较早的项目,使用起来较为麻烦需要提供一…

shell中的正则表达式、编程-grep、编程-SED、以及编程-AWK

正则表达式RE 用来处理文本 正则表达式(Regular Expression, RE)是一种字符模式, 用于在查找过程中匹配指定的字符. 在大多数程序里, 正则表达式都被置于两个正斜杠之间; 例如/l[oO]ve/就是由正斜杠界定的正则表达式, 它将匹配被查找的行中任何位置出现的相同模式. 在正则表达…

SpringBoot 如何 配置端口号

结论 server:port: 8088演示 [Ref] 快速构建SpringBoot项目

是时候扔掉cmder, 换上Windows Terminal

作为一个Windows的长期用户,一直没有给款好用的终端,知道遇到了 cmder,它拯救一个习惯用Windows敲shell命令的人。 不用跟我安利macOS真香!公司上班一直用macOS,一方面确实更加习惯windows下面学习, 另一方面是上课需要…

天津最新web前端培训班 如何提升web技能?

随着互联网的迅猛发展,web前端成为了一个热门的职业方向。越来越多的人希望能够通过学习web前端技术来提升自己的就业竞争力。为了满足市场的需求,许多培训机构纷纷推出了web前端培训课程。 什么是WEB前端 web前端就是web给用户展示的东西,…

Go语言学习记录——用正则表达式(regexp包)来校验参数

前言 最近坐毕设ing,简单的一个管理系统。 其中对于用户注册、登录功能,需要进行一些参数校验。 因为之前使用过,因此这里计划使用正则表达式进行校验。但是之前的使用也仅限于使用,因此这次专门进行一次学习,并做此记…

Python将Labelme文件的真实框和预测框绘制到图片上

Python将Labelme文件的真实框和预测框绘制到图片上 前言前提条件相关介绍实验环境Python将Labelme文件的标注信息绘制到图片上代码实现输出结果 前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击进入Python日常小操作专…

ROS 摄像头的标定

在ROS中,标定摄像头是一个重要的步骤,它是为了获取摄像头的内参和外参,进而提高摄像头的定位精度。摄像头标定校正由镜头畸变、相机内参(焦距、主点坐标等)、相机外参(旋转和平移矩阵)等因素引起…

js 节流和防抖

1 节流 可以形象理解为“节约流量”防止事件高频触发 作用 将高频触发变为低频触发 场景 降低resize等事件触发频率无限加载场景下,定期触发 代码 function throttle(fn, delay 100) {let timer null;return function() {if (timer) return;timer setTime…

leetcode每日一题43

116. 填充每个节点的下一个右侧节点指针 层序遍历嘛 /* // Definition for a Node. class Node { public:int val;Node* left;Node* right;Node* next;Node() : val(0), left(NULL), right(NULL), next(NULL) {}Node(int _val) : val(_val), left(NULL), right(NULL), next(N…

深入理解Java源码:提升技术功底,深度掌握技术框架,快速定位线上问题

为什么要看源码: 1、提升技术功底: 学习源码里的优秀设计思想,比如一些疑难问题的解决思路,还有一些优秀的设计模式,整体提升自己的技术功底 2、深度掌握技术框架: 源码看多了,对于一个新技术…

猫头虎分享已解决Bug || Error: ImagePullBackOff (K8s)

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通Golang》…