1

I have a PHP file that runs a node script using exec() to gather the output, like so:

$test = exec("/usr/local/bin/node /home/user/www/bin/start.js --url=https://www.example.com/");
echo $test;

It outputs a JSON string of data tied to the website in the --url paramater. It works great, but sometimes the output string is cut short.

When I run the command in the exec() script directly, I get the full output, as expected.

Why would this be? I've also tried running shell_exec() instead, but the same things happens with the output being cut short.

Is there a setting in php.ini or somewhere else to increase the size of output strings?

Dario Zadro
  • 1,143
  • 2
  • 13
  • 23
  • How is it being run automatically (web,cron)? How long does it take to run when it works? Strings in php are big https://stackoverflow.com/questions/3189040/what-is-the-maximum-length-of-a-string-in-php – Jason K Jul 10 '19 at 16:38
  • 1
    Not familiar enough with the inner workings of PHP, but it sounds like possibly a buffering issue. –  Jul 10 '19 at 16:46
  • Is there any rhyme or reason to when it does this? Does re-running with the **same** URL work fine? Or is it consistent for certain URLs? – ceejayoz Jul 10 '19 at 16:54
  • No, re-running with the same URL that's having issues is always cut short. The only thing I've noticed is the length of the string is much larger on URLs that fail. – Dario Zadro Jul 10 '19 at 23:58
  • Did notice that the output is only cut short when part of the ouput includes a reference to base64 data, such as `"fonts":{"amount":6,"files":["data:application/x-font-woff2;base64,d09GMgABAAAAAFEAABIAAAAAxMwAAFCZAAFND....` – Dario Zadro Jul 11 '19 at 00:52
  • Sending to a temp file as shown here https://stackoverflow.com/questions/3554679/php-exec-output-being-trimmed/3554964 is working, but would rather have the direct output. Any other ideas? – Dario Zadro Jul 11 '19 at 01:13

2 Answers2

2

It appears the only way to get this working is by passing exec() to a temp file, like this:

exec("/usr/local/bin/node /home/user/www/bin/start.js --url=https://www.example.com/ > /home/user/www/uploads/json.txt");
$json = file_get_contents('/home/user/www/uploads/json.txt');
echo $json;

I would prefer to have the direct output and tried increasing output_buffering in php.ini with no change (output still gets cut off).

Definitely open to other ideas to avoid the temp file, but could also live with this and just unlink() the file on each run.

Dario Zadro
  • 1,143
  • 2
  • 13
  • 23
0

exec() only returns the last line of the output of the command you pass to it. Per the section marked Return Value of the following documentation:

The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.

To get the output of the executed command, be sure to set and use the output parameter.

To do what you are trying to do, you need to pass the function an array to store the output, like so:

exec("/usr/local/bin/node /home/user/www/bin/start.js --url=https://www.example.com/", $output);
echo implode("\n", $output);
Community
  • 1
  • 1
Alex V
  • 3,416
  • 2
  • 33
  • 52
  • There's only one line of output as a JSON string, so this doesn't apply in my case – Dario Zadro Jul 10 '19 at 23:56
  • 1
    Does your JSON string include the characters '\n' or '\r' at any point? Exec would read those as newlines, so they're sometimes present, that's probably where and why it's getting cutoff. That would also explain why it does work if you use a tempfile: since you're redirecting the output, none of the newlines appear in STDIN so it doesn't get cutoff. – Alex V Jul 11 '19 at 16:56
  • No, the json.txt file does not contain any newline or return notations. I just re-ran again to double-check. – Dario Zadro Jul 12 '19 at 15:43