I'm trying to run the curl
command in PHP file and am trying to list its output in the error log file. All the PHP errors are listed in the file except the errors I get from exec()
function. The PHP code I'm trying is:
exec("nohup curl --output " . $_SERVER['DOCUMENT_ROOT'] . "/abc.mp3 http://192.99.8.170:8098/stream/1; --max-time $time_in_seconds > /devnull&");
How could I get the error generated by this command in the error log file? I have googled for this, but I couldn't get sufficient results.
There are several issues in the command itself.
exec("nohup curl --output ".$_SERVER['DOCUMENT_ROOT'] . "/abc.mp3 http://192.99.8.170:8098/stream/1; --max-time $time_in_seconds > /devnull&");
(I have wrapped the original line for clarity.)
No need in nohup
The main purpose of the nohup
command is to have a process running if you get logged off the shell because of a terminal line hang-up. (When a shell exits, it sends SIGHUP to its child processes.) With nohup
you can start a command and then log off the shell.
The curl
command is indeed terminated on SIGHUP. You may use nohup
to put the download process running in background. But your objective is to capture the command's output, whether STDIN or STDOUT. It is also important to know when the command completes its work and how. For instance, after executing the command synchronously, it is possible to check the exit code (zero indicates a success) and to check if the file is actually downloaded to the file system:
$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;
Output
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
Note the use of escapeshellarg
function. You should escape all shell arguments, otherwise the shell will interpret its special characters.
The semicolon
Strings separated with semicolon (;
) are interpreted as different commands. So your --max-time $time_in_seconds > /devnull&
is interpreted as the second command. I have no idea what you have tried to achieve, but you most likely don't need it there.
Redirection to /dev/null
There is a typo in your > /devnull&
expression. You likely meant redirection to the /dev/null
pseudo-device: > /dev/null
.
In the code above, we have captured the standard output. You should use the proc_open()
function, if you want to capture the output to other file descriptors as well:
$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";
Output
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
outputs the "verbose" output to the standard error descriptor)
In the view of foregoing, your command should be built as follows:
$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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With