Java执行运行守护程序的Bash脚本



我正在处理我的Java Server应用程序请求服务器重新启动时运行的bash脚本。该脚本确实需要在Java应用程序的进程树之外操作。

我使用ProcessBuilder以以下方式调用Java中的重新启动脚本:

// Vars declared at the top of the file
private static final String LOC = "/some/directory/";
private static final String RESTART_SCRIPT = LOC + "restart.sh";
...
// In the function that is invoked to handle reboot behavior
final ProcessBuilder pb = new ProcessBuilder(RESTART_SCRIPT);
Process p = pb.start();

此脚本执行以下操作,以删除另一个处理所有重启逻辑的脚本。看起来如下:

#!/bin/bash
(bash /some/directory/shutdownHandler.sh "true" &)
exit 0

在Java应用程序中,我调用包含ProcessBuilder Logic的函数时,我看不到shutdownhandler.sh脚本中逻辑的效果。即使是简单的文本回声,也没有发生在文件中。我已经检查了我有正确的权限。

直接从命令行执行restart.sh时,它可以按预期工作。

请建议我为什么看到这种行为差异。Java是否有某种方式杀死了守护程序?

我建议您尝试以下简化:

final String[] RESTART_COMMAND = { "nohup", "/some/directory/shutdownHandler.sh", "true" };
final ProcessBuilder pb = new ProcessBuilder(RESTART_COMMAND);
Process p = pb.start();
//DON'T waitFor()

使用nohup并避免使用waitFor应该具有相同的效果您的RESTART_SCRIPT工具:这两个过程'生命周期都是独立的(jvm不等待shutdownHandler.sh,Java进程的终止不会导致shutdownHandler.sh的中断)。

我找到了一种使脚本shutdownHandler.sh在我描述的用法方案中正确触发的方法。问题在于我如何使shutdownHandler.sh进行危险。我已将restart.sh更改为:

#!/bin/bash
LOGFILE="/some/log/directory/scriptLog.log"
(setsid /some/directory/shutdownHandler.sh "true" >$LOGFILE 2>&1 < /dev/null &)
exit 0

上面有一些关键的事情:

  • 处理脚本的stdoutstderrstdinstdoutstderr被定向到LOGFILE中,并将dev/null连接到stdin
  • 与控制tty断开连接
  • 启动的修改脚本。shutdownHandler.sh不会与JVM
  • 处于同一过程树中

最新更新