当前位置: 首页 > news >正文

【Linux】信号处理

一、Linux系统信号

1、常见的系统信号

常见的Linux系统信号
信号描述
1SIGHUP挂起(hang up)进程
2SIGINT中断进(interrupt)程
3SIGQUIT停止(stop)进程
9SIGKILL无条件终止(terminate)进程
15SIGTERM尽可能终止进程
18SIGCONT继续运行停止的进程
19SIGSTOP无条件停止,但不终止进程
20SIGTSTP停止或暂停(pause),但不终止进程

2、两种基本的信号

中断进程Ctrl+C

Ctrl+C生成的是SIGINT信号,它会将其发送给当前在shell中运行的所有进程。

暂停进程Ctrl+Z

Ctrl+Z生成的是SIGTSTP信号,停止shell中运行的任何进程。

停止(stopping)进程和终止(terminating)进程不同,前者是让程序继续驻留在内存中,但依然能从上次停止的位置继续运行。

方括号里的数字 1 是shell分配的作业号

shell将运行的各个进程称为作业,并且为作业在当前shell内分配了唯一的作业号。作业号从1开始,接着是2,依次递增。

如果shell会话中存在一个已经停止的作业,那么在退出shell时,bash会给出提醒。

此时只需要再输入一遍exit命令即可,shell就会退出,并终止已停止的作业。

也可以用kill命令发送SIGKILL(9)信号将其终止。

ps命令查看已停止的作业。

 3、捕获信号trap命令

trap命令可以让shell脚本需要侦测并拦截的Linux信号,如果脚本收到了trap命令中列出的信号,则该信号不再由shell处理,而是由本地处理。

格式:

trap commands signals

commands:列出想要shell执行的命令;

signals:列出想要捕获的信号(多个信号之间用空格分隔)。指定信号时可用信号的值或信号名。

#!/bin/bashtrap "echo '捕获到了Ctrl+C信号'" SIGINTecho "测试脚本"count=1
while [ $count -le 5 ]
doecho "这是第$count次循环"sleep 1count=$[ $count + 1 ]
doneecho "测试脚本结束!"
exit

此shell脚本每次侦测到Ctrl+C信号(SIGINT)时,trap命令都会打印出一条“捕获”信息。通过此,可以阻止用户通过Ctrl+C停止脚本。 

如果shell脚本中的命令被信号中断,使用带有指定命令的trap未必能让被中断的命令继续执行。为了保证脚本中的关键操作不被打断,可以使用带有空操作命令的trap以及要捕获的信号列表。

如:trap " " SIGINT

此形式的trap命令可以让shell脚本完全忽略SIGINT信号,继续执行重要工作。 

捕获shell脚本在退出时的信号

在trap命令后加上EXIT信号即可。

#!/bin/bashtrap "echo '此脚本已执行完,马上退出……'" EXITecho "测试脚本"count=1
while [ $count -le 5 ]
doecho "这是第$count次循环"sleep 1count=$[ $count + 1 ]
doneecho "测试脚本结束!"
exit
正常退出 

 

提前退出

 

修改或移除信号捕获

要想在shell脚本中不同位置进行不同的信号捕获处理,只需要重新使用带有新选项的trap命令即可。

#!/bin/bashtrap "echo '捕获到Ctrl+C信号'" SIGINTecho "第1项测试"count=1
while [ $count -le 5 ]
doecho "这是第$count次循环"sleep 1count=$[ $count + 1 ]
donetrap "echo '捕获到Ctrl+Z信号'" 20echo "第2项测试"count=1
while [ $count -le 4 ]
doecho "这是第$count次循环"sleep 1count=$[ $count + 1 ]
doneexit

查看被捕获的信号

在交互式shell会话中使用 trap -p 查看被捕获的信号。如果什么都没显示,说明shell会话按照默认方式处理了信号。

移除已设置好的信号捕获

 在trap命令与希望恢复默认行为的信号列表之间加上两个连字符,如 trap -- SIGINT;也可以在trap命令后使用单连字符来恢复信号的默认行为,如 trap - SIGINT

#!/bin/bashtrap "echo '捕获到Ctrl+C信号'" SIGINTecho "第1项测试"count=1
while [ $count -le 5 ]
doecho "这是第$count次循环"sleep 1count=$[ $count + 1 ]
donetrap -- SIGINT # 等同于trap - SIGINT
echo "移除信号捕获。"echo "第2项测试"count=1
while [ $count -le 4 ]
doecho "这是第$count次循环"sleep 1count=$[ $count + 1 ]
doneexit

在移除信号捕获后,一旦执行Ctrl+C,就会立即停止执行脚本。 

二、后台运行脚本

 使用 ps -e 命令,查看系统后台运行的进程。

在后台运行模式中,进程运行时不和终端会话的STDIN、STDOUT、STDERR关联。

1、后台运行脚本

在脚本名后面加上 & 即可,它会将脚本与当前shell分离开,并将脚本作为一个独立的后台进程运行。

方括号里的数字 1 是shell分配给后台进程的作业号,数字 109747 是Linux系统为进程分配的进程ID(PID)。Linux系统中的每个进程都必须有唯一的PID。

注:如下所示,当后台进程运行时,它仍然会使用终端显示器来显示STDOUT和STDERR的消息。

 

如下所示,后台运行时可以执行其它命令 

三、在非控制台下运行脚本

 退出终端会话后,仍然想让脚本一直在后台运行直到结束。可以使用 nohup 命令实现。

nohup命令可以阻断发给特定进程的SIGHUP信号,当退出终端会话时,便可以避免进程退出。

格式:nohup command

 当使用nohup命令时,如果关闭终端会话,shell脚本会忽略其发送的SIGHUP信号。由于nohup命令会解除终端与进程之间的关联,因此进程不再同STDOUT和STDERR绑定在一起。为了保存该命令产生的输出,nohup命令会自动将STDOUT和STDERR产生的消息重定向到 nohup.out 的文件中。(nohup.out文件一般在当前工作目录下,不然就在$HOME目录下)

如果使用nohup运行了另一个命令,则该命令的输出会被追加到已有的nohup.out文件中。

四、作业控制

 kill命令可以杀死作业,如果要重启已停止的进程,需要向其发送SIGCONT信号。

作业控制包括启动、停止、杀死恢复

1、查看作业jobs命令

jobs 命令允许用户查看shell当前正在处理的作业。

#!/bin/bashecho "脚本的PID:$$" # $$是一个特殊变量,它表示shell进程的进程ID(PID)count=1
while [ $count -le 6 ]
doecho "这是第$count次循环。"sleep 8count=$[ $count + 1 ]
doneecho "脚本结束……"
exit

 运行脚本后,使用 Ctrl+Z 组合键停止脚本。

然后在后台又运行一次此脚本,并将输出重定向到文件 test1.out 中。

 使用 jobs 命令查看分配给shell的作业。

如下图所示,加号 + 表示默认作业。如果作业控制命令没有指定作业号,则引用该默认作业。

减号 - 表示在默认作业结束后成为下一个默认作业。

任何时候,不管shell中运行着多少作业,带加号和减号的作业都有且只能有一个。

jobs -l 查看作业的进程号。

 

jobs命令选项
-l列出进程的PID以及作业号
-n只列出上次shell发出通知后状态发生改变的作业
-p只列出作业的PID
-r只列出运行中的作业
-s只列出已停止的作业

删除已停止的作业

2、重启已停止的作业bg命令

可以将已停止的作业作为后台进程或前台进程重启(注:前台进程重启后会接管当前正在使用的终端)

后台模式重启:bg命令

注:当作业被转入后台模式后,并不会显示其PID。

如果存在多个作业,需要在bg命令后加上作业号,如 bg 2

前台模式重启:fg命令

如下所示,因为作业是在前台运行的,所以直到该作业完成后,命令行界面的提示符才会出现。

http://www.lryc.cn/news/516782.html

相关文章:

  • 5个不同类型的mysql数据库安装
  • python学习笔记—12—布尔类型、if语句
  • 分数阶傅里叶变换代码 MATLAB实现
  • 《数据结构》期末考试测试题【中】
  • openwrt 清缓存命令行
  • RP2K:一个面向细粒度图像的大规模零售商品数据集
  • .NET Core FluentAPI
  • 【C++数据结构——查找】顺序查找(头歌实践教学平台习题)【合集】
  • HTTP Scheme 通常指的是在 URL 中用于指定使用 HTTP 协议的方案(scheme)
  • 基于Matlab的变压器仿真模型建模方法(13):单相升压自耦变压器的等效电路和仿真模型
  • 【Vue.js】监听器功能(EventListener)的实际应用【合集】
  • 【Shell脚本】Docker构建Java项目,并自动停止原镜像容器,发布新版本
  • 【iOS Swift Moya 最新请求网络框架封装通用】
  • 前端批量下载文件
  • 【pytorch-lightning】架构一览
  • MongoDB相关使用问题
  • DevSecOps自动化在安全关键型软件开发中的实践、Helix QAC Klocwork等SAST工具应用
  • 常见的显示器分辨率及其对应的像素数量
  • TDengine + MQTT :车联网时序数据库如何高效接入
  • maven的中国镜像有哪些
  • ModelScope ms-swift:轻量级模型微调框架
  • 深度解析与实践:HTTP 协议
  • Zookeeper是如何解决脑裂问题的?
  • 《Opencv》基础操作详解(5)
  • AI大模型-提示工程学习笔记2
  • AWS ELB基础知识
  • 我用Ai学Android Jetpack Compose之Text
  • Robot---奇思妙想轮足机器人
  • springcloud 介绍
  • 【STM32】I2C为什么要开漏输出和上拉电阻