java - 如何防止SIGINT信号杀死Java中的子进程

标签 java exec

我使用Java exec运行bash脚本,但是当我输入CTRL+C时,Java进程将退出,子进程也会退出,如何在JVM关闭后保持子进程运行?

String command = "ffmpeg -re -strict -2 -i video.mp4 -c:v copy -an -f rtp rtp://127.0.0.1:1234";
Utils.writeToFile("sub.sh", command);

new ProcessBuilder("parent.sh", "sub.sh").inheritIO()
        .start().waitFor();

parent.sh:

#!/bin/bash
trap '' SIGINT SIGTERM SIGQUIT SIGHUP SIGTSTP
nohup "$@" &

我已阅读类似问题的答案 herehere ,例如,使用 nohup 在该脚本运行命令中启动父 bash 脚本,或使用 trap 命令来阻止信号, 根据我的研究,它适用于例如“tail -f somefile”,但不适用于我的用例 “ffmpeg -params”,请帮忙,谢谢。

最佳答案

TL;DR

parent.sh 中使用 setsid 而不是 nohup:

#!/bin/bash
setsid $@ &
<小时/>

第一个问题是,当您的 Java 程序收到 SIGTERM 信号(在 CTRL + C 之后)时,JVM 会向子进程,不能被捕获、阻止或忽略。因此,一旦您的 parent.sh 进程收到 SIGKILL,它就会被传递给其子进程 sub.sh,从而停止该进程。

第二个问题是使用 nohup "$@"& 你让你的 sub.sh 子程序在后台运行,但它并没有完全脱离当前终端。 nohup 所做的基本上是忽略 SIGHUP 信号。它正常执行进程(在后台)并且实际上不提供守护进程。

您可以使用 setsid 代替 nohup ,它通过创建一个新 session 来分 ionic 进程 sub.sh,然后该 session 将没有控制终端,因此不会收到 SIGKILL 信号。

另一种方法可以使用 disown,例如 source $@ & disown,但在这种情况下,它不会t 阻止运行 parent.sh 的当前终端。问题是,您将无法知道子进程何时完成。因此,为了监视子进程 ID,您需要做更多的工作。

进一步说明:

关于java - 如何防止SIGINT信号杀死Java中的子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56313898/

相关文章:

java - ClassCastException 与 "inconvertible types"编译错误

java - 如何更新具有 OneToMany 关联的对象的子行

c - 解释器文件的主要用途是什么?

php - 为什么 exec 和 proc_open 在 IIS 上以不同的用户运行?

java - 通过命令终端在 Eclipse 中使用 JUnit 运行 java 文件

java - 如何从 bootRun 传递 JVM 选项

java - 学习 Java Portlet 规范 (JSR-168) 的最佳资源是什么?

c - C处理管道时悬挂外壳

php - 使用PHP正确执行ssh/命令行

bash - find -exec 找不到本地函数 "find: Log: No such file or directory"