李斯特 发表于 2018-8-24 09:28:42

Shell 信号发送与捕捉

  防伪码:李白乘舟将欲行,忽闻岸上踏歌声。
  9.1 Linux信号类型
  信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行响
  应的处理函数。
  进程可以通过三种方式来响应一个信号:
  1)忽略信号,即对信号不做任何处理,其中有两个信号不能忽略:SIGKILL 及 SIGSTOP。
  2)捕捉信号。
  3)执行缺省操作,Linux 对每种信号都规定了默认操作。
  Linux 究竟采用上述三种方式的哪一个来响应信号呢?取决于传递给响应 API 函数的参数。
  Linux 支持的信号有:
  编号信号名称缺省动作描述
  1SIGHUP终止终止进程,挂起
  2SIGINT终止键盘输入中断命令,一般是 CTRL+C
  3SIGQUITCoreDump键盘输入退出命令,一般是 CTRL+\
  4SIGILLCoreDump非法指令
  5SIGTRAPCoreDumptrap 指令发出,一般调试用
  6SIGABRTCoreDumpabort(3)发出的终止信号
  7SIGBUSCoreDump非法地址
  8SIGFPECoreDump浮点数异常
  9SIGKILL终止立即停止进程,不能捕获,不能忽略
  10SIGUSR1终止
  用户自定义信号 1,像 Nginx 就支持 USR1 信号,用于重载配
  置,重新打开日志
  11SIGSEGVCoreDump无效内存引用
  12SIGUSR2终止用户自定义信号 2
  13SIGPIPE终止管道不能访问
  14SIGALRM终止时钟信号,alrm(2)发出的终止信号
  15SIGTERM终止
  终止信号,进程会先关闭正在运行的任务或打开的文件再终
  止,有时间进程在有运行的任务而忽略此信号。不能捕捉
  16SIGSTKFLT终止处理器栈错误
  17SIGCHLD可忽略子进程结束时,父进程收到的信号
  18SIGCONT可忽略让终止的进程继续执行
  19SIGSTOP停止停止进程,不能忽略,不能捕获
  20SIGSTP停止停止进程,一般是 CTRL+Z
  21SIGTTIN停止后台进程从终端读数据
  22SIGTTOU停止后台进程从终端写数据
  23SIGURG可忽略紧急数组是否到达 socket
  24SIGXCPUCoreDump超出 CPU 占用资源限制
  25SIGXFSZCoreDump超出文件大小资源限制
  26SIGVTALRM终止
  虚拟时钟信号,类似于 SIGALRM,但计算的是进程占用的时
  间
  27SIGPROF终止类似与 SIGALRM,但计算的是进程占用 CPU 的时间
  28SIGWINCH可忽略窗口大小改变发出的信号
  29SIGIO终止文件描述符准备就绪,可以输入/输出操作了
  30SIGPWR终止电源失败
  31SIGSYSCoreDump非法系统调用
  CoreDump(核心转储):当程序运行过程中异常退出时,内核把当前程序在内存状况存储在一个
  core 文件中,以便调试。
  Linux 支持两种信号:
  一种是标准信号,编号 1-31,称为非可靠信号(非实时),不支持队列,信号可能会丢失,比如发
  送多次相同的信号,进程只能收到一次,如果第一个信号没有处理完,第二个信号将会丢弃。
  另一种是扩展信号,编号 32-64,称为非可靠信号(实时),支持队列,发多少次进程就可以收到
  多少次。
  信号类型比较多,我们只要了解下,记住几个常用信号就行了,红色标记的我觉得需要记下。
  发送信号一般有两种情况:
  一种是内核检测到系统事件,比如键盘输入 CTRL+C 会发送 SIGINT 信号。
  另一种是通过系统调用 kill 命令来向一个进程发送信号。
  l 9.2 kill命令
  kill 命令发送信号给进程。
  命令格式:kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l
  
  -s # 信号名称
  -n # 信号编号
  -l # 打印编号 1-31 信号名称
  示例:
  给一个进程发送终止信号:
  kill -s SIGTERM pid
  或
  kill -n 15 pid
  或
  kill -15 pid
  或
  kill -TREM pid
  p 9.3 trap命令
  trap 命令定义 shell 在处理程序运行时接受信号,来做相应的处理。
  命令格式:trap [-lp] [ signal_spec ...]
  -l # 打印编号 1-64 编号信号名称
  arg # 捕获信号后执行的命令或者函数
  signal_spec # 信号名或编号
  一般捕捉信号后,做以下几个行动:
  1)清除临时文件
  2)忽略该信号
  3)询问用户是否终止脚本执行
  示例 1:按 CTRL+C 不退出循环
  #!/bin/bash
  trap "" 2 # 不指定 arg 就不做任何操作,后面也可以写多个信号,以空格分隔
  for i in {1..10}; do
  echo $i
  sleep 1
  done
  # bash a.sh
  1
  2
  3
  ^C4
  5
  6
  ^C7
  8
  9
  10
  示例 2:循环打印数字,按 CTRL+C 退出,并打印退出提示
  #!/bin/bash
  trap "echo 'exit...';exit" 2
  for i in {1..10}; do
  echo $i
  sleep 1
  done
  # bash test.sh
  1
  2
  3
  ^Cexit...
  示例 3:让用户选择是否终止循环
  #!/bin/bash
  trap "func" 2
  func() {
  read -p "Terminate the process? (Y/N): " input
  if [ $input == "Y" ]; then
  exit
  fi
  }
  for i in {1..10}; do
  echo $i
  sleep 1
  done
  # bash a.sh
  1
  2
  3
  ^CTerminate the process? (Y/N): Y
  # bash a.sh
  1
  2
  3
  ^CTerminate the process? (Y/N): N
  4
  5
  6
  ...
  谢谢观看,真心的希望能帮到您!

页: [1]
查看完整版本: Shell 信号发送与捕捉