我找到了这个解决方案,但对我来说不是 100% 好的。 output of child-prc
我有以下 php 文件:
<?php
printf("$argv[1]: ". date("H:m:s")."\n");
if ($argv[1]=='1') {exec('/usr/bin/php -f t.php 2 2&>1');}
?>
现在我在提示符下进行调用,并希望将所有输出(也来自 exec)重定向到日志文件。php -f t.php 1 > t.log
结果应该是: 1: 15:10:52
2: 15:10:53
线 2: 15:10:53
来自 exec 子进程。但我只得到第一行。
请通知日志文件的名称
t.log
不应硬连线定义。是什么让我错了?
谢谢
最佳答案
PHP's exec()
与 exec()
完全不同任何其他语言。
仅调用 exec("some string")
时, 它得到 some string
由子进程中的 shell 解释为 shell 代码,并返回其输出的最后一行,去掉了所有尾随 ASCII 空白字符。
在这里,您没有对该输出做任何事情。
现在至于:
/usr/bin/php -f t.php 2 2&>1
shell 代码,注意行为在 sh
之间变化实现。符合 POSIX
sh
实现,这意味着与:/usr/bin/php -f t.php 2 2 &
>1
即运行 php
在后台执行命令,然后打开名为 1
的文件用于写入,但没有任何输出要发送到那里的命令。不是全部
sh
实现是合规的,有些 shell 实现了非标准 &>
重定向运算符。在
sh
的 GNU 实现中( bash
),这被解释为:/bin/bin/php -f t.php 2 2 &> "1"
哪个正在运行 php
带有 stdout 和 stderr 的命令(带有 2 个“2”参数)重定向到名为 1
的文件.所以它不会在 stdout 上产生输出(由 php 捕获)但发送 /usr/bin/php
的输出到该文件。在
zsh
, 2&> "1"
将 fd 2 和 fd 2 都重定向到名为 1 的文件,就像你写了 2> "1" 2>&2
.使用 fd 2 重定向两次,zsh 通常实现 tee
类似行为,其中数据被发送到两个位置(此处相同),但调用为 sh
(不是很多系统都有 sh
用 zsh
实现),zsh
禁用 tee
类似的功能,所以 2&>1
最终与 2> "1"
相同,因此将 stderr 重定向到名为 1
的文件.无论如何,因为 php
command 不会在 stderr 上输出任何内容,这没有区别。mksh
(MirBSD sh
) 的行为类似于上面的 zsh-as-sh。在这里,你可以做
echo exec('/usr/bin/php -f t.php') . "\n";
打印 php
输出的最后一行的内容命令后跟换行符。或者(也许你想要什么?):echo exec('/usr/bin/php -f t.php 2>&1') . "\n";
对于该 php
的输出+错误的最后一行命令。但是在这里,听起来您只想保留
php
的输出命令原封不动;不要捕获它,而是让它与 echo
去同一个目的地做。PHP 有一些
system()
和 passthru()
函数,但那些捕获shell命令的输出以在之后显示它。但是,您可以使用
pcntl_exec()
更像 exec()
的函数其他语言,除了它不允许你设置 argv[0]
.pcntl_exec("/usr/bin/php", ["-f", "t.php", "2"]);
喜欢 exec()
其他语言,它在同一个进程中运行它,所以这是 php 脚本要做的最后一件事。它不调用shell,只是直接运行命令。不过,这可能不是您想要在 Web 应用程序中使用的。在 web 应用程序中,php 需要在发送它之前知道它要发送什么输出,如果只是填写
Content-Length
HTTP header 的类型。在那里,你会使用 passthru()
或 system()
或 shell_exec()
...也可以看看:
shell_exec()
passthru()
system()
proc_open()
popen()
关于bash - 如何将php(及其stderr)中的exec调用的输出重定向到调用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69832797/