我正在开发一个利用关闭挂钩的Java应用程序,以便清除程序的终止/中断,但我注意到Cygwin的CTRL-C实现似乎没有触发关闭挂钩.从表面上看,似乎已中断了该过程,将控制权交还给命令行,但是根本不会触发进程的"关闭"挂钩,因此不会发生清理.
在cmd中它们被捕获,但由于各种约束,我需要以某种方式让它们在Cygwin中工作.
有什么方法可以通过Cygwin在正在运行的进程中触发SIGINT,或者可能是我可以用来清理中断和终止的关闭挂钩的替代方法?
我的目录中有以下两个文件:
Dockerfile
FROM debian
WORKDIR /app
COPY start.sh /app/
CMD ["/app/start.sh"]
Run Code Online (Sandbox Code Playgroud)
start.sh(使用权限 755 chmod +x start.sh)
FROM debian
WORKDIR /app
COPY start.sh /app/
CMD ["/app/start.sh"]
Run Code Online (Sandbox Code Playgroud)
然后我运行以下命令:
$ docker build . -t tmp
$ docker run --name tmp tmp
Run Code Online (Sandbox Code Playgroud)
然后我期望按 Ctrl+C 会向程序发送 SIGINT,该程序会将 SIGINT 打印到屏幕然后退出,但这并没有发生。
我还尝试运行$ docker stop tmp,我希望它会向程序发送一个 SIGTERM ,但$ docker logs tmp之后检查显示 SIGTERM 未被捕获。
为什么 bash 脚本没有捕获 SIGINT 和 SIGTERM?
我有一个在远程机器上运行的程序,它希望从父代接收SIGINT.该程序需要接收该信号才能正常运行.不幸的是,如果我通过SSH远程运行该进程并发送SIGINT,则ssh进程本身会捕获并中断而不是转发信号.
以下是使用GDB的此行为的示例:
在本地运行:
$ gdb GNU gdb 6.3.50-20050815 (Apple version gdb-1344) (Fri Jul 3 01:19:56 UTC 2009) ... This GDB was configured as "x86_64-apple-darwin". ^C (gdb) Quit ^C (gdb) Quit ^C (gdb) Quit
远程运行:
$ ssh foo.bar.com gdb GNU gdb Red Hat Linux (6.3.0.0-1.159.el4rh) ... This GDB was configured as "i386-redhat-linux-gnu". (gdb) ^C Killed by signal 2. $
任何人都可以建议一种解决这个问题的方法吗?本地ssh客户端是OpenSSH_5.2p1.
我有一个分叉的Perl脚本.
每个fork运行一个外部程序,解析输出,并将输出转换为Storable文件.
然后由父母读入可存储文件,并且在继续重复前一个分支之前分析来自每个孩子的总数据,否则父母停止.
当一些孩子仍在运行外部程序时发出^ C时到底发生了什么?在前台调用父perl脚本,我认为,尽管有分叉,仍保留在前台.
是否将SIGINT传递给所有子节点,即父节点,父节点的子节点以及子节点调用的外部程序?
更新:
我应该补充一点,看来当我发出SIGINIT时,我脚本的子节点调用的外部程序似乎会确认信号并终止.但孩子们,或者父母的计划,继续下去.这一点对我来说都不清楚.
更新2:
关于tchrist的评论,外部程序是用Perl的system()命令调用的.
事实上,tchrist的评论似乎也包含了我正在寻找的解释.经过一些调试后,根据我的程序的行为,看来确实,SIGINT正从父级传递给所有子级,并且从所有子级传递给所有子级(外部程序).
因此,根据tchrist的评论,似乎正在发生的事情是CTRL-C正在杀死外部程序,导致孩子们离开system()命令 - 仅此而已.
虽然我让我的孩子检查了所调用内容的退出状态system(),但我假设CTRL-C会从父节点中删除所有内容,而不是导致创建更多轮处理,这就是发生的事情! !
解决方案(对我的问题):
我需要在父级中为SIGINT创建一个信号处理程序.然后信号处理程序将SIGTERM发送给每个子节点(我假设它也会向子节点的子节点发送SIGTERM),然后使父节点正常退出.虽然这个有点明显的解决方案可能会解决问题,但我想理解我对于在Perl中分叉的SIGINT行为的误解.
在子/后台进程中运行时,我无法捕获信号.
这是我简单的bash脚本:
#!/bin/bash
echo "in child"
trap "got_signal" SIGINT
function got_signal {
echo "trapped"
exit 0
}
while [ true ]; do
sleep 2
done
Run Code Online (Sandbox Code Playgroud)
当运行这个以后再做
kill -SIGINT (pid)
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,打印"被困"并退出.
现在,如果我从父脚本启动相同的脚本,如下所示:
#!/bin/bash
echo "starting the child"
./child.sh &
Run Code Online (Sandbox Code Playgroud)
然后孩子不再陷入信号......?
更改为使用SIGTERM而不是SIGINT后,它似乎正常工作......?
我的python脚本用信号处理模块拦截SIGINT信号以防止过早退出,但是这个信号被传递给我用Popen打开的子进程.是否有一些方法可以防止将此信号传递给子进程,以便在用户按下ctrl-c时也不会过早退出?
我试图SIGINT在Python 2.7程序中捕获(或键盘中断).这就是我的Python测试脚本的test外观:
#!/usr/bin/python
import time
try:
time.sleep(100)
except KeyboardInterrupt:
pass
except:
print "error"
Run Code Online (Sandbox Code Playgroud)
接下来我有一个shell脚本test.sh:
./test & pid=$!
sleep 1
kill -s 2 $pid
Run Code Online (Sandbox Code Playgroud)
当我使用bash或sh或其他东西运行脚本时,bash test.shPython进程test保持运行并且无法使用SIGINT.而当我复制test.sh命令并将其粘贴到(bash)终端时,Python进程test将关闭.
我不知道发生了什么,我想了解.那么,差异在哪里,为什么?
这不是关于如何捕获SIGINTPython!根据文档 - 这是应该工作的方式:
Python默认安装少量信号处理程序:SIGPIPE ...和SIGINT转换为KeyboardInterrupt异常
这的确是追赶KeyboardInterrupt时SIGINT被发送kill,如果该程序是由外壳直接启动,但是当程序从后台运行bash脚本开始,似乎KeyboardInterrupt永远不会提高.
我使用readline获得了类似于以下内容的代码:
#include <errno.h>
#include <error.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <readline/readline.h>
#include <readline/history.h>
void handle_signals(int signo) {
if (signo == SIGINT) {
printf("You pressed Ctrl+C\n");
}
}
int main (int argc, char **argv)
{
//printf("path is: %s\n", path_string);
char * input;
char * shell_prompt = "i-shell> ";
if (signal(SIGINT, handle_signals) == SIG_ERR) {
printf("failed to register interrupts with kernel\n");
}
//set up custom completer and associated data strucutres
setup_readline();
while (1)
{
input = …Run Code Online (Sandbox Code Playgroud) 我正在设计一个脚本来在命名的屏幕会话中启动进程.
as_user "screen -p 0 -S **$command** -X eval 'stuff \"wine LFS.exe /cfg=**$command**.cfg\"\015'"
Run Code Online (Sandbox Code Playgroud)
因此,bash myscript.sh start test将创建一个名为test的屏幕并test.cfg使用该软件运行.
现在我希望我的脚本访问特定的屏幕会话并执行CTRL+ C以停止正在运行的进程,以便我可以终止屏幕会话.
像这样的东西:
as_user "screen -p 0 -S **$command** **... kill the process with ctrl-c...**"
as_user "screen -p 0 -S **$command** -X eval 'stuff \"exit\"\015'"
Run Code Online (Sandbox Code Playgroud) 在Node.js服务器中,捕获SIGTERM与捕获SIGINT之间有什么区别吗?
我认为进程不应该能够阻止SIGINT的关闭?
process.once('SIGINT', function (code) {
console.log('SIGINT received...');
server.close();
});
// vs.
process.once('SIGTERM', function (code) {
console.log('SIGTERM received...');
server.close();
});
Run Code Online (Sandbox Code Playgroud)
我能够捕获两个信号并阻止退出吗?我的实验表明答案是肯定的,但从我读过的内容来看,SIGINT总是假设关闭一个进程.
或者我可能会把SIGINT与SIGKILL混淆?也许SIGKILL是我无法恢复的信号?
捕获这些信号当然可以让我优雅地关闭:
server.once('close', function(){
// do some other stuff
process.exit(2); // or whatever code pertains
});
Run Code Online (Sandbox Code Playgroud)
我想SIGINT与SIGKILL混淆了 -
如果我尝试这样做:
process.once('SIGKILL', function (code) {
console.log('SIGKILL received...');
exitCode = code || 2;
server.close();
});
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
internal/process.js:206
throw errnoException(err, 'uv_signal_start');
^
Error: uv_signal_start EINVAL
at exports._errnoException (util.js:1022:11)
at process.<anonymous> (internal/process.js:206:15)
at emitTwo (events.js:106:13)
at process.emit (events.js:191:7)
at _addListener (events.js:226:14)
at process.addListener (events.js:275:10) …Run Code Online (Sandbox Code Playgroud)