我想运行程序“A”,将其输出转到另一个程序“B”的输入,以及stdin转到“B”的输入。如果程序“A”关闭,我希望“B”继续运行。
我可以轻松地将A输出重定向到B输入:
./a | ./b
如果我愿意,我可以将stderr合并到输出中:
./a 2>& 1 | ./b
但我无法弄清楚如何将stdin组合到输出中。我的猜测是:
./a 0>& 1 | ./b
但它不起作用。
这是一项不需要我们重写任何测试程序的测试:
$ echo ls 0>&1 | /bin/sh -i
$ a b info.txt
$
/bin/sh: Cannot set tty process group (No such process)
如果可能的话,我想在命令行上只使用bash重定向来做这个(我不想写一个C程序来分叉子进程,每次我想做一些stdin的重定向时做任何复杂的事情到管道)。
答案 0 :(得分:3)
如果不编写辅助程序,就无法完成。
通常,stdin可能是只读文件描述符(哎呀,它可能指的是只读文件)。所以你不能“插入”任何东西。
您需要编写一个“帮助程序”程序来监视两个文件描述符(例如,0和3),以便从两者中读取并“合并”它们。一个简单的select
或poll
循环就足够了,您可以用大多数脚本语言编写它,但不是shell,我不这么认为。
然后你可以使用shell重定向将程序的输出提供给“helper”的描述符3。
既然你想要的基本上与“tee”相反,我可以称之为“eet”......
[编辑]
如果只有你可以在后台启动“猫”......
但是这会失败,因为具有控制终端的后台进程无法从stdin读取。所以,如果你可以从控制终端分离“cat”并在后台运行它......
在Linux上,“setsid cat”应该粗略地做到这一点。但是(a)我不能让它工作得很好而且(b)我今天真的没有时间和(c)它是非标准的。
我会编写帮助程序。
[编辑2]
好的,这似乎有效:
{ seq 5 ; sleep 2 ; seq 5 ; } | /bin/bash -c 'set -m ; setsid cat ; echo HELLO'
set -m
事件强制bash
启用作业控制,显然需要防止shell从/ dev / null重定向stdin。
此处,echo HELLO
代表您的“程序A”。 seq
命令(中间有sleep
)只是为了提供一些输入。是的,你可以将整个事情告诉处理B.
关于丑陋和不便携的解决方案,你可以要求......
答案 1 :(得分:1)
管道有两端。一个用于写作,写入的另一个用于阅读。
这是一个管道,而不是T或Y交界处。
我认为你的情景不可能。 “stdin要输入”任何东西都没有意义。
答案 2 :(得分:1)
要使给定的测试用例正常工作,您必须从while ... read
构造内的控制终端设备/dev/tty
sh -c '...'
开始。
请注意使用eval
(这里可以避免吗?)并且input>
上的多行命令会失败。
echo 'ls; export var=myval' | (
stdin="$(</dev/stdin)"
/bin/sh -i -c '
eval "$1";
while IFS="" read -e -r -p "input> " line; do
history -s "${line}"
eval "${line}";
done </dev/tty
' argv0 "${stdin}"
)
input> echo $var
对于类似的问题以及命名管道的使用,请参见此处:
答案 3 :(得分:0)
这不能完全按照图示完成,但为了执行您的示例,您可以利用cat
将文件连接在一起的能力:
cat <(echo ls) - | /bin/sh
(你可以做-i,但是你必须让另一个进程终止/ bin / sh,因为你尝试Ctrl-C和Ctrl-D out会失败。)
这假定您要传入管道输入,然后从stdin接受。您也可以使它在stdin完成后或双方都做某事 - 但它不会逐个字符或逐行合并输入。
答案 4 :(得分:0)
如果我理解你的要求,你需要这个设置(ASCII艺术就在前面):
o----+----->| A |----+---->| B |---->o
| ^
| |
+------------------+
附加约束条件是,如果流程A关闭了商店,则流程B应该能够继续输入流转到B。
这是一个非标准设置,正如您所知,并且只能通过使用辅助程序来驱动A和B的输入来实现。您最终会遇到一些有趣的同步问题,但它们都会非常好地工作只要你的信息足够短。
实现这一目标所需的管道是值得注意的 - 你需要两个管道,一个用于输入A,另一个用于输入到B,A的输出也将连接到B的输入。
o---->| C |---------->| A |----+---->| B |---->o
| ^
| |
+--------------------------+
请注意,C将两次写入数据,一次写入A,一次写入B.另请注意,从A到B的管道与从C到A的管道是相同的管道。
答案 5 :(得分:0)
这似乎可以做你想要的:
$ ( ./a <&-; cat ) | ./b
(我不清楚你是否想获得输入......这个解决方案将所有输入发送到b) 当然,在这种情况下,b的输入是严格排序的:a的所有输出 首先发送到b,然后终止,然后输入到b。如果你想要的东西 交错,尝试:
$ ( ./a <&- & cat ) | ./b