shell脚本控制——处理信号
Linux利用信号与系统中的进程进行通信。你可以通过对脚本进行编程,使其在收到特定信号时执行某些命令,从而控制shell脚本的操作。
1.重温Linux信号
Linux系统和应用程序可以产生超过30个信号。下表列出了在shell脚本编程时会遇到的最常见的Linux系统信号。
| 信号 | 值 | 描述 |
|---|---|---|
| 1 | SIGHUP | 挂起(hang up)进程 |
| 2 | SIGINT | 中断(interrupt)进程 |
| 3 | SIGQUIT | 停止(stop)进程 |
| 9 | SIGKILL | 无条件终止(terminate)进程 |
| 15 | SIGTERM | 尽可能终止进程 |
| 18 | SIGCONF | 继续运行停止的进程 |
| 19 | SIGSTOP | 无条件停止,但不终止进程 |
| 20 | SIGTSTP | 停止或暂停(pause),但不终止进程 |
在默认情况下,bash shell会忽略收到的任何SIGQUIT(3)信号和SIGTERM(15)信号(因此交互式shell才不会被意外终止)。但是,bash shell会处理收到的所有SIGHUP(1)信号和SIGINT(2)信号。
如果收到了SIGHUP信号(比如在离开交互式shell时),bash shell就会退出。但在退出之前,它会将SIGHUP信号传给所有由该shell启动的进程,包括正在运行的shell脚本。
随着收到SIGINT信号,shell会被中断。Linux内核将不再为shell分配CPU处理时间。当出现这种情况时,shell会将SIGINT信号传给由其启动的所有进程,以此告知出现的状况。
你可能也注意到了,shell会将这些信号传给shell脚本来处理。而shell脚本的默认行为是忽略这些信号,因为可能不利于脚本运行。要避免这种情况,可以在脚本中加入识别信号的代码,并做相应的处理。
2.产生信号
bash shell允许使用键盘上的组合键来生成两种基本的Linux信号。这个特性在需要停止或暂停失控脚本时非常方便。
1.中断进程
Ctrl+C组合键会生成SIGINT信号,并将其发送给当前在shell中运行的所有进程。通过执行一条需要很长时间才能完成的命令,然后按下Ctrl+C组合键,可以对此进行测试:
$ sleep 60
^C
$
sleep命令会按照指定的秒数暂停shell操作一段时间,然后返回shell提示符。Ctrl+C组合键会发送SIGINT信号,停止shell中当前运行的进程。在超时前(60秒)按下Ctrl+C组合键,就可以提前终止sleep命令。
2.暂停进程
你也可以暂停进程,而不是将其终止。尽管有时这可能比较危险(比如,脚本打开了一个关键的系统文件的文件锁),但它往往可以在不终止进程的情况下,使你能够深入脚本内部一窥究竟。
Ctrl+Z组合键会生成SIGTSTP信号,停止shell中运行的任何进程。停止(stopping)进程跟终止(terminating)进程不同,前者让程序继续驻留在内存中,还能从上次停止的位置继续运行。
当使用Ctrl+Z组合键时,shell会通知你进程已经被停止了:
$ sleep 60
^Z
[1]+ Stopped sleep 60
$
方括号中的数字是shell分配的作业号。shell将运行的各个进程称为作业,并为作业在当前shell内分配了唯一的作业号。作业号从1开始,然后是2,依次递增。
如果shell会话中有一个已停止的作业,那么在退出shell时,bash会发出提醒:
$ sleep 70
^Z
[2]+ Stopped sleep 70
$
$ exit
logout
There are stopped jobs.
$
可以用ps命令查看已停止的作业:
$ ps -l
F S UID PID PPID [...] TTY TIME CMD
0 S 1001 1509 1508 [...] pts/0 00:00:00 bash
0 T 1001 1532 1509 [...] pts/0 00:00:00 sleep
0 T 1001 1533 1509 [...] pts/0 00:00:00 sleep
0 R 1001 1534 1509 [...] pts/0 00:00:00 ps
$
在S列(进程状态)中,ps命令将已停止作业的状态显示为T。这说明命令要么被跟踪,要么被停止。
如果在有已停止作业的情况下仍旧想退出shell,则只需再输入一遍exit命令即可。shell会退出,终止已停止作业。
或者,如果知道已停止作业的PID,那就可以用kill命令发送SIGKILL(9)信号将其终止:
$ kill -9 1532
[1]- Killed sleep 60
$ kill -9 1533
[2]+ Killed sleep 70
$
每当shell生成命令行提示符时,也会显示shell中状态发生改变的作业。“杀死”作业后,shell会显示一条消息,表示运行中的作业已被“杀死”,然后生成提示符。
注意 在某些Linux系统中,“杀死”作业时不会得到任何回应。但当下次执行能让shell生成命令行提示符的操作时(比如,按下Enter键),你会看到一条消息,表示作业已被“杀死”。
3.捕获信号
你也可以用其他命令在信号出现时将其捕获,而不是忽略信号。trap命令可以指定shell脚本需要侦测并拦截的Linux信号。如果脚本收到了trap命令中列出的信号,则该信号不再由shell处理,而是由本地处理。
trap命令的格式如下:
trap commands signals
在trap命令中,需要在commands部分列出想要shell执行的命令,在signals部分列出想要捕获的信号(多个信号之间以空格分隔)。指定信号的时候,可以使用信号的值或信号名。
下面这个简单的例子展示了如果使用trap命令捕获SIGINT信号并控制脚本的行为:
$ cat trapsignal.sh
#!/bin/bash
#Testing signal trapping
#
trap "echo ' Sorry! I have trapped Ctrl-C'" SIGINT
#
echo "This is a test script."
#
count=1
while [ $count -le 5 ]
doecho "Loop #$count"sleep 1count=$[ $count + 1 ]
done
#
echo "This is the end of test script."
exit
$
每次侦测到SIGINT信号时,本例中的trap命令都会显示一行简单的文本消息。捕获这些信号可以阻止用户通过组合键Ctrl+C停止脚本:
$ ./trapsignal.sh
This is a test script.
Loop #1
Loop #2
^C Sorry! I have trapped Ctrl-C
Loop #3
^C Sorry! I have trapped Ctrl-C
Loop #4
Loop #5
This is the end of test script.
$
每次使用Ctrl+C组合键,脚本都会执行trap命令中指定的echo语句,而不是忽略信号并让shell停止该脚本。
警告 如果脚本中的命令被信号中断,使用带有指定命令的trap未必能让被中断的命令继续执行。为了保证脚本中的关键操作不被打断,请使用带有空操作命令的trap以及要捕获的信号列表,例如:
trap "" SIGINT
这种形式的trap命令允许脚本完全忽略SIGINT信号,继续执行重要的工作。
4.捕获脚本退出
除了在shell脚本中捕获信号,也可以在shell脚本退出时捕获信号。这是在shell完成任务时执行命令的一种简便方法。
要捕获shell脚本的退出,只需在trap命令后加上EXIT信号即可:
$ cat trapexit.sh
#!/bin/bash
#Testing exit trapping
#
trap "echo Goodbye..." EXIT
#
count=1
while [ $count -le 5 ]
doecho "Loop #$count"sleep 1count=$[ $count + 1 ]
done
#
exit
$
$ ./trapexit.sh
Loop #1
Loop #2
Loop #3
Loop #4
Loop #5
Goodbye...
$
当脚本运行到正常的退出位置时,触发了EXIT,shell执行了在trap中指定的命令。如果提前退出脚本,则依然能捕获到EXIT:
$ ./trapexit.sh
Loop #1
Loop #2
Loop #3
^CGoodbye...$
因为SIGINT信号并未在trap命令的信号列表中,所以当按下Ctrl+C组合键发送SIGINT信号时,脚本就退出了。但在退出之前已经触发了EXIT,于是shell会执行trap命令。
5.修改或移除信号捕获
要想在脚本中的不同位置进行不同的信号捕获处理,只需重新使用带有新选项的trap命令即可:
$ cat trapmod.sh
#!/bin/bash
#Modifying a set trap
#
trap "echo ' Sorry...Ctrl-C is trapped.'" SIGINT
#
count=1
while [ $count -le 3 ]
doecho "Loop #$count"sleep 1count=$[ $count + 1 ]
done
#
trap "echo ' I have modified the trap!'" SIGINT
#
count=1
while [ $count -le 3 ]
doecho "Second Loop #$count"sleep 1count=$[ $count + 1 ]
done
#
exit
$
修改了信号捕获之后,脚本处理信号的方式就会发生变化。但如果信号是在捕获被修改前接收到的,则脚本仍然会根据原先的trap命令处理该信号。
$ ./trapmod.sh
Loop #1
^C Sorry...Ctrl-C is trapped.
Loop #2
Loop #3
Second Loop #1
Second Loop #2
^C I have modified the trap!
Second Loop #3
$
提示 如果在交互式shell会话中使用trap命令,可以使用trap -p查看被捕获的信号。如果什么都没有显示,则说明shell会话按照默认方式处理信号。
也可以移除已设置好的信号捕获。在trap命令与希望恢复默认行为的信号列表之间加上两个连字符即可。
$ cat trapremoval.sh
#!/bin/bash
#Removing a set trap
#
trap "echo ' Sorry...Ctrl-C is trapped.'" SIGINT
#
count=1
while [ $count -le 3 ]
doecho "Loop #$count"sleep 1count=$[ $count + 1 ]
done
#
trap -- SIGINT
echo "The trap is now removed."
#
count=1
while [ $count -le 3 ]
doecho "Second Loop #$count"sleep 1count=$[ $count + 1 ]
done
#
exit
$
注意 也可以在trap命令后使用单连字符来恢复信号的默认行为。单连字符和双连字符的效果一样。
移除信号捕获后,脚本会按照默认行为处理SIGINT信号,也就是终止脚本运行。但如果信号是在捕获被移除前接收到的,那么脚本就会按照原先trap命令中的设置进行处理:
$ ./trapremoval.sh
Loop #1
Loop #2
^C Sorry...Ctrl-C is trapped.
Loop #3
The trap is now removed.
Second Loop #1
Second Loop #2
^C
$
在本例中,第一个Ctrl+C组合键用于提前终止脚本。因为信号是在捕获被移除前接收的,所以脚本会按照事先的安排,执行trap中指定的命令。捕获随后会被移除,再按Ctrl+C组合键就能提前终止脚本了。
相关文章:
shell脚本控制——处理信号
Linux利用信号与系统中的进程进行通信。你可以通过对脚本进行编程,使其在收到特定信号时执行某些命令,从而控制shell脚本的操作。 1.重温Linux信号 Linux系统和应用程序可以产生超过30个信号。下表列出了在shell脚本编程时会遇到的最常见的Linux系统信…...
【个人开发】macbook m1 Lora微调qwen大模型
本项目参考网上各类教程整理而成,为个人学习记录。 项目github源码地址:Lora微调大模型 项目中微调模型为:qwen/Qwen1.5-4B-Chat。 去年新发布的Qwen/Qwen2.5-3B-Instruct同样也适用。 微调步骤 step0: 环境准备 conda create --name fin…...
电脑开机提示按f1原因分析及终极解决方法来了
经常有网友问到一个问题,我电脑开机后提示按f1怎么解决?不管理是台式电脑,还是笔记本,都有可能会遇到开机需要按F1,才能进入系统的问题,引起这个问题的原因比较多,今天小编在这里给大家列举了比…...
2025华为OD机试真题最新题库 (B+C+D+E卷) + 在线OJ在线刷题使用说明(C++、Java、Python合集)(正在更新E卷,目前已收录581道)
2024年8月份,华为已经开始使用E卷题库,题目和往期一样,旧题加新题的组合,有题目第一时间更新,大家可以跟着继续学习,目前使用复用题较多,可在OJ上直接找到对应的E卷学习,可以放心学习…...
《手札·避坑篇》2025年传统制造业企业数字化转型指南
一、引言 在数字化浪潮的推动下,传统制造业企业正加速向智能化、数字化转型。开源软件技术与制造MES(制造执行系统)产品的结合,为企业提供了高效、灵活且低成本的转型路径。本指南旨在为传统制造业企业的信息化负责人提供一套完整的数字化转型方案,助力企业实现高效、智能…...
Qt+海康虚拟相机的调试
做机器视觉项目的时候,在没有相机或需要把现场采集的图片在本地跑一下做测试时,可以使用海康的虚拟相机调试。以下是设置步骤: 1.安装好海康MVS软件,在菜单栏->工具选择虚拟相机工具,如下图: 2.打开虚拟…...
《Origin画百图》之边际分布曲线图
《Origin画百图》第六集——边际分布曲线图 入门操作可看《30秒,带你入门Origin》 边际分布曲线图,其中包含散点图形,而在图的边际有着分布曲线图。在比较数据以查看多个变量之间是否存在关系时非常有用。 1.数据准备:为多列XY数…...
如何提升自己的能力
提高自身能力是一个长期且综合的过程,需要从多个方面进行努力和持续的学习,以下是一些有效的方法: 明确目标与规划 确定目标:首先要明确自己想要提高哪些方面的能力,例如沟通能力、领导力、专业技能等,并根…...
【ORACLE】这个‘‘和null不等价的场景,deepseek你怎么看?
【ORACLE】一处’和null不等价的场景–to_char(number,varchar2) 背景 最近在做一个国产数据库替代项目,要求将ORACLE迁移到一个openGauss系数据库,迁移后,执行一个存储过程时,发现国产库的执行结果和ORACLE不一致, …...
安全知识之网络扫描器概念与相关技术
网络安全扫描器简介 迅速发展的Internet给人们的生活、工作带来了巨大的方便,但同时,也带来了一些不容忽视的问题,网络信息的安全保密问题就是其中之一。 网络的开放性以及黑客的攻击是造成网络不安全的主要原因。科学家在设计Internet之初就…...
Vim跳转文件及文件行结束符EOL
跳转文件 gf 从当前窗口打开那个文件的内容,操作方式:让光标停在文件名上,输入gf。 Ctrlo 从打开的文件返回之前的窗口 Ctrlwf 可以在分割的窗口打开跳转的文件,不过在我的实验不是次次都成功。 统一行尾格式 文本文件里存放的…...
Termux安装ssh实现电脑ssh
Termux下载 点击下载 在 Termux 中安装并使用 SSH,按照以下步骤操作: 1. 更新软件包列表 pkg update && pkg upgrade2. 安装 OpenSSH pkg install openssh3. 设置 SSH 密码(必须,否则无法使用 SSH 服务器)…...
DeepSeek大模型介绍、本地化部署与使用!【AI大模型】
一、DeepSeek 是什么? 1.技术定位 专注大模型与AGI研究,开发高性能基座模型(如 DeepSeek LLM 系列),支持长文本、多模态、代码生成等复杂任务。 提供开源模型(如 DeepSeek-MoE、DeepSeek-V2)…...
Axios 的原理
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
Gitlab中如何进行仓库迁移
需求:之前有一个自己维护的新仓库A,现在需要将这个仓库提交并覆盖另一个旧的仓库B,需要保留A中所有的commit信息。 1.方法一:将原有仓库A导出后再导入到新的仓库B中 适用场景:新的仓库B是一个待建仓库,相当…...
Android的MQTT客户端实现
在 Android 平台上实现 MQTT 客户端的完整技术方案,涵盖基础实现、安全连接、性能优化和最佳实践: 一、技术选型与依赖配置 推荐库 Eclipse Paho Android Service(官方维护,支持后台运行) gradle 复制 // build.gradl…...
Centos挂载镜像制作本地yum源,并补装图形界面
内网环境centos7.9安装图形页面内网环境制作本地yum源 上传镜像到服务器目录 创建目录并挂载镜像 #创建目录 cd /mnt/ mkdir iso#挂载 mount -o loop ./CentOS-7-x86_64-DVD-2009.iso ./iso #前面镜像所在目录,后面所挂载得目录#检查 [rootlocalhost mnt]# df -h…...
Thread类以及常见方法
Thread类是JVM用来管理线程的一个类,每个线程都有一个唯一的Thread对象与之关联。 多一个线程,就多一条执行流,每个执行流也要一个对象来描述,而Thread类的对象就是用来描述一个线程的执行流,JVM 会将这些 Thread 对象…...
【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记
第十一届省赛真题代码部分 前言赛题代码思路笔记竞赛板配置内部振荡器频率设定键盘工作模式跳线扩展方式跳线 建立模板明确设计要求和初始状态显示功能部分数据界面第一部分第二部分第三部分调试时发现的问题 参数设置界面第一部分第二部分和第四部分第三部分和第五部分 按键功…...
【原创】Android Studio Ladybug 中Gradle配置
使用Android Studio创建项目后,由于需要下载的一下文件在国外,加上网速的问题,以及防火墙的问题,不少文件难以下载。常常导致项目创建后,要等很长时间,各种折腾,结果一个demo都跑不起来。 经过…...
CLion2024.3.2版中引入vector头文件报错
报错如下: 在MacBook端的CLion中引入#include <vector>报 vector file not found(引入map、set等也看参考此方案),首先可以在Settings -> Build,Execution,Deployment -> Toolchains中修改C compiler和C compiler的路…...
自动化测试工具:selenium
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 Selenium是一个用于Web应用程序测试的工具。是一个开源的Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键…...
MR30分布式IO模块:驱动智能制造工厂的工业互联与高效控制新范式
在工业4.0与智能制造浪潮的推动下,传统制造业正经历着从“机械驱动”向“数据驱动”的深刻转型。作为工业数据连接领域的领军者,明达技术凭借其自主研发的MR30分布式IO模块,以创新的技术架构与卓越的性能表现,为全球制造企业构建了…...
计算机领域QPM、TPM分别是什么并发指标,还有其他类似指标吗?
在计算机领域,QPM和TPM是两种不同的并发指标,它们分别用于衡量系统处理请求的能力和吞吐量。 QPM(每分钟请求数) QPM(Query Per Minute)表示每分钟系统能够处理的请求数量。它通常用于衡量系统在单位时间…...
Python截图轻量化工具
这是用Python做到截图工具,不过由于使用了ctypes调用了Windows的API, 同时访问了Windows中"C:/Windows/Cursors/"中的.cur光标样式文件, 这个工具只适用于Windows环境; 如果要提升其跨平台性的话,需要考虑替换ctypes的一些专属于W…...
Python----Python高级(并发编程:协程Coroutines,事件循环,Task对象,协程间通信,协程同步,将协程分布到线程池/进程池中)
一、协程 1.1、协程 协程,Coroutines,也叫作纤程(Fiber) 协程,全称是“协同程序”,用来实现任务协作。是一种在线程中,比线程更加轻量级的存在,由程序员自己写程序来管理。 当出现IO阻塞时,…...
DeepSeek使用技巧大全(含本地部署教程)
在人工智能技术日新月异的今天,DeepSeek 作为一款极具创新性和实用性的 AI,在众多同类产品中崭露头角,凭借其卓越的性能和丰富的功能,吸引了大量用户的关注。 DeepSeek 是一款由国内顶尖团队研发的人工智能,它基于先进…...
.NET Core 8 Blazor 和 Vue 3 技术构建网
以下是一个可行的解决方案,能够满足使用 .NET Core 8 Blazor 和 Vue 3 技术构建网站,并且将前后端代码放在一个站点中,实现一次发布部署的目标。 解决方案概述 技术栈选择: 后端:.NET Core 8 Blazor Server 或 Blazor …...
ElasticSearch集群因索引关闭重打开导致飘红问题排查
背景 某组件向 ElasticSearch 写入数据,从最近某一天开始写入速度变慢,数据一直有积压。推测是 ElasticSearch 集群压力导致的,查看 ElasticSearch 集群状态,发现集群确实处于 red 状态。 本文记录 ElasticSearch 集群因索引关闭…...
计算机毕业设计Tensorflow+LSTM空气质量监测及预测系统 天气预测系统 Spark Hadoop 深度学习 机器学习 人工智能
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
