0

With cron jobs, the output of the file being executed is emailed to me. I recently discovered via this answer that it's possible to asynchronously execute a PHP file using the shell_exec() function. Per the above answer, I've been using the following command:

shell_exec('php /file/path.php parameter1 parameter2 > /dev/null 2>/dev/null &');

I think what is of most interest with regards to this question is the stuff at the end:

> /dev/null 2>/dev/null &

Is there any way to change that so that the output is emailed, like with a cron job?

Community
  • 1
  • 1
Nate
  • 22,356
  • 31
  • 115
  • 196

3 Answers3

2

The line

> /dev/null 2>/dev/null &

Essentially sends the output to a null file. If you take that bit off, the output will be sent to the standard out, which should in turn should email you the results assuming you run it with a cron job.

So,

shell_exec('php /file/path.php parameter1 parameter2');

If you're not running it with a cron job, you'll need to build in the email functionality to the script itself.

Samsquanch
  • 8,042
  • 12
  • 50
  • 86
2

First off, shell_exec() is not asynchronous. Execution of the PHP code will be suspended until the shell_exec() call has terminated.

This: > /dev/null tells the shell to redirect stdout from the process being executed to /dev/null, which means it disappears. This: 2> /dev/null does the same, but for stderr in stead of stdout.

If you remove these parts of the shell_exec() call, the call will return whatever is written to stdout:

$result = shell_exec('php /file/path.php parameter1 parameter2');
mail('me@email.com', 'Shell output', $result);

There are also other alternatives to shell_exec() that may suit your needs better. For example popen()andproc_open()` allow more fine grained control over input and output.

Also, since you are executing a PHP script, you may be able to simply use include() or require(), depending on how the script is written. Another option would be to read the file and then execute the PHP code using eval().

Nico
  • 2,465
  • 16
  • 25
  • Are you sure with those parameters it's not asynchronous? According to the answer I linked to in my post (http://stackoverflow.com/a/1019904/1101095), it is. – Nate Mar 10 '14 at 18:06
  • The `shell_exec()` function works by launching a shell process and executing the specified command within that process. The `&` sign at the end of your command means that the command will run asynchronously *within the shell process*, so you could run multiple shell commands simultaneously. PHP execution still won't resume until the shell process has terminated, however. – Nico Mar 10 '14 at 18:26
  • Actually, looking at the answer you linked to, it appears you're right. But if you launch the process asynchronously like this the output is discarded, so you won't be able to mail it to anyone either. You could work around that by redirecting the output to a file and mailing the contents of the file once execution is done, but that means you need some way of determining whether execution is done as well. Or you could do what Oct suggested in his answer: http://stackoverflow.com/a/22307556/623612 – Nico Mar 10 '14 at 18:32
1

Use :

| mail -s "Result of cron job" myemail@company.com

At the end of your command. Also, you can pipe stderr and stdout into stdout 2> &1 | mail....

That should do the trick. Maybe because you use shell_exec("... &"), you'll have to wrap the whole php /file/... | mail -s "result" myemail@company.com in a subshell. like:

shell_exec('(php /file/path.php parameter1 parameter2 2> &1 | mail -s "Result of cron job" myemail@company.com) &')

This is a rather ugly way to get the output to send a message and I'd advise in favor of refactoring the outer call of shell_exec to read stderr and stdout, craft a message and send that to yourself. Meanwhile the | mailsolution should do the trick.

Happy mailing !

Oct
  • 1,465
  • 13
  • 18