Unix 指南/解释/信号
信号是软件中断,通知进程某个条件或事件已经发生。产生信号的事件示例包括:
- 进程尝试进行除零运算
- 用户在终端按下中断键
- 进程使用 kill 命令或 kill 函数向另一个进程发送信号
可以使用以下命令显示所有不同信号的列表:
$ kill -l
kill 命令还可以用于向其他进程发送信号。启动一个在后台运行 1000 秒的睡眠进程
$ sleep 1000 & [1] 14936 $ ps PID TTY TIME CMD 14936 pts/7 0:00 sleep 12203 pts/7 0:01 bash
注意,当你运行它时,进程 ID(很可能)会不同。下面的命令行向进程 14936(在本例中)发送 SIGKILL 信号
$ kill -KILL 14936 $ ps PID TTY TIME CMD 12203 pts/7 0:01 ksh [1] + Killed sleep 1000 &
收到 SIGKILL 信号后,sleep 进程将终止。
进程可以以三种不同的方式响应信号
- 执行默认操作
- 忽略信号。
- 执行指定函数(称为信号处理程序)
进程在收到信号时执行的默认操作取决于信号类型。大多数信号(如 SIGKILL)会导致进程终止。其他信号,如 SIGQUIT,会导致进程终止并生成核心转储
$ sleep 1000 & [1] 14950 $ kill -QUIT 14950 $ ps PID TTY TIME CMD 12203 pts/7 0:01 bash [1] + Quit(coredump) sleep 1000 & $ ls core core
核心文件可能很大,因此请将其删除
$ rm core
可以使用 trap 命令捕获信号。在文件 catch_signal.sh 中创建以下 shell 脚本
#!/bin/bash trap 'echo "GOTCHA!"' INT KILL while : do sleep 10 done
在后台运行 catch_signal.sh
$ catch_signal.sh & [1] 15053 $ kill -INT 15053 $ GOTCHA!
信号已捕获,并且未终止(这是 SIGINT 的默认操作),而是将消息 "GOTCHA!" 回显到标准输出。
但是,某些信号无法捕获,例如 SIGKILL
$ kill -KILL 15053 [1] + Killed catch_signal &
运行 catch_signal.sh;在前景中
$ catch_signal
按下中断键(通常是 Ctrl+C)
^CGOTCHA!
现在按下退出键
^\catch_signal[3]: 15102 Quit(coredump) $ ls core # will have generated a core file core
使用 nohup 运行的命令在用户注销时不会终止。
在文件 dont_hangup.sh 中创建脚本,并使其可执行
#!/bin/bash while : do date sleep 100 done
在后台运行它,前面加上命令 nohup
$ nohup dont_hangup.sh & [1] 15224 Sending output to nohup.out
检查其运行状态:id(在本例中为 12203)
$ ps -fu aholt aholt 15224 12203 pts/7 sh ./dont_hangup.sh aholt 15232 15224 pts/7 sleep 100
记录 "dont_hangup" 的父进程 ID(在本例中为 12203)和终端设备,然后注销你的会话。
再次登录。可以看到 dont_hangup.sh 仍在运行
$ ps -fu aholt aholt 15224 1 ? 0:00 sh ./dont_hangup.sh aholt 15237 15224 ? 0:00 sleep 100
虽然 "dont_hangup.sh" 仍在运行,但其父进程已更改。父进程的 ID 为 1(而不是之前的 12203),并且不再与终端设备关联。使用 nohup 等同于忽略 SIGHUP,即
trap '' HUP