【问题标题】:background process in java listening to stdinjava中的后台进程监听stdin
【发布时间】:2012-07-25 06:11:38
【问题描述】:

我必须制作一个 java 程序,当用户输入 0 时它应该退出。用java代码写没问题。

int cmd = read();
System.out.println("got command : " + cmd);
if (cmd == 48) { // ASCII code for 0
System.exit(0);

我想在 linux 中使用 start-stop 脚本来运行这个过程。我也可以使用&nohup 来做到这一点

case "$1" in    
  'start')
    if [ -f myfifo ]; then
      rm myfifo
    fi
    mkfifo myfifo
    cat > myfifo &
    echo $! > myfifo-cat-pid
    java -jar myjar.jar >/dev/null 2>&1 0<myfifo &
    echo "Started process: "$!
    ;;

  'stop')
    echo 0 > myfifo
    echo "Stopped process: "
    rm myfifo
    ;;
esac

我的问题是,一旦我运行此过程,它就会读取输入 -1。虽然我想从 stdinput 读取当somthing明确回显到它时,即调用停止。只是我需要一个程序被shell脚本明确关闭。我已经很努力了。帮帮我。

编辑:

我只想在用户按下 q 或任何此类事件时关闭程序,并且不希望代码中出现无限循环。如果可能的话,任何其他方法(如监听其他事件)也会有所帮助。我的代码不应该轮询事件。我试过Jnotify,它监视一个目录并在该目录中创建或删除文件时引发一个事件。但不幸的是,他们不支持 SunOS。 :(

【问题讨论】:

  • 使用 System.in.read();我也尝试过使用 BufferReader
  • hum... 你确定 myfifo 存在并且其中包含任何内容吗? System.in.read() 旨在正常工作...mkfifo 是什么?
  • mkfifo 创建一个fifo(队列)。 System.in .read() 正在读取,即使我没有为进程分配任何标准输入。
  • 我的理解是,由于fifo中还没有任何东西,所以它到达了EOF。尝试创建 fifo 并在启动 java 程序之前向其中推送一些值,以确保它在有要读取的内容时正常工作。
  • 你检查过myfifo 是否存在吗?你能读出来吗?

标签: java shell stdin background-process


【解决方案1】:

好吧,事实上fifo 文件的行为似乎与您想象的不完全一样。

read() 命令没有阻塞管道。你应该循环直到你得到数据:

    try {
        bis = new BufferedInputStream(System.in);
        while (true) {
            byte[] buffer = new byte[4096];
            if (bis.available() > 0) {
                bis.read(buffer, 0, bis.available());
                // do some clever thing
            } else {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    } catch (IOException e) {
        // it failed...
    }

这将尝试读取,如果没有,则等待 50 毫秒。

M.

【讨论】:

  • 我忘了提及我也使用 while 循环完成了此操作,但随后它将不断从标准输入读取我不想要的内容,因为它是一个无限循环,直到用户发送正确的命令。 :(
  • 您需要什么?在您的程序中做某事并同时收听标准输入?当用户按下“q”时它会停止你的程序?
  • 是的,这是我需要的。但是程序应该在后台运行
  • 那么你必须将你的代码分成两个线程。如果程序必须退出,它将侦听 fifo 并将变量设置为 true。另一个将完成这项工作并检查每个循环是否可以继续或现在必须停止。
  • 是的,事实上两者都是。由于您希望它们作为后台进程运行,它们必须处于无限模式。 STDIN 线程循环,直到有东西要读取,然后休眠,读取,休眠,......然后另一个线程完成工作,检查它是否必须停止,完成工作,检查......
【解决方案2】:

由于管道中还没有数据,read() 会看到流的结尾,因此它会返回 -1。在从流中读取之前调用available(),以确保其中有信息。

【讨论】:

    【解决方案3】:

    如果您在 shell 脚本的顶部使用 set -m(从而启用强制作业控制),您应该会看到一致的行为。

    【讨论】:

      【解决方案4】:

      当您在脚本中执行命令时,该命令的标准输入会从 /dev/null 隐式重定向。

      # test by executing a script with ...
      - cat > myfifo & lsof -p $!
      + cat 0<&0 > myfifo & lsof -p $!
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-17
        • 2016-01-28
        • 2017-11-16
        • 2012-07-30
        • 1970-01-01
        相关资源
        最近更新 更多