如何在php错误日志文件中获取命令行错误?

时间:2016-09-19 08:33:39

标签: php bash curl stderr error-log

我试图在php文件中运行curl命令并尝试在错误日志文件中列出其输出。除了从exec()函数获得的错误之外,文件中列出了所有php错误。我尝试的PHP代码是:

exec("nohup curl --output ".$_SERVER['DOCUMENT_ROOT']."/abc.mp3 http://192.99.8.170:8098/stream/1; --max-time $time_in_seconds > /devnull&");

任何人都可以请求帮助,以便我可以在错误日志文件中获取此命令生成的错误。我已经用Google搜索了,但无法获得足够的结果。

谢谢!

1 个答案:

答案 0 :(得分:1)

命令

命令本身有几个问题。

  

exec(“nohup curl --output”。$ _ SERVER ['DOCUMENT_ROOT']。          “/abc.mp3 http://192.99.8.170:8098/stream/1; - max-time $ time_in_seconds> / devnull&”);

(为了清楚起见,我已将原始行包裹起来。)

不需要nohup

nohup命令的主要目的是,如果由于终端线挂起而导致shell被注销,则进程正在运行。 (当shell退出时,它会将SIGHUP发送到其子进程。)使用nohup,您可以启动命令,然后注销shell。

curl命令确实在SIGHUP上终止。您可以使用nohup使下载进程在后台运行。但是你的目标是捕获命令的输出,无论是STDIN还是STDOUT。知道命令何时完成其工作以及如何完成也很重要。例如,在同步执行命令之后,可以检查退出代码(零表示成功)并检查文件是否实际下载到文件系统:

$output_dir = empty($_SERVER['DOCUMENT_ROOT']) ?
'/tmp/default-download-dir' : $_SERVER['DOCUMENT_ROOT'];
if (!is_dir($output_dir)) {
  if (!mkdir($output_dir, 0755, true))
    die("Failed to create directory $output_dir");
}

$url = 'http://php.net/images/logo.php';
$output_file = "{$output_dir}/logo.svg"; ;
// 2>&1 redirects standard error descriptor (2)
// to the standard output descriptor (1)
$command = sprintf("curl -o %s %s 2>&1",
  escapeshellarg($output_file),
  escapeshellarg($url));
$output = [];
exec($command, $output, $exit_code);
if ($exit_code != 0) {
  die("Failed to download $url to $output_file");
}

clearstatcache(true, $output_file);
if (!file_exists($output_file)) {
  die("File $output_file not found on file system, command: $command");
}

echo "$url has been saved to $output_file:\n",
  implode(PHP_EOL, $output), PHP_EOL;

输出

http://php.net/images/logo.php has been saved to /tmp/default-download-dir/logo.svg:
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  2202  100  2202    0     0   4171    0 --:--:-- --:--:-- --:--:--  4665

请注意使用escapeshellarg功能。您应该转义所有shell参数,否则shell将解释其特殊字符。

分号

用分号(;)分隔的字符串被解释为不同的命令。所以你的--max-time $time_in_seconds > /devnull&被解释为第二个命令。我不知道你试图实现什么,但你很可能不需要它。

重定向到/dev/null

您的> /devnull&表达式中存在拼写错误。您可能需要重定向到/dev/null伪设备:> /dev/null

捕获输出到不同的文件描述符

在上面的代码中,我们捕获了标准输出。如果要将输出捕获到其他文件描述符,则应使用proc_open()函数:

$output_dir = empty($_SERVER['DOCUMENT_ROOT']) ?
  '/tmp/default-download-dir' : $_SERVER['DOCUMENT_ROOT'];
if (!is_dir($output_dir)) {
  if (!mkdir($output_dir, 0755, true))
    die("Failed to create directory $output_dir");
}

$url = 'http://php.net/images/logo.php';
$output_file = "{$output_dir}/logo.svg"; ;
$command = sprintf("curl -o %s %s",
  escapeshellarg($output_file),
  escapeshellarg($url));

$descriptors = [
  1 => ['pipe', 'w'], // stdout
  2 => ['pipe', 'w'], // stderr
];

$proc = proc_open($command, $descriptors, $pipes);
if (!is_resource($proc))
  die("Failed to open process for command $command");

if ($output = stream_get_contents($pipes[1]))
  echo "Output: $output\n\n";
fclose($pipes[1]);

if ($errors = stream_get_contents($pipes[2]))
  echo "Errors: >>>>>>>>\n$errors\n<<<<<<<\n\n";
fclose($pipes[2]);

$exit_code = proc_close($proc);

if ($exit_code != 0) {
  die("Failed to download $url to $output_file");
}

clearstatcache(true, $output_file);
if (!file_exists($output_file)) {
  die("File $output_file not found on file system, command: $command");
}

echo "$url\nhas been saved to $output_file\n";

输出

Errors: >>>>>>>>
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2202  100  2202    0     0   4231      0 --:--:-- --:--:-- --:--:--  4735

<<<<<<<

http://php.net/images/logo.php
has been saved to /tmp/default-download-dir/logo.svg

curl将“详细”输出输出到标准错误描述符)

固定命令

在上述观点中,您的命令应按如下方式构建:

$url = 'http://192.99.8.170:8098/stream/1';
$command = sprintf("curl -o %s %s --max-time $time_in_seconds",
  escapeshellarg($output_file),
  escapeshellarg($url));