【问题标题】:Bash script subprocess locking Java app/consoleBash 脚本子进程锁定 Java 应用程序/控制台
【发布时间】:2013-01-17 02:20:00
【问题描述】:

我有以下简单的脚本(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应用流程?

【问题讨论】:

  • 在启动tail 之后可能是disown

标签: java bash


【解决方案1】:

尝试使用 nohup:

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

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

【讨论】:

    【解决方案2】:

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

    尝试以下基于ThreadedStreamHandler.javaSystemCommandExecutor.javaProcessBuilderExample.java 运行commands.add("ssh localhost /tmp/test.sh"); 的Java 示例代码(它适用于我使用适用于Web 开发人员的最新Eclipse Java EE IDE - 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
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2011-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多