Linux 如果 Ctrl+C 从二进制文件启动的 shell 脚本输入,编译的二进制文件会得到错误的退出代码
Linux compiled binary getting wrong exit code if Ctrl+C entered from a shell script launched by the binary
我这里有一个我认为很奇怪的东西。我有以下环境。
- 一个 Linux 编译的二进制文件,它设置了一个信号处理程序来禁用 Ctrl+C、Ctrl+z 等。这是通过调用信号来完成的:SIGINT、SITTSTP 和 SIGQUIT。信号处理程序只是打印一条错误消息,表明不允许用户中止程序。
- 设置信号处理程序后,二进制文件调用交互式 ash 脚本。
- 这个交互式ash脚本还禁用了所有破解脚本的方法。它在一开始使用 "trap '' INT TSTP" 来执行此操作。这有效,如果输入 Ctrl+C 等,它只是将控制字符回显到终端但不会退出。
二进制和 ash 脚本分别阻止用户退出。
但是,请注意下面发生的情况:
- 允许通过交互式 shell 脚本的正常完成将控制返回给二进制文件。一旦控制 returns 到二进制文件,输入 Ctrl+C 就可以工作并且不允许用户中断程序。 这是正确的行为。
错误的地方是:
- 在交互式 shell 脚本 运行ning 期间键入几个 Ctrl+C,一旦控制 returns 到二进制文件,退出代码将更改为以下内容shell 脚本在做什么。
这是一个例子:
在 C 代码中,假设我有:
void sigintHandler(int sig_num)
{
fprintf(stderr, "You are not allowed to exit this program.\n");
return;
}
void main(void)
{
signal(SIGINT, sigintHandler);
int ret = system("/etc/scripts/test.sh");
printf("test.sh returned: %d exit status.\n", ret);
}
在 test.sh 我有:
#!/bin/ash
# Disable interrupts so that one cannot exit shell script.
trap '' INT TSTP
echo -n "Do you want to create abc file? (y/n): "
read answer
if [ $answer == "y" ];then
touch /tmp/abc
fi
if [ -f /tmp/abc ]; then
echo "Returning 1"
exit 1
else
echo "Returning 2"
exit 2
fi
如果我 运行 C 二进制文件通常我会得到正确的退出状态(1 或 2),这取决于文件是否存在。实际上我得到 256 或 512,这表明它将退出代码存储在第二个字节中。重点是每次都能始终如一地工作。
但是现在,如果我在 shell 脚本处于 运行ning 时按下 Ctrl+C(在回答所提出的问题之前)并说我回答 "n",即退出代码 2 . 在 C 二进制文件中,我得到的代码有时是 2(不是 512,表示退出代码现在在低位字节中)但更多时候我得到的代码是 0!即使我看到 shell 脚本回显的消息 "Returning 2",也会发生这种情况。
这让我疯狂地试图弄清楚为什么一个简单的退出代码被搞砸了。
谁能提供一些建议?
非常感谢
艾伦
我发现了问题。
之前我在 shell 脚本中使用 trap '' INT TSTP 来禁用中断。虽然这可以防止 shell 脚本被中止,但它导致了这个 post 中的问题。我怀疑在禁用以这种方式中止 shell 脚本的能力时,上层 shell 框架并没有意识到这一点,它所知道的只是按下 Ctrl+C 或其他任何东西并返回 SIGINT作为退出代码,尽管 shell 脚本本身正在退出。
解决方案是使用:
stty-isig
在 shell 脚本的开头。
这不仅会禁用中断,还会让上层框架知道这是您所做的,因此它会忽略按下 Ctrl+C 的事实。
我在以下页面上找到了此信息:
https://unix.stackexchange.com/questions/80975/preventing-propagation-of-sigint-to-parent-process
谢谢大家,
艾伦
我这里有一个我认为很奇怪的东西。我有以下环境。
- 一个 Linux 编译的二进制文件,它设置了一个信号处理程序来禁用 Ctrl+C、Ctrl+z 等。这是通过调用信号来完成的:SIGINT、SITTSTP 和 SIGQUIT。信号处理程序只是打印一条错误消息,表明不允许用户中止程序。
- 设置信号处理程序后,二进制文件调用交互式 ash 脚本。
- 这个交互式ash脚本还禁用了所有破解脚本的方法。它在一开始使用 "trap '' INT TSTP" 来执行此操作。这有效,如果输入 Ctrl+C 等,它只是将控制字符回显到终端但不会退出。
二进制和 ash 脚本分别阻止用户退出。
但是,请注意下面发生的情况:
- 允许通过交互式 shell 脚本的正常完成将控制返回给二进制文件。一旦控制 returns 到二进制文件,输入 Ctrl+C 就可以工作并且不允许用户中断程序。 这是正确的行为。
错误的地方是:
- 在交互式 shell 脚本 运行ning 期间键入几个 Ctrl+C,一旦控制 returns 到二进制文件,退出代码将更改为以下内容shell 脚本在做什么。
这是一个例子:
在 C 代码中,假设我有:
void sigintHandler(int sig_num)
{
fprintf(stderr, "You are not allowed to exit this program.\n");
return;
}
void main(void)
{
signal(SIGINT, sigintHandler);
int ret = system("/etc/scripts/test.sh");
printf("test.sh returned: %d exit status.\n", ret);
}
在 test.sh 我有:
#!/bin/ash
# Disable interrupts so that one cannot exit shell script.
trap '' INT TSTP
echo -n "Do you want to create abc file? (y/n): "
read answer
if [ $answer == "y" ];then
touch /tmp/abc
fi
if [ -f /tmp/abc ]; then
echo "Returning 1"
exit 1
else
echo "Returning 2"
exit 2
fi
如果我 运行 C 二进制文件通常我会得到正确的退出状态(1 或 2),这取决于文件是否存在。实际上我得到 256 或 512,这表明它将退出代码存储在第二个字节中。重点是每次都能始终如一地工作。
但是现在,如果我在 shell 脚本处于 运行ning 时按下 Ctrl+C(在回答所提出的问题之前)并说我回答 "n",即退出代码 2 . 在 C 二进制文件中,我得到的代码有时是 2(不是 512,表示退出代码现在在低位字节中)但更多时候我得到的代码是 0!即使我看到 shell 脚本回显的消息 "Returning 2",也会发生这种情况。
这让我疯狂地试图弄清楚为什么一个简单的退出代码被搞砸了。
谁能提供一些建议?
非常感谢 艾伦
我发现了问题。
之前我在 shell 脚本中使用 trap '' INT TSTP 来禁用中断。虽然这可以防止 shell 脚本被中止,但它导致了这个 post 中的问题。我怀疑在禁用以这种方式中止 shell 脚本的能力时,上层 shell 框架并没有意识到这一点,它所知道的只是按下 Ctrl+C 或其他任何东西并返回 SIGINT作为退出代码,尽管 shell 脚本本身正在退出。
解决方案是使用:
stty-isig
在 shell 脚本的开头。
这不仅会禁用中断,还会让上层框架知道这是您所做的,因此它会忽略按下 Ctrl+C 的事实。
我在以下页面上找到了此信息:
https://unix.stackexchange.com/questions/80975/preventing-propagation-of-sigint-to-parent-process
谢谢大家, 艾伦