从 PHP 运行没有输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10968661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Running at from PHP gives no output
提问by Bojangles
I've been wrestling with exec(), trying to capture the output from it when I add a task using the atUnix system command. My problem is that it is giving no output when run from my script, however running it from the terminal andPHP in interactive mode prints out a couple of lines.
我一直在exec()努力,试图在我使用atUnix 系统命令添加任务时捕获它的输出。我的问题是它在从我的脚本运行时没有给出任何输出,但是从终端和PHP 以交互模式运行它会打印出几行。
The command I want to execute is this:
我要执行的命令是这样的:
echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
var_dump()gives string(0) "", and print_r()spits out Array (). I've tried using shell_exec(), which outputs NULL, however the following outputs hiwhen run in a web page context:
var_dump()给予string(0) "",并print_r()吐出Array ()。我试过使用shell_exec(), 输出NULL,但是在hi网页上下文中运行时会出现以下输出:
echo exec("echo 'hi'");
This also outputs stuff:
这也输出东西:
echo exec("atq");
However, as soon as I use at, nothing is output. How can I get the output of:
但是,一旦我使用at,就不会输出任何内容。我怎样才能得到输出:
exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
Because at present it outputs nothing when run as "normal" by PHP through Apache, however running the command in the terminal as well as in PHP's interactive console gives me the expected result of something like:
因为目前它在 PHP 通过 Apache 以“正常”方式运行时不输出任何内容,但是在终端以及 PHP 的交互式控制台中运行该命令会给我以下预期结果:
php > echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);
warning: commands will be executed using /bin/sh
job 1219 at Sun Jun 10 12:43:00 2012
safe_modeis off, and I cannot work out why I don't get any output from atwith a piped-in echo statement, when executing atqor any other commend with exec()gives me output. I've searched and read this question, all to no avail.
safe_mode关闭,我无法弄清楚为什么我没有从at管道输入的 echo 语句中获得任何输出,在执行atq或任何其他推荐时exec()给我输出。我已经搜索并阅读了这个问题,但都无济于事。
How can I get exec()to return the output from atto either a string, or an array if using a second argument with exec()?
如果使用第二个参数 with ,如何exec()将输出返回at到字符串或数组exec()?
回答by Bojangles
Working, one line solution
工作,一条龙解决方案
I didn't realise it could be this simple. All that is required is to reroute stderr to stdout by putting 2>&1at the end of the command to execute. Now any output from atis printed to stdout, therefore captured by exec():
我没有意识到它可以这么简单。所需要做的就是通过2>&1在要执行的命令的末尾放置来将 stderr 重新路由到 stdout 。现在任何输出都at被打印到标准输出,因此被捕获exec():
echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);
My old solution:
我的旧解决方案:
I was trying to keep to a one/two line solution, however the only thing that worked in the end was using proc_open()because atlogs to stderr, which exec()doesn't read!I'd like to thank @Tourniquet for pointing this out, however he has deleted his answer. To quote:
我试图保持单行/两行解决方案,但是最后唯一有效的方法是使用,proc_open()因为at记录到标准错误,它exec()不读取!我要感谢@Tourniquet 指出这一点,但他已删除了他的回答。报价:
As far as i can see, at outputs to stderr, which isn't captured by exec. I'm not really confident in it, but consider using http://php.net/manual/en/function.proc-open.php, which allows you to direct stderr to its own pipe.
据我所知,在输出到 stderr 时,exec 没有捕获它。我对它不是很有信心,但可以考虑使用 http://php.net/manual/en/function.proc-open.php,它允许您将 stderr 定向到它自己的管道。
This is actually the correct way of doing things. My solution (because I only want stderr) was to do this:
这实际上是正确的做事方式。我的解决方案(因为我只想要 stderr)是这样做的:
// Open process to run `at` command
$process = proc_open("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", array(2 => array("pipe", "w")), $pipes);
// Get stuff from stderr, because `at` prints out there for some odd reason
if(is_resource($process)) {
$output = stream_get_contents($pipes[2], 100);
fclose($pipes[2]);
$return_value = proc_close($process);
}
$outputnow contains whatever atprinted to stderr (which should really go to stdout because it's not an error), and $return_valuecontains 0on success.
$output现在包含at打印到 stderr 的任何内容(它应该真正转到 stdout,因为它不是错误),并且$return_value包含0成功。
回答by Francesco Casula
Here a more complex solution with proc_open. I'm writing this answer because, in my case, the '2>&1'workaround doesn't work.
这是一个更复杂的解决方案proc_open。我写这个答案是因为,就我而言,“2>&1”解决方法不起作用。
function runCommand($bin, $command = '', $force = true)
{
$stream = null;
$bin .= $force ? ' 2>&1' : '';
$descriptorSpec = array
(
0 => array('pipe', 'r'),
1 => array('pipe', 'w')
);
$process = proc_open($bin, $descriptorSpec, $pipes);
if (is_resource($process))
{
fwrite($pipes[0], $command);
fclose($pipes[0]);
$stream = stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($process);
}
return $stream;
}
Usage examples:
用法示例:
// getting the mime type of a supplied file
echo runCommand('file -bi ' . escapeshellarg($file));
Another example using the commandparameter:
另一个使用命令参数的例子:
// executing php code on the fly
echo runCommand('/usr/bin/php', '<?php echo "hello world!"; ?>');
Another example using the forceparameter (this can be useful for commands that will change the output during the execution process):
另一个使用force参数的示例(这对于将在执行过程中更改输出的命令很有用):
// converting an mp3 to a wav file
echo runCommand('lame --decode ' . escapeshellarg($source) . ' ' . escapeshellarg($dest), '', true);
I hope this helps :-)
我希望这会有所帮助:-)
回答by hpekristiansen
Try to create a minimum (non-)working example. Break everything down, and test only one thing at a time.
尝试创建一个最小(非)工作示例。打破一切,一次只测试一件事。
Here is one error in your bash:
这是您的 bash 中的一个错误:
hpek@melda:~/temp$ echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes
at: pluralization is wrong
job 22 at Sun Jun 10 14:48:00 2012
hpek@melda:~/temp$
Write minuteinstead og minutes.
写minute代替OG minutes。
My output from atis send to me by mail!!
我的输出at是通过邮件发送给我的!!

