调用它时,有没有办法将一个string“推”到程序的标准inputstream?
所以我们会有效果的
echo "something" | ./my_program
但不是在"something"
之后读取EOF, my_program
会从原始标准input(例如键盘)读取其进一步的input。
例如:假设我们想要启动一个bash shell,但是我们想要做的第一件事就是调用date
。 echo date | bash
echo date | bash
不会做这个工作,因为shell会在运行date
之后终止。
这可能工作:
(echo "something"; cat -) | ./my_program
它创建了一个子shell,其中第一行输出来自echo
,其余的来自标准输入cat
,它是终端(或脚本的标准输入,无论如何)。 我使用-
来强调cat
需要从标准输入中读取 – 不是简单地说我忘记了在cat
命令之后指定"$@"
或什么的。 省略-
不会产生运营差异; 这可能会造成可理解性差异。
请注意, my_program
的输入不再是终端,而是连接到终端的管道,这会影响程序的行为。 cat
过程也引入了延迟。
如果这样做不能完成这项工作,那么你可能需要使用expect
来代替。 这是一个用于脚本与其他程序交互的通用工具,它使用伪ttys(ptys)使其看起来好像终端上的用户正在与另一个程序进行通信。 正如anishsane所 指出的那样 , expect
有一个interact
命令,可以让用户在输入一些固定的序言之后输入程序。
适应这个你的第二个场景并不是一个舒适的体验:
(echo date; cat -) | bash -i
-i
告诉Bash这是一个交互式shell。 date
工作,我得到一个提示后,但我没有得到任何更多的命令执行。 中断让我更多的提示; 几乎一切似乎都被忽略了。 这可能是cat
做了太多的缓冲输出。
我终于从另一个终端窗口中杀死了这个shell。 我有更好的运气:
(echo date; cat -) | bash
但Bash没有提示。 小心; 确保你知道如何摆脱困境。
里奇也指出 ,在这个特殊情况下,你可以使用:
{ { echo date; echo 'exec 0<&3-';} | bash -i; } 3<&0
这是相当聪明的,因为结尾3<&0
在描述符3上复制了原始标准输入(文件描述符0),然后运行bash -i
,输入来自两个echo
语句。 第一个请求日期。 第二个重定向的东西,使标准输入现在来自文件描述符3(这是0<&3
部分) – 这是原来的标准输入,也就是“终端” – 也关闭文件描述符3(这是尾随-
;它是通过POSIX shell I / O重定向的Bash扩展)。
作为乔纳森·莱弗勒(Jonathan Leffler)的一个可能更简单但有限选择 的有用答案的补充:
如果
./my_program
是bash
,就像在OP的例子中一样 bash
实例中都不可见 你可以尝试下面的方法:
bash -c "$(<command that produces Bash commands>); exec bash -i"
使用date
命令的例子作为启动命令:
bash -c "$(echo 'date'); exec bash -i"
这个执行date
,然后用一个新的实例替换正在运行的bash
实例,然后保持打开 (由于既没有接收stdin输入,也没有通过-c
传递给它的命令)。
为了说明对启动 shell环境所做的任何更改都不会传播到最终保持打开状态的环境 ,请考虑以下事项:
bash -c "$(echo 'date; foo=bar; echo $foo'); exec bash -i"
这将打印日期并分配和打印变量$foo
,但是如果您再次执行echo $foo
,则不会定义它,因为最终保持打开状态的shell实例不会从执行启动命令的状态继承它的状态 。
你可以通过传递-a
到bash
来部分解决这个限制 ,这会导致所有由启动命令修改或创建的变量被自动导出 :
bash -ac "$(echo 'date; foo=bar; echo $foo'); exec bash -i"
现在,如果在保持打开的实例中再次执行echo $foo
,它将会打印bar
。
注意: