1

我有以下简单的脚本(test.sh):

    #!/bin/bash
    tail -f /var/log/dmesg > /tmp/output.log &
    echo "THE END"
    exit 0

从 java 程序(远程在 ssh 下)调用此 test.sh 脚本后,java 控制台(eclipse)保持锁定状态。然后,1)如果我手动终止服务器中的“tail -f /var/log/dmesg > /tmp/output.log”进程,控制台将解锁并且我在控制台中收到“THE END”消息。2) 如果我从脚本中删除“tail -f /var/log/dmesg > /tmp/output.log”并运行 java 应用程序,则不会发生锁定,我会在控制台中收到“THE END”消息。

有没有人通过test.sh在bg中运行tail -f,并继续java应用流程?

4

3 回答 3

0

在通过 Java 运行 Unix 系统命令时,Java 方面也可能存在一些缺陷。例如,如果没有在 Java 线程中读取基于 Unix 操作系统的标准 I/O 流(stdout、stderr、stdin),则 Unix 系统调用可能会意外阻塞甚至死锁(有关此主题的更多详细信息,请参阅Java exec - 使用 Java ProcessBuilder 和 Process (part 3) (2012) 执行系统进程

尝试以下基于ThreadedStreamHandler.java,的 Java 示例代码SystemCommandExecutor.javaProcessBuilderExample.java运行commands.add("ssh localhost /tmp/test.sh");(它适用于我使用最新的 Eclipse Java EE IDE for Web Developers - Mac OS X 版本):

# References: 
#
# - "Java exec - execute system processes with Java ProcessBuilder and Process (part 3)" (2012), 
# http://alvinalexander.com/java/java-exec-processbuilder-process-3
# 
# - "Running system commands in Java applications" (2012), 
# http://alvinalexander.com/java/edu/pj/pj010016
# 
# - "When Runtime.exec() won't: Navigate yourself around pitfalls related to the Runtime.exec() method" (2000),
# http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

mkdir -vp /tmp/com/devdaily/system
cd /tmp/com/devdaily/system
curl -LO http://alvinalexander.com/java/edu/java-exec/ProcessBuilderExample.java
curl -LO http://alvinalexander.com/java/edu/java-exec/SystemCommandExecutor.java
curl -LO http://alvinalexander.com/java/edu/java-exec/ThreadedStreamHandler.java
cd ../../..

# create commands.add("ssh localhost /tmp/test.sh");
printf '%s\n' 'H' ',s|ls -l.*tmp|ssh localhost /tmp/test.sh|' 'wq' |
    ed -s com/devdaily/system/ProcessBuilderExample.java

echo '
#!/bin/bash
tail -f /private/var/log/system.log > /tmp/output.log &
echo "THE END"
exit 0
' > /tmp/test.sh

chmod +x /tmp/test.sh

javac com/devdaily/system/ProcessBuilderExample.java
java com/devdaily/system/ProcessBuilderExample


java -version
# java version "1.6.0_31"
# Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-10M3646)
# Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)


# Eclipse Java EE IDE for Web Developers (Mac OS X version).
# Version: Juno Service Release 2
# Build id: 20130225-0426
#
# use the following menu sequences:
# Window --> Show View --> Console
# Run --> External Tools --> External Tools Configuration... --> Program (double-click) --> New_configuration
# Location: /usr/bin/java
# Working Directory: /tmp
# Arguments: com/devdaily/system/ProcessBuilderExample
于 2013-03-10T07:21:45.923 回答
0

看看 htis文章,它描述了使用进程时的主要错误。您需要做的是添加一个 Steam Gobbler - 输入流的消费者,以便外部程序在写入输出时不会因为缓冲区已满而卡住。

于 2013-03-10T07:29:23.713 回答
0

尝试使用 nohup:

nohup tail -f /var/log/dmesg > /tmp/output.log &

SSH 有时会在退出之前等待所有进程关闭 tty。nohup将 stdin/dev/null和 stdout/stderr 设置为一个文件,因此 SSH 可以立即退出(刷新任何可能阻止“THE END”显示的缓冲区)。

于 2013-02-01T17:49:50.247 回答