在Linux上,是否有可能以某种方式禁用外部程序的信令......即不修改源代码?
上下文
我正在Linux上的bash脚本中调用C(和Java )程序。我不希望我的bash脚本和脚本启动的其他程序(作为前台进程)中断。
虽然我可以使用......
trap '' INT
...在我的bash脚本中禁用Ctrl C信号,这仅在程序控件恰好在bash代码中时才有效。也就是说,如果我在C程序运行时按下Ctrl C,C程序会被中断并退出!这个C程序正在进行一些关键操作,因此我不希望它被中断。我无法访问此C程序的源代码,因此C程序内的信号处理是不可能的。
#!/bin/bash
trap 'echo You pressed Ctrl C' INT
# A C program to emulate a real-world, long-running program,
# which I don't want to be interrupted, and for which I
# don't have the source code!
#
# File: y.c
# To build: gcc -o y y.c
#
# #include <stdio.h>
# int main(int argc, char *argv[]) {
# printf("Performing a critical operation...\n");
# for(;;); // Do nothing forever.
# printf("Performing a critical operation... done.\n");
# }
./y
此致
/ HS
答案 0 :(得分:13)
进程信号掩码在exec
之间继承,因此您只需编写一个阻塞SIGINT
的小包装器程序并执行目标:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGINT);
sigprocmask(SIG_BLOCK, &sigs, 0);
if (argc > 1) {
execvp(argv[1], argv + 1);
perror("execv");
} else {
fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
}
return 1;
}
如果您将此程序编译为noint
,则只需执行./noint ./y
。
作为注释中的流行音符,信号处理也是继承的,所以你可以让包装器忽略信号而不是阻塞信号:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
struct sigaction sa = { 0 };
sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &sa, 0);
if (argc > 1) {
execvp(argv[1], argv + 1);
perror("execv");
} else {
fprintf(stderr, "Usage: %s <command> [args...]\n", argv[0]);
}
return 1;
}
(当然,对于腰带和牙套的方法,你可以做到这两点)。
答案 1 :(得分:3)
“陷阱”命令是此过程的本地命令,从不适用于儿童。
要真正捕获信号,您必须使用LD_PRELOAD
挂钩来破解它。这是非繁琐的任务(您必须使用_init()
,sigaction()
编译可加载的内容),因此我不会在此处包含完整代码。您可以在Phack Volume 0x0b, Issue 0x3a, Phile #0x03上找到SIGSEGV的示例。
另外,请尝试nohup
和tail
技巧。
nohup your_command &
tail -F nohup.out
答案 2 :(得分:0)
我建议您的C(和Java)应用程序需要重写,以便它可以处理异常,如果确实需要中断,电源故障等会发生什么......
我失败了,J-16是对的。用户是否需要与流程相互作用,或者只是看输出(他们甚至需要查看输出吗?)
答案 3 :(得分:0)
上面解释的解决方案对我来说不起作用,即使链接了Caf提出的两个命令。
但是,我终于成功地以这种方式获得了预期的行为:
#!/bin/zsh
setopt MONITOR
TRAPINT() { print AAA }
print 1
( ./child & ; wait)
print 2
如果我在child
运行时按下Ctrl-C,它将等待它退出,然后将打印AAA和2. child
将不会收到任何信号。
子shell用于防止显示PID。
抱歉......这是针对zsh的,虽然问题是关于bash,但我不知道bash足以提供一个等效的脚本。
答案 4 :(得分:0)
这是为阻止它的程序启用Ctrl + C等信号的示例代码。
fixControlC.c
#include <stdio.h>
#include <signal.h>
int sigaddset(sigset_t *set, int signo) {
printf("int sigaddset(sigset_t *set=%p, int signo=%d)\n", set, signo);
return 0;
}
编译:
gcc -fPIC -shared -o fixControlC.so fixControlC.c
运行它:
LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld