【发布时间】:2014-02-21 13:30:57
【问题描述】:
我有一个在 Mac OS X 上使用 Bash 脚本运行的 Java 程序。我有两个文件 - 一个允许我将命令通过管道传输到程序中的 FIFO,以及一个输出日志文件。
Bash 脚本由以下代码组成:
#!/bin/bash
java -jar file.jar <./run/command-fifo >>./run/server.log 2>&1 &
echo $! >| ./run/server.pid
老实说,我不记得为什么我在第三行中使用了>|(我只知道它有效)。在 java 行中,第一个 < 将 fifo 文件重定向到标准输入。 >> 应该将标准输出重定向到文件,2>&1 也应该将标准错误重定向到它。然后它在后台运行。
问题是没有任何东西写入 server.log 文件。读取 command-fifo 文件,但不写入日志。该程序正在写入标准输出(如果我自己运行它,它工作正常)。
我也按照this question 中的建议尝试了script,但也没有用:
script -q /dev/null java -Xmx4G -Xms4G -jar current.jar --nogui <./run/command-fifo >>./run/server.log 2>&1 &
任何人有想法让它正确写入日志?
跟进:我应该多解释一下软件是如何工作的,这样解释才有意义。这里有三个部分在起作用:
-
launchd用于通过调用启动器脚本在启动时启动程序的 plist - 处理终止信号并等待 java 进程的 pid 的启动器脚本
- 由启动器脚本调用的启动脚本,用于启动程序并保存其 pid
上面给出的脚本是启动脚本。这将启动 java 进程,将其 pid 回显到文件,然后返回。启动器脚本(此处未给出)然后等待 pid 在终止之前退出。如果它终止,launchd 会自动重新启动启动器脚本。
Launchd 有一个特性,可以为它启动的文件设置标准输出路径。本质上,它将启动器脚本的标准输出重定向到给定的文件。
我这样做了,你瞧,它有效。通过将启动脚本行更改为以下内容:
java -jar file.jar <>./run/command-fifo &
它允许 launchd 捕获标准输出并将其写入文件。这是一个有点不同的解决方案,但它确实有效。这很奇怪,因为启动器脚本在技术上没有任何输出,因为 java 进程在后台,但是不管它如何工作,它确实以某种方式工作。
当然,我更喜欢将文件的标准输出显式重定向到一个文件中(在其他脚本中,可能存在多个文件,我需要将它们分开)。我仍然会尝试并尝试找到解决方案。
【问题讨论】:
-
我不是 java 专家,但我敢打赌你的 java 程序只是在缓冲输出(可能会在输出大小达到 8K 或 64K 字节时写入)。同时,
>|重定向运算符的意思是“写入文件,即使它存在 并且 我也已经完成了set -o noclobber,因此您通常会拒绝重定向并显示文件存在的错误”。更令人难忘的是,管道的意思是:“我是认真的!”
标签: bash redirect background-process