【问题标题】:Running at from PHP gives no output从 PHP 运行 at 没有输出
【发布时间】:2012-06-10 12:22:49
【问题描述】:

我一直在与exec() 搏斗,试图在使用at Unix 系统命令添加任务时捕获它的输出。我的问题是从我的脚本运行时它没有输出,但是从终端 PHP 以交互模式运行它会打印出几行。

我要执行的命令是这样的:

echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);

var_dump() 给出string(0) "",而print_r() 吐出Array ()。我试过使用shell_exec(),它会输出NULL,但是在网页上下文中运行时会输出hi

echo exec("echo 'hi'");

这也输出东西:

echo exec("atq");

但是,一旦我使用at,就没有任何输出。如何获得以下输出:

exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes", $result);

因为目前它在 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_mode 已关闭,我无法弄清楚为什么在执行atq 或使用exec() 执行任何其他命令时,我没有从at 使用管道回显语句获得任何输出给我输出.我已经搜索并阅读了this question,但都无济于事。

如果使用带有exec() 的第二个参数,如何让exec()at 的输出返回到字符串或数组?

【问题讨论】:

  • 闻起来像 seLinux 或其他权限问题。即使没有看到任何输出,任务是否也会被安排?
  • 是的,即使没有输出,它也会被安排。运行 sudo atq 会列出新任务。

标签: php exec


【解决方案1】:

工作,一条线解决方案

我没想到会这么简单。所需要做的就是通过将2>&1 放在要执行的命令末尾来将stderr 重新路由到stdout。现在at 的任何输出都被打印到标准输出,因此被exec() 捕获:

echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);

我的旧解决方案:

我试图保持一个/两行解决方案,但最终唯一有效的是使用proc_open() 因为at 记录到stderr,exec() 不读取! 我要感谢@Tourniquet 指出这一点,但他已经删除了他的答案。引用:

据我所知,在输出到 stderr 时,它没有被 执行。我对它不是很有信心,但考虑使用 http://php.net/manual/en/function.proc-open.php,它允许您 将 stderr 指向它自己的管道。

这其实是正确的做事方式。我的解决方案(因为我只想要 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);
}

$output 现在包含打印到 stderr 的任何 at(它应该真正进入 stdout,因为它不是错误),并且 $return_value 包含 0 成功。

【讨论】:

  • @Jack 你到底是什么意思?
  • 我的意思是echo exec("echo 'php -f /path/to/file.php foo=1' | at now + 1 minutes 2>&1", $result);
  • @Jack 它运行良好。难道你不能早点发布并节省我几个小时的挣扎吗? ;)
  • 哦不!抱歉,我不得不在 SO 和加勒比海盗之间做出选择 ;-)
【解决方案2】:

这里有一个更复杂的解决方案,使用 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;
}

用法示例:

// getting the mime type of a supplied file
echo runCommand('file -bi ' . escapeshellarg($file));

另一个使用命令参数的例子:

// executing php code on the fly
echo runCommand('/usr/bin/php', '<?php echo "hello world!"; ?>');

另一个使用 force 参数的示例(这对于将在执行过程中更改输出的命令很有用):

// converting an mp3 to a wav file
echo runCommand('lame --decode ' . escapeshellarg($source) . ' ' . escapeshellarg($dest), '', true);

我希望这会有所帮助:-)

【讨论】:

  • 感谢您展示蹩脚的例子!目前正是这样做的。
【解决方案3】:

尝试创建一个最小(非)工作示例。分解所有内容,一次只测试一件事。

这是您的 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$ 

minute 而不是minutes

at 的输出通过邮件发送给我!!

【讨论】:

  • 邮局还是联邦快递?
猜你喜欢
  • 2017-05-16
  • 1970-01-01
  • 2017-08-30
  • 2014-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多