我正在将线条划分为PHP脚本(参见下面的设计示例)。唉,管道无意中流入脚本中的shell命令,因此nano不会运行,因为它在STDIN上窒息。
我希望shell命令与通过管道传输到主脚本的STDIN完全无关。所以PHP脚本应该以某种方式“吃掉”STDIN,因此它不会到达子shell。我该如何解决这个问题?
请注意,exec()
,system()
和passthru()
都会给出相同的结果。
$ echo -e "World\nEverybody" | php script.php
Hello World
Received SIGHUP or SIGTERM
Hello Everybody
Received SIGHUP or SIGTERM
的script.php:
<?php
foreach(file("php://stdin") as $name) {
echo "Hello $name";
passthru("nano");
}
?>
环境:
答案 0 :(得分:1)
管道并没有真正流入子壳。事实上,没有任何东西流入。为了将nano
的STDIN连接到终端,你将控制终端(总是/dev/tty
)传输到nano,如下所示:
passthru("nano </dev/tty");
以下是您的后续问题的答案。 (非常好的问题IMO。我之前的回答实际上有些错误.STDIN会流入子进程。)
如果脚本只包含passthru(&#34; nano&#34;)并且你没有将任何内容传递给PHP,那么nano不需要&lt; / dev / tty。这是为什么?
实际上,子进程确实从父进程继承了STDIN,但由于缓冲,有时并不完全清楚。由于它们继承了相同的STDIN,当达到EOF时,它们会在达到EOF时执行任何操作(查看nano
在这种情况下的作用,见下文)。
让我们把PHP从等式中拿出来,看看当我们打开或关闭缓冲时我们得到了什么。这里有一些C代码,它们将从STDIN,system()读取,并再次从STDIN读取:
#include <stdio.h>
#include <stdlib.h>
int main() {
// setvbuf(stdin, NULL, _IONBF, 0 );
char buffer[32];
gets(buffer);
printf("Hello %s\n", buffer);
system("bash -c 'read FOO; echo This is bash, got $FOO'");
gets(buffer);
printf("Hello2 %s\n", buffer);
}
编译(忽略有关gets
的警告)并运行:
$ cc -o script script.c
$ echo -e "Foo\nBar\nCar" | ./script
Hello Foo
This is bash, got
Hello2 Bar
bash
没有得到任何结果。 gets
之后的system
神奇地得到了这个输入。现在取消注释第一行:
- // setvbuf(stdin, NULL, _IONBF, 0 );
+ setvbuf(stdin, NULL, _IONBF, 0 );
我们得到:
$ cc -o script script.c
$ echo -e "Foo\nBar\nCar" | ./script
Hello Foo
This is bash, got Bar
Hello2 Car
这一次bash
得到了第二个输入。 &#34;太长了;没有读过&#34;:我们确实有相同的STDIN。
首先,你会发现nano
的行为是相同的,即使你把PHP排除在等式之外:
$ echo foo | nano
Received SIGHUP or SIGTERM
理论上,{p> nano
可以很好地检测出我们是否有终端,如果我们没有,则尝试打开/dev/tty
(它只是一个常规终端) open
致电)。事实上,如果您执行nano
,nano
会执行此操作:
echo foo | nano -
scoop_stdin
中的src/nano.c
函数在版本2.9.4中处理此问题:http://git.savannah.gnu.org/cgit/nano.git/tree/src/nano.c?h=v2.9.4#n1122
版本2.7.4中的finish_stdin_pager
函数:http://git.savannah.gnu.org/cgit/nano.git/tree/src/nano.c?h=v2.7.4#n1116)
那么当nano
获得EOF时会发生什么?键输入中的EOF如下处理:
版本2.7.4:get_key_buffer()
直接调用handle_hupterm(0)
。
http://git.savannah.gnu.org/cgit/nano.git/tree/src/winio.c?h=v2.7.4#n207
版本2.9.4:die(_("Too many errors from stdin"));
http://git.savannah.gnu.org/cgit/nano.git/tree/src/winio.c?h=v2.9.4#n207
(我之间链接两者的原因是因为消息在某些时候发生了变化。)
我希望这会让事情变得更清楚。