【问题标题】:Redirecting input of application (java) but still allowing stdin in BASH重定向应用程序(java)的输入,但仍然允许 BASH 中的标准输入
【发布时间】:2011-03-24 17:01:20
【问题描述】:

我有点困惑,我昨天有这个工作,但它只是停止接受重定向的标准输入,几乎是神奇的。

set -m
mkfifo inputfifo
mkfifo inputfifo_helper
((while true; do cat inputfifo; done) > inputfifo_helper)&
trap "rm -f inputfifo inputfifo_helper java.pid; kill $!" EXIT

exec 3<&0
(cat <&3 > inputfifo)&

NOW=$(date +"%b-%d-%y-%T")

if ! [ -d "logs" ]; then
    mkdir logs
fi

if [ -f "server.log" ]; then
    mv server.log logs/server-$NOW.log
fi
java <inputfifo_helper -jar $SERVER_FILE & echo $! > java.pid && fg

这运行良好,我可以将内容回显到 inputfifo 并且应用程序得到了它,我也可以直接在它的控制台中输入。它甚至可以通过屏幕工作。代码方面绝对没有任何变化,但重定向的标准输入已停止工作。我尝试将文件描述符更改为 9,甚至 127,但都没有修复它。

我是不是忘记了什么?是否有特定原因损坏且不再工作?

(我使用它而不是向屏幕本身发送输入,因为我启动屏幕分离并且它拒绝接收输入,除非它被附加到至少一次,我不知道这是一个错误还是有意的)

【问题讨论】:

  • 想解释一下为什么需要 _helper fifo 吗?
  • 我真的不记得了,但我怀疑它对我的重定向有任何影响。进程或屏幕的行为就像他们被锁定而无法直接输入一样(输入没有任何作用),尽管就像我说的那样,它以前工作得很好。

标签: java bash shell fifo io-redirection


【解决方案1】:

如果您可以让您的 java 程序保持后台运行,您可以尝试从控制终端 /dev/tty 读取并使用 while-read 循环写入 inputfifo。

# ...
java <inputfifo_helper -jar $SERVER_FILE & echo $! > java.pid

while IFS="" read -e -r -d $'\n' -p 'input> ' line; do
  printf '%s\n' "${line}"
done </dev/tty >inputfifo

【讨论】:

    【解决方案2】:

    这是一种预感 .. 但是 fd 0 上是否还有其他东西?

    在我的 linux 上我看到了这个

    $ ls -l /dev/fd/
    total 0
    lrwx------ 1 nhed nhed 64 Mar 24 19:15 0 -> /dev/pts/2
    lrwx------ 1 nhed nhed 64 Mar 24 19:15 1 -> /dev/pts/2
    lrwx------ 1 nhed nhed 64 Mar 24 19:15 2 -> /dev/pts/2
    lr-x------ 1 nhed nhed 64 Mar 24 19:15 3 -> /proc/6338/fd
    

    但是在随后的每个 ls 中,fd3 指向的 proc# 都不同 - 我不知道这是什么意思(可能与我的提示命令有关),但是 fd 3 被采用,尝试 fds #5-9

    (并在脚本顶部添加ls -l /dev/fd/ 进行诊断)

    【讨论】:

    • 我也有同样的东西,但是将其更改为使用 7 或 8 无济于事。
    【解决方案3】:

    运行给定代码的缩短版本会打印 I/O 错误消息:

    cat: stdin: Input/output error
    

    一个快速的解决方法是将此命令的 stderr 重定向到 /dev/null。

    在 Mac OS X / FreeBSD 上,您还可以尝试使用“cat -u”来禁用输出缓冲(从而避免 cat 输出缓冲问题)。

    rm -v inputfifo inputfifo_helper
    mkfifo inputfifo inputfifo_helper
    
    (
    ((while true; do cat inputfifo; done) > inputfifo_helper) &
    # use of "exec cat" terminates the cat process automatically after command completion
    #((while true; do exec cat inputfifo; done) > inputfifo_helper) &
    pid1=$!
    exec 3<&0  # save stdin to fd 3
    # following command prints: "cat: stdin: Input/output error"
    #(exec cat <&3 >inputfifo) &
    (exec cat <&3 >inputfifo 2>/dev/null) &
    pid2=$!
    # instead of: java <inputfifo_helper ...
    (exec cat <inputfifo_helper) &
    pid3=$!
    echo $pid1,$pid2,$pid3   
    lsof -p $pid1,$pid2,$pid3
    echo hello world > inputfifo
    )
    
    
    # show pids of cat commands
    ps -U $(id -u) -axco pid,command | grep cat | nl    # using ps on Mac OS X
    

    【讨论】:

    • 我使用的是 ubuntu 10.04,即使快速修复它也不能解决我的问题。我什至尝试将 cat 的 stderr 重定向到文件,以查看它们是否真的在我这边抛出了任何错误,但也没有。
    【解决方案4】:

    尝试使用单个 fifo 并将内容回显到 r/w 文件描述符。 使用 ASCII NUL 字符来终止您的(行)输入,以便 读取命令继续读取直到一个 NULL 字节(或 EOF)。

    rm -v inputfifo 
    mkfifo inputfifo
    (
    exec 0>&-
    exec 3<>inputfifo   # open fd 3 for reading and writing
    echo "hello world 1" >&3
    echo "hello world 2" >&3
    printf '%s\n\000' "hello world 3" >&3
    # replaces: java <inputfifo_helper ...
    cat < <(IFS="" read -r -d '' <&3 lines && printf '%s' "$lines")
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多