How to email output from shell_exec()? - php

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?

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.

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().

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 !

Related

How to run external php script using Php shell_exec?

I have the following code on my index.php file. But it is not working properly.. When i directly visit domain.com/script.php it works. I need this script to be executed in the background while accessing index page. Can anyone help me?
shell_exec('php script.php > /dev/null 2>/dev/null &');
check php is running in safe mode or not shell_exec is disabled in safe mode for the sake of security why don't you use
curl
to run the code
Well I think there are 2 possible issues in your case
1) try this:
shell_exec("script.php 2>/dev/null >/dev/null &");
OR
shell_exec("script.php 2>&1 | tee -a /tmp/mylog 2>/dev/null >/dev/null &");
2) A simple way to handle the problem of capturing stderr output when using shell-exec under windows is to call ob_start() before the command and ob_end_clean() afterwards
ob_start();
ob_end_clean();
Well instead of using shell_exec, you can make an ajax call to script.php when the user visits index.php.
Another option is to run the script.php as a cron job every 5 minutes or so. When the user visits index.php, some data can be saved to database indicating that script.php should run. script.php should check if it is marked for running.

What does 2>&1 do in this php snippet?

Regarding this code
public function invoke($url)
{
exec('wget 2>&1', $output);
print_r($output);
}
What does the 2>&1 do in this command? I found this on SO but the 2>&1 was not explained
wget is a linux command and I'm running it from PHP using exec().
The code above works. I just need to insert the $url in the correct place and understand the 2>&1.
Related Links
GNU Documentation on Wget
You have several output streams.
The 2 most common are STDOUT (standard output) and STDERR (error output).
Normally you only see the STDOUT output. With exec this is also the only stream that it catches.
Now: the command 2>&1 means litteraly that you pass the output that would go to STDERR to the same output as the normal output. In this case to the exec function of PHP (but mostly to your shell).
This is mostly used when you want to daemonize your apps, and sent all the output to /dev/null, but it can also be used for this case (that you can see everything with PHP).

Is it time consuming to print log in exec command?

In PHP,
I am running exec command in php script so that It will run in background. But I'm wondering about the performance hit when logging to log_file?
exec("/usr/bin/php /path/to/Notification.php >> /path/to/log_file.log 2>&1 &");
If so then how can I not print output to log_file? I know /dev/null. But I don't know correct syntax or structure. Please Can anyone append me this on above line.
Any help will be appreciated.
since you are appending to the log file through the bash output redirection, it will be very good in terms of performance.
Everything depends ofcourse on how much output that is being logged and how big your log file is, if you aren't rotating it properly.
If this is too excessive, you can disable the output redirection, simply by removing everything after the >> output redirection directive:
exec("/usr/bin/php /path/to/Notification.php &");
this however could still output to the system's stdout or stderr, to skip this redirect all output to /dev/null as you mentioned:
exec("/usr/bin/php /path/to/Notification.php &> /dev/null &");
here is a good reference about output redirection in bash
please also note that $> is bash only.

What exactly does this PHP code do? system("php ./somescript.php $something >/dev/null &");

system("php ./somescript.php $something >/dev/null &");
I'm new to PHP and I am deciphering someone else's code and can't figure out what this code is doing. I looked at the system documentation here so I understand that it will execute the PHP script in somescript.php, and that $something is a parameter passed to that script...but after that I'm lost.
Also, what part of the script does $something get passed to? How does it know what function in somescript.php to call first?
You are correct about it executing the script with $something passed as parameter. The > /dev/null is just piping the output into a black hole (i.e. suppressing it). The & part launches the script in the background.
system("php ./somescript.php $something >/dev/null &");
can be split up as:
system(
This is the php function to execute a command in shell
system("php
We are asking the php command line interpreter to be run
system("php ./
we are asking the interpreter to look in current directory using ./
system("php ./somescript.php
we are saying that the php file to be executed in somescript.php
system("php ./somescript.php $something
we are passing $something which is a variable in the script running system() as an argument into the script somescript.php
system("php ./somescript.php $something >/dev/null
we are saying that the output should be sent to /dev/null ..which basically means do not print any output on the screen. > is the redirection command. So > /dev/null means redirect output to /dev/null which is like an alias for a "null device" or simply..nothing.
system("php ./somescript.php $something >/dev/null &");
Lastly we are asking the script to be run in the background using & which means as soon as the script starts, control is returned back to the shell
It's basically running the ./somescript.php program, with $something as a command-line parameter.
It explicitly ignores the output by routing it to the null device.
And it runs it in its own shell and doesn't wait for it to finish (that's the & bit on the end).
I assume that somescript.php is a program that runs some kind of background task. It probably takes a bit of time to run, but your main program doesn't need to know about the results of that task, so it doesn't need to wait for it to finish.
[EDIT]
$something is passed into the program as a command-line argument. When PHP is called from the command line, the arguments are populated into the $argv array.
See the PHP manual for more info:
http://php.net/manual/en/reserved.variables.argv.php
http://php.net/manual/en/features.commandline.php
1 - system: execution of an external program from PHP
2- php ./somescript.php $something: PHP cli execution of a script called ./somescript.php with one argument being $something.
3 - >/dev/null: redirects stdout to /dev/null which means you won't see standard output, but you will still see stderr. More info on output redirections. That's pure UNIX nothing to do with PHP.
4 - &: sends command in the background so that PHP execution can continue without having to wait for the external program to complete. Once again, pure UNIX, nothing to do with PHP per se. More info.

Prevent waiting for command line output

I thought that this would run without waiting for an output:
php /scripts/htdocs/summaries.live/app/scripts/generate-pdfs.php live 1 > /dev/null 2>&1
But it's not happening. PHP's exec() function is waiting for an output. How can I work around this to prevent this from happening?
you're missing & on the end of command
php /scripts/htdocs/summaries.live/app/scripts/generate-pdfs.php live 1 > /dev/null 2>&1 &
If running something with exec, the documentation states
Note:
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.

Categories