在bash脚本中,当信号被困时会发生什么

发布于 2025-01-20 03:44:00 字数 859 浏览 0 评论 0 原文

假设我正在运行以下示例保存为 hello.sh

#!/bin/bash
hello() {
    echo "hello"
}

trap "hello" INT
sleep 100
echo "end"

而在Shell I开始 Hello.sh 。 1秒钟后,我按 ctrl-c

请将睡眠视为我开始的任何长期过程。

这是我的问题:

  1. 当生成 sigint 时,它是直接传递到 Sleep 还是直接发送给Shell脚本?
  2. 如果是第二个,我可以让睡眠有机会处理 sigint ,并且不传播其父 hello.shy.sh 吗?
  3. 如果是第一个,睡眠的状态是什么?

我的测试使我觉得以下发生在

  1. 睡眠开始运行
  2. hello.sh 接收到信号
  3. 函数 Hello 开始运行
  4. 函数 > Hello 完成
  5. echo“ end” 开始运行
  6. 脚本退出。

但是在哪个阶段,睡眠过程退出,并且由于什么(例如Sigint停止了 Sleep 过程?)

Suppose I am running the following example saved as hello.sh

#!/bin/bash
hello() {
    echo "hello"
}

trap "hello" INT
sleep 100
echo "end"

and in shell I start hello.sh. After 1 second I press Ctrl-C.

Please treat sleep as any long-run process that I started.

Here are my questions:

  1. When SIGINT is generated, is it delivered to sleep directly or to the shell script?
  2. If it is the second, can I let sleep has a chance to handle the SIGINT and do not propagate to its parent hello.sh?
  3. If it is the first, what is the status of sleep after the hello function is finished?

My tests made me feel that the following occurred in order

  1. sleep started to run
  2. hello.sh received the signal
  3. function hello started to run
  4. function hello finished
  5. echo "end" started to run
  6. the script exits.

But at which stage the sleep process exits and because of what (e.g. the SIGINT stopped the sleep process?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江心雾 2025-01-27 03:44:00
$ cat foo.sh
_sigint()
{
    echo "received SIGINT"
}

trap _sigint INT

sleep 10000
echo "status=$?"
$ bash foo.sh              # <-- start foo.sh and then press CTRL-C
^Creceived SIGINT
status=130

一些解释:

  • sleep 作为 bash 的子进程运行。 bashsleep 在同一个进程组中运行,该进程组现在是前台进程组

  • 当按下CTRT-C时,它将生成SIGINT,并且该信号将发送到中的所有进程前台进程组,因此 bashsleep 都会收到 SIGINT

  • 根据bash 手册 (可以另请参阅man bash

    <块引用>

    如果 bash 正在等待命令完成并接收到已设置陷阱的信号,则陷阱将不会执行直到命令完成

    所以这里bash会等待sleep被杀死(默认的SIGINT行为是终止进程。请参阅signal(7)) 首先,然后 bash运行它的SIGINT 陷阱。

  • 根据 bash 手册

    <块引用>

    简单命令的返回值是其退出状态,如果命令由信号 n 终止,则为 128+n

    SIGINT 为 2 (请参阅 kill -l,因此 sleep 的退出状态为 128+2=130

$ cat foo.sh
_sigint()
{
    echo "received SIGINT"
}

trap _sigint INT

sleep 10000
echo "status=$?"
$ bash foo.sh              # <-- start foo.sh and then press CTRL-C
^Creceived SIGINT
status=130

Some explanation:

  • sleep runs as a child process of bash. bash and sleep are running in the same process group which is now the foreground process group.

  • When CTRT-C is pressed, it'll generate SIGINT and the signal will be sent to all processes in the foreground process group so both bash and sleep will receive SIGINT.

  • According to bash manual (can also see man bash)

    If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.

    So here bash would wait for sleep to be killed (The default SIGINT behavior is to terminate the process. See signal(7)) first and then bash runs its SIGINT trap.

  • According to bash manaul

    The return value of a simple command is its exit status, or 128+n if the command is terminated by signal n.

    The SIGINT is 2 (see kill -l) so sleep's exit status is 128+2=130.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文