从外部禁用Linux程序的信号

从外部禁用Linux程序的信号,linux,bash,signals,external,bash-trap,Linux,Bash,Signals,External,Bash Trap,在Linux上,是否可以在外部禁用程序的信令。。。也就是说,不修改他们的源代码 上下文: 我正在从Linux上的bash脚本中调用一个C(和一个Java)程序。我不希望我的bash脚本以及脚本启动的其他程序(作为前台进程)受到任何中断 虽然我可以用 trap '' INT 。。。在我禁用Ctrl C信号的bash脚本中,这仅在程序控件恰好位于bash代码中时有效。也就是说,如果我在C程序运行时按Ctrl C,C程序会被中断并退出!这个C程序正在做一些关键的操作,因为我不希望它被中断。我没有这个

在Linux上,是否可以在外部禁用程序的信令。。。也就是说,不修改他们的源代码

上下文:

我正在从Linux上的bash脚本中调用一个C(和一个Java)程序。我不希望我的bash脚本以及脚本启动的其他程序(作为前台进程)受到任何中断

虽然我可以用

trap '' INT
。。。在我禁用Ctrl C信号的bash脚本中,这仅在程序控件恰好位于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
#/bin/bash
trap'echo您按下Ctrl C'INT
#一个模拟现实世界中长期运行的程序的C程序,
#我不想被打扰,为此我
#没有源代码!
#
#档案:y.c
#要构建:gcc-oyy.c
#
##包括
#int main(int argc,char*argv[]){
#printf(“执行关键操作…\n”);
#因为(;);//永远什么也不做。
#printf(“执行关键操作…完成。\n”);
# }
/y
问候,

/HS

此过程的“陷阱”命令是本地的,不适用于子进程

要真正捕获信号,必须使用
LD\u PRELOAD
hook对其进行破解。这不是一项繁琐的任务(您必须使用
\u init()。您可以在上找到SIGSEGV的示例

或者,尝试
nohup
tail
技巧

nohup  your_command &
tail -F nohup.out

我建议您的C(和Java)应用程序需要重写,以便能够处理异常,如果确实需要中断、电源故障等,会发生什么情况


如果失败了,J-16的钱就对了。用户是否需要与进程交互,或者只是查看输出(他们甚至需要查看输出吗?

进程信号掩码是跨
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;
}

(当然,对于腰带和背带的方法,你可以两者兼而有之)。

以上解释的解决方案对我不起作用,即使将Caf提出的两个命令链接起来

然而,我最终成功地通过这种方式获得了预期的行为:

#!/bin/zsh
setopt MONITOR
TRAPINT() { print AAA }

print 1
( ./child & ; wait)
print 2
如果我在运行
child
时按Ctrl-C,它将等待退出,然后打印AAA和2<代码>子项
将不会接收任何信号

子shell用于防止显示PID


对不起。。。这是针对zsh的,虽然问题是针对bash的,但我对bash的了解还不足以提供一个等效的脚本。

这是为阻止它的程序启用诸如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;
}
运行它:

LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld

你能用结尾处的&吗?因此,您将程序发送到后台。e、 g.cat文件&您还应该知道,按ctrl-c停止程序失败的用户通常有一种令人讨厌的倾向,即变得粗暴并开始使用kill命令。因此,尽管你付出了努力,但一定要确保你能应对整个事件被扼杀的可能性。@Eric Fortis我需要按顺序执行bash脚本中的步骤,因此无法在后台发送临时步骤。起初,我同意你的建议。。。我想,是的,为什么不把它发送到后台,然后调用“等待”内置程序。但是&+wait似乎没有什么帮助:无限循环C程序确实设法被中断,bash脚本也在此后不久退出。@Michael Kohne这是一个很好的建议。我认为这个节目的观众将包括知道“kill意味着坏”但不一定知道“Ctrl C在某些情况下也可能是坏的”的用户。尽管我将记录“不按Ctrl-C键”或“否则”的可怕后果!“子句,我想为什么不尝试通过一个陷阱和一个友好的消息来阻止它。但是如果所有这些都不可能,那么我可能只能依靠文档。+1:我对你的答案投了赞成票,但有一个问题。如果孩子明确地清除了自己的进程信号掩码怎么办?这不会使信号失效吗?”屏蔽父进程集?忽略信号可能比阻止它更有意义:
sigaction(SIGINT,&(struct-sigaction){.sa_handler=SIG_-IGN},NULL)
这就是shell为它的孩子们所做的。@caf-Boy,这是一个地狱般的答案。它似乎起作用了。+1-在我进一步评估它时告诉你(特别是根据ephemient的评论)。仅供参考,我确实尝试了一些基于包装器的解决方案,但我没有考虑execvp,而是考虑做系统(“...")内部,因此无法使其工作。非常感谢。要阻止子进程更改其自己的信号掩码,您可以使用LD_预加载库并放入您自己的信号函数来拦截标准库中的信号函数。@Vlad:
nohup
仅忽略
SIGHUP
,而不是
SIGINT
。Richo,重写是不可能的不是因为我不想,而是因为缺乏可用的资源。我相信caf的上述解决方案应该适合我。谢谢。感谢你(清楚地)告诉我关于陷阱在过程中是局部的,所以+1。但是caf的解决方案确实是我想要的。谢谢。@Harry,不用担心。你应该接受caf的回答是正确的,这样其他人就可以更容易地找到信息:)-ED这是为了不在我的帖子上。哦,好吧,这是正确的。
gcc -fPIC -shared -o fixControlC.so fixControlC.c
LD_LIBRARY_PATH=. LD_PRELOAD=fixControlC.so mysqld