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

时间:2017-09-06 20:30:20

标签: java linux bash

我正在处理一个在我的Java服务器应用程序请求重新启动服务器时运行的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();

此脚本执行以下操作以对另一个处理所有重新启动逻辑的脚本进行deamonize。它看起来如下:

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

在Java Application中,当我调用包含ProcessBuilder逻辑的函数时,我没有在shutdownHandler.sh脚本中看到逻辑的影响。即使是简单的文本到文件的回声也不会发生。我已经检查过我有正确的权限。

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

请告知我为什么看到这种行为上的差异。 Java有没有杀死守护程序的脚本?

2 个答案:

答案 0 :(得分:0)

我建议你尝试以下简化:

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的中断。

答案 1 :(得分:0)

我找到了一种让脚本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的连接
  • Reparents脚本到init。 shutdownHandler.sh将不在与JVM相同的进程树中