29

I have a number of command line scripts in PHP that use exec() to perform tasks such as restarting services, loading MySQL timezone files, etc. While exec() itself does not output anything to the screen, some of the commands I am running are forcing output that I can't seem to suppress (even with ob_start()/ob_end_clean()). For example, the following would load timezone files into MySQL. We run this periodically to make sure MySQLs timezone data is up to date:

 $command = 'mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql';
 exec($command, $output, $result);

In this example, I would expect all output from the command to be written into $output, but I still get the following output forced to the screen:

Warning: Unable to load '/usr/share/zoneinfo/Asia/Riyadh87' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/Asia/Riyadh88' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/Asia/Riyadh89' as time zone. Skipping it.
...

Is there any way to suppress this output? Redirecting to /dev/null is not ideal as that would cause PHP to continue processing without waiting for the command to complete.

Thanks in advance,
~ JamesArmes

chanchal118
  • 3,551
  • 2
  • 26
  • 52
JamesArmes
  • 1,315
  • 4
  • 18
  • 23
  • 3
    For those wondering why the example code isn't working, it's because only `stdout` is captured. The errors given are being written to `stderr`, which is not captured but rather dumped to the screen. – etheros Oct 22 '09 at 15:38
  • 1
    I came to this thread through google looking for a way to supress all output when running a PHP CLI script. My solution was to wrap the `exec()` call in `ob_start()` and `ob_end_clean()`. – Alex S Aug 12 '12 at 00:56

4 Answers4

27

Redirecting stderr alone should not influence where processing takes place, just make sure not to add an &. It should only run in the background if you redirect the output and make it run in the background.

Edit:

Cracked open cygwin, you need to redirect stderr for the first command, give this a try:

$command = 'mysql_tzinfo_to_sql /usr/share/zoneinfo 2> /dev/null | mysql mysql';
exec($command, $output, $result);
Yannick Motton
  • 34,761
  • 4
  • 39
  • 55
  • This is not entirely true. The PHP manual means that if you simply use `&` without redirection, PHP will still hang. Redirection alone still does not cause it to run in the background. – Ben James Oct 22 '09 at 12:58
  • Hmm indeed, that seems more plausible. I will correct my answer – Yannick Motton Oct 22 '09 at 13:02
  • Redirecting using $command = 'mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql 2> /dev/null'; still causes the same output. However, calling my script like php mysql_timezones.php 2> /dev/null properly suppress the output. Is it possible to get the same results without calling my script in that fashion? – JamesArmes Oct 22 '09 at 14:03
  • 1
    Try `&> /dev/null`. please note there is no space between `&` and `>` – Yannick Motton Oct 22 '09 at 14:39
  • I just figured this out and came here to post my findings, only to find that you beat me to it :-P It was indeed mysql_tzinfo_to_sql outputting the errors and not mysql. Thanks to everyone who responded! – JamesArmes Oct 22 '09 at 16:05
  • Return *The system cannot find the path specified.* on Windows. – vee Sep 03 '21 at 13:11
12

Just redirect stderr to /dev/null

$command = 'mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql 2>/dev/null';

or to stdout

$command = 'mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql 2>&1';
jitter
  • 53,475
  • 11
  • 111
  • 124
4

Redirecting to /dev/null does not cause PHP to stop waiting for the command. Adding a & does do this, you probably associate the two because the final & is often used in conjunction with a redirect.

In response to Yannick's (deleted) comment: it seems if you want to run something in the background in PHP, you must redirect as well as using &. This does not mean that redirection alone causes it to run in the background.

Ben James
  • 121,135
  • 26
  • 193
  • 155
  • According to the PHP manual "If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends." Although it appears your are correct, PHP requires both a redirect and the background operator & – JamesArmes Oct 22 '09 at 13:57
  • JamesArmes: that is precisely what the 2nd part of my answer was intended to explain – Ben James Oct 22 '09 at 14:27
1

According to http://us3.php.net/manual/en/function.shell-exec.php you can assign this command's output to a variable.

You don't necessarily have to do anything with the variable, which means you are effectively suppressing output.

Hope that helps!

  • 1
    That's what the $output variable in the exec() call is supposed to do (it's passed by reference). I have tried using shell_exec() and it produces the same results. – JamesArmes Oct 22 '09 at 14:22