防止 SIGINT 中断当前任务,同时仍然传递有关 SIGINT 的信息(并保留退出代码) [英] Prevent SIGINT from interrupting current task while still passing information about SIGINT (and preserve the exit code)

查看:31
本文介绍了防止 SIGINT 中断当前任务,同时仍然传递有关 SIGINT 的信息(并保留退出代码)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很长的 shell 脚本,我正在尝试为它添加信号处理.

I have a quite long shell script and I'm trying to add signal handling to it.

脚本的主要任务是运行各种程序,然后清理它们的临时文件.

The main task of the script is to run various programs and then clean up their temporary files.

我想捕获 SIGINT.当信号被捕获时,脚本应等待当前程序执行完毕,然后进行清理并退出.

I want to trap SIGINT. When the signal is caught, the script should wait for the current program to finish execution, then do the cleanup and exit.

这是一个 MCVE:

#!/bin/sh

stop_this=0
trap 'stop_this=1' 2

while true ; do
    result="$(sleep 2 ; echo success)" # run some program
    echo "result: '$result'"
    echo "Cleaning up..." # clean up temporary files
    if [ $stop_this -ne 0 ] ; then
        echo 'OK, time to stop this.'
        break
    fi
done

exit 0

预期结果:

Cleaning up...
result: 'success'
Cleaning up...
^Cresult: 'success'
Cleaning up...
OK, time to stop this.

实际结果:

Cleaning up...
result: 'success'
Cleaning up...
^Cresult: ''
Cleaning up...
OK, time to stop this.

问题是当前正在运行的指令(result="$(sleep 2 ; echo success)" 在这种情况下)被中断了.我该怎么做才能让它表现得更像我设置了 trap '' 2?

The problem is that the currently running instruction (result="$(sleep 2 ; echo success)" in this case) is interrupted. What can I do so it would behave more like I was set trap '' 2?

我正在寻找 POSIX 解决方案或大多数 shell 解释器(BusyBox、dash、Cygwin...)支持的解决方案

I'm looking for either a POSIX solution or one that is supported by most of shell interpreters (BusyBox, dash, Cygwin...)

我已经看到了 防止 SIGINT 关闭子进程的答案在 bash 脚本中 但这对我来说并不真正有效.所有这些解决方案都需要修改不应中断的每一行.我的真实脚本很长,而且比示例复杂得多.我将不得不修改数百行.

I already saw answers for Prevent SIGINT from closing child process in bash script but this isn't really working for me. All of these solutions require to modify each line which shouldn't be interrupted. My real script is quite long and much more complicated than the example. I would have to modify hundreds of lines.

推荐答案

@PSkocik 和 @WilliamPursell 的回答都帮助我走上了正轨.

Both answers from @PSkocik and @WilliamPursell have helped me to get on the right track.

我有一个完全有效的解决方案.这不是很好,因为它需要使用外部文件来表明信号没有发生,但除此之外它应该可靠地工作.

I have a fully working solution. It ain't pretty because it needs to use an external file to indicate that the signal didn't occurred but beside that it should work reliably.

#!/bin/sh

touch ./continue
trap 'rm -f ./continue' 2

( # the whole main body of the script is in a separate background process
trap '' 2 # ignore SIGINT
while true ; do
    result="$(sleep 2 ; echo success)" # run some program
    echo "result: '$result'"
    echo "Cleaning up..." # clean up temporary files
    if [ ! -e ./continue ] ; then # exit the loop if file "./continue" is deleted
        echo 'OK, time to stop this.'
        break
    fi
done
) & # end of the main body of the script
while ! wait ; do : ; done # wait for the background process to end (ignore signals)
wait $! # wait again to get the exit code
result=$? # exit code of the background process

rm -f ./continue # clean up if the background process ended without a signal

exit $result

<小时>

编辑:此代码在 Cygwin 中存在一些问题.


EDIT: There are some problems with this code in Cygwin.

有关信号工作的主要功能.但是,完成的后台进程似乎并没有像僵尸一样留在系统中.这使得 wait $! 不起作用.脚本的退出代码具有错误的 127 值.

The main functionality regarding signals work. However, it seems like the finished background process doesn't stay in the system as a zombie. This makes the wait $! to not work. The exit code of the script has incorrect value of 127.

解决方案是删除行 wait $!result=$?result=$? 所以脚本总是返回 0.也应该可以通过使用另一层子shell保留正确的错误代码并将退出代码临时存储在文件中.

Solution to that would be removing lines wait $!, result=$? and result=$? so the script always returns 0. It should be also possible to keep the proper error code by using another layer of subshell and temporarily store the exit code in a file.

这篇关于防止 SIGINT 中断当前任务,同时仍然传递有关 SIGINT 的信息(并保留退出代码)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆