1
7
我的猜测是Java不认为脚本已经结束,直到通过STDIN/STDUD/STDRR传递给它的管道被子进程关闭。也就是说,在stdin上不再有活动的读卡器进程,在stdout/stderr上不再有活动的编写器进程。 当你在管道上阅读时,你不会收到文件结束指示,除非 不再有进程 打开管道进行输出。因此,如果一个进程分叉,新进程继承了一个打开的文件句柄,那么原始进程终止,仍然有一个打开文件的进程,读卡器仍将等待。 同样,对于正在编写的管道,在最后一个读卡器关闭管道之前,您不会收到“断管”信号。 当脚本分叉继承stdin/stdout/stderr的后台任务(如新安装的服务)时,通常会出现此问题。 通过使用exec,您将明确地破坏这些管道的继承链,以便后台进程不使用它们。 如果在Linux上,为任何新服务检查/PRO/*/FD,看看它们的STDIN/STDUD/STDER是否是Java进程传递给脚本的同一个管道。 同样的情况经常发生在运行/etc/init.d/xxx脚本时:当您从命令行运行它们时,它们会正常完成,但当您从某种监视器运行它们时,它们似乎会挂起。 编辑: 您说安装程序脚本包含以下行:
第一个术语3>&1将stdout克隆到文件描述符3(请参见 Redirections 在人巴什)。据我所知,fd 3没有特殊意义。然后,它通过打开/var/log/another-log.log来替换stdout,并通过克隆stdout来替换stderr。请参见bash手册页的重定向部分。 这意味着新的文件描述符3已打开,可以在最初作为stdout传入的管道上进行写入。期望成为系统服务守护进程的程序通常会关闭文件描述符0(stdin)、1(stdout)和2(stderr),但不会影响任何其他程序。此外,现在shell已经打开了fd-3,它将把打开的文件传递给它执行的任何命令,包括后台命令。 你知道安装程序打开fd 3有什么特别的原因吗?我的猜测是,如果您简单地从安装程序中删除“3>&1”术语,您的问题将得到解决。这将允许您从脚本中完全删除exec |
2
1
一个可能的原因是安装软件包会启动后台进程,使一个或两个管道(stdout/stderr)保持打开状态。因此,线程不会终止。这意味着这些后台进程没有正确地进行后台监控。正确的守护进程在完成初始化后将其原始stdin/stdout/stderr替换为/dev/null或日志文件。 |
3
0
如果您在Linux/Unix上运行,请尝试 不 正在使用stdout/stderr。 上次我不得不从Java运行外部脚本时,我不得不检查OS并只在Windows上附加输出线程线程。 |
4
0
我也会泵的标准输入以及。泵送所有三种标准液流是个好主意。我无法解释,但我以前遇到过类似的问题,流程挂起,问题是缺少stdin泵。 |
5
0
我没有在Linux上尝试过,但在Windows中遇到了这个问题。我认为在流程终止之前,必须关闭流程中的标准。 |
6
0
听起来你已经了解了问题的一些细节,但你还没有完全了解“大局”。
我认为,核心问题是“I/O缓冲”。 缓冲是一件好事。 我强烈建议您: 1。创建一个简单的单线程命令行Java测试程序,调用shell脚本。 <=您应该看到“预期结果”
祝你好运——而且请不要只是跳到第一个看似中肯的结论。总是检验你的理论。 PS: 重复我的咒语:“I/O缓冲很好”;—) PPS: 问:到目前为止,这个问题只被浏览了38次! A:“小蚱蜢,你必须学会耐心”;—) 问:这对我来说有点关键! A:“你也必须学会谦虚”;—) |
7
-1
你不能从Java执行脚本并等待它。必须执行该脚本的解释器。命令数组应该以“bash”开头,而不是以“myscript.bash”开头。 |