重定向应用程序(java)的输入,但仍然允许 BASH 中的 stdin

发布于 2024-10-26 23:23:26 字数 780 浏览 5 评论 0原文

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

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,但都没有修复它。

我是不是忘记了什么?它坏掉并且不再工作有什么具体原因吗?

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

I'm a little confused, I had this working yesterday, but it just stopped accepting the redirected stdin, almost magically.

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

This was running fine, I could echo things to inputfifo and the app got it, and I could type directly into it's console as well. It even worked through screen. Absolutely nothing code-wise has changed, but the redirected stdin has stopped working. I tried changing the file descriptor to 9, or even 127, but neither fixed it.

Am I forgetting something? Is there a specific reason it broke and no longer works?

(I'm using this instead of sending input to the screen itself because I start the screen detached and it refuses to receive input unless it's been attached to atleast once, I don't know if this is a bug or intended)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

装迷糊 2024-11-02 23:23:26

如果您可以让您的 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

If you can keep your java program backgrounded, you may try to read from the controlling terminal /dev/tty and write to inputfifo using a while-read loop.

# ...
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
我乃一代侩神 2024-11-02 23:23:26

这是一种预感..但是 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/ 进行诊断)

Its a hunch .. but could there be something else attached to fd 0?

On my linux I see this

$ 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

but on every subsequent ls the proc# pointed to by fd3 is different - I have no idea what this is about(maybe its tied to my prompt command), but fd 3 is taken, try fds #5-9

(and add ls -l /dev/fd/ at the top of the script for diagnostics)

梦途 2024-11-02 23:23:26

运行给定代码的缩短版本会打印 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

Running a shortened version of your given code prints an I/O error message:

cat: stdin: Input/output error

A quick fix is to redirect stderr to /dev/null for this command.

On Mac OS X / FreeBSD you could also try using "cat -u" to disable output buffering (thus avoiding cat output buffering issues).

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
枫林﹌晚霞¤ 2024-11-02 23:23:26

尝试使用单个 fifo 并将内容回显到 ar/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")
)

Try using a single fifo and echo things to a r/w file descriptor.
Use an ASCII NUL character to terminate your (lines of) input so that
the read command continues reading until a NULL byte (or 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")
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文