execute command and email results

I am trying to create a PHP file, which will run a Linux command, and email the results to me. Then I will schedule the file to be executed via cron. I have already tested the command - grep “fail” /var/log/syslog | awk ‘{ print $9 }’ | sort | uniq -c - and it works perfectly. This is on a mail server running qmail.

Then to test it, I run wget “https://xxx.xxx.xxx.xxx/cron/send_mail_failures.php” --no-check-certificate > /dev/null

The test seems to output everything normally, but I never get the email. I know the credentials for the mail account are correct, as we use this for other things. I replaced the ip and password with xxx.

Here is my code:

[php]

<? include_once("mail.inc.php"); $temp = ""; extract($_REQUEST,EXTR_PREFIX_ALL,"r"); ob_start(); //$output = cat /var/log/qmhandle_output | grep "Deleting" | awk '{ print $1,$2 }' | sort | uniq -c; $output = grep "fail" /var/log/syslog | awk '{ print $9 }' | sort | uniq -c; qob_end_clean(); //echo $output; if (!empty($output)) { $mail = new my_phpmailer; $mail->IsHTML(false); $mail->SMTPAuth = true; $mail->Host = "xxx.xxx.xxx.xxx"; $mail->Username = "[email protected]"; $mail->Password = "xxxxxx"; $mail->SMTPDebug = false; $mail->From = "[email protected]"; $mail->Subject = "(MAIL) qmHandle Failure Report"; $mail->Body = $output; $mail->AddAddress("[email protected]"); if($mail->Send()) { } else { } } ?>[/php]

I have modified my code, but it still does not work. Here is what I have now…

[php]<?
include_once(“mail.inc.php”);

$temp = "";
extract($_REQUEST,EXTR_PREFIX_ALL,"r");

ob_start();
//$output = cat /var/log/qmhandle_output | grep "Deleting" | awk '{ print $1,$2 }' | sort | uniq -c;
  	passthru("grep "fail" /var/log/syslog | awk '{ print $9 }' | sort | uniq -c");
$last_line = ob_get_contents();
qob_end_clean();

//echo $output;

if (!empty($last_line)) {
	$mail = new my_phpmailer;
	$mail->IsHTML(false);
	$mail->SMTPAuth = true;
	$mail->Host     = "xxx.xxx.xxx.xxx";
	$mail->Username     = "[email protected]";
	$mail->Password     = "xxxxxxx";

	$mail->SMTPDebug = false;
	$mail->From = "[email protected]";
	$mail->Subject = "(MAIL) qmHandle Failure Report";
	$mail->Body = $last_line;

	$mail->AddAddress("[email protected]");

	if($mail->Send()) {
	} else {
	}
}

?>[/php]

That doesn’t look like a valid command.

You would also have a syntax error for “fail” it should be “fail”

grep, awk, sed and unicid are all valid linux calls. However, you’re right on the string escaping.

In addition, the following are wrong:

  • Line 9: If you are using double quotes, change $9 to $9 to prevent PHP from evaluating your variable.
  • Line 11: ob_get_clean() and not qob_get_clean()

Thank you very much. That worked perfectly!!

Now that the code works, I am having another issue trying to run it via cron every 6 hours. Here is my crontab entry.

0 */6 * * * wget “https://xxx.xxx.xxx.xxx/cron/send_mail_failures.php” --no-check-certificate > /dev/null

In theory, shouldn’t I be able to test this by running the following

 wget "https://10.0.134.104/cron/send_mail_failures.php" --no-check-certificate > /dev/null

from the command line, and it will execute my php file, which sends me an email with the results of the grep, as it does when I execute the file directly (php /var/www/cron/send_mail_failures.php?

With that line, you’re running it once at 6am, 12am, 6pm, 12pm. The correct format is:

*/6 * * * * your_command_here

(Minutes, Hours, DoM, month, DoW)

When using wget, does the syntax of the grep within the php file need to be different than if I were simply executing the script from command line?

In order to get the php script to work, I followed your suggestions to string escape the $9 and the “fail” as below, but would this cause any issues if I am calling this script using wget? The script works great when executing from cmd line, but will not work when using wget.

passthru(“grep “fail” /var/log/syslog | awk ‘{ print $9 }’ | sort | uniq -c”);

The linux wget command generates a HTTP request to your webserver. As such, it will be as though you queried your site from your browser.

A few caveats, however:

  • Depending on your webhosting company, if they use virtual host directives, you’ll need to provide the exact website host in there (http://mywebsite.com/ and not http://1.2.3.4/)
  • Depending on your webhosting company, your domain name might not resolve on the server. GoDaddy is a notorious PITA on this
  • Depending on your webservice company, you’ll have issues with wget like it being uninstalled or similar.

Consider the following command for cron:
*/6 * * * * wget “https://10.0.134.104/cron/send_mail_failures.php” --no-check-certificate > /home/to/a/file/you/can/read.txt

This will pipe the output of wget to the file /home/to/a/file/you/can/read.txt, allowing you to see what wget is stumbling on. Alternatively, you can run it using passthru in PHP (but make sure you’re on the same server as the one that has the cron job).

It seems that wget does not like my passthru command.

Here is one that works great:

[php]ob_start();
passthru(“grep user /var/log/syslog”);
$last_line = ob_get_contents();
ob_end_clean();
[/php]

Here is the one I cannot get to work:

[php]ob_start();
passthru(“grep “fail” /var/log/syslog | awk ‘{ print $9 }’ | sort | uniq -c”);
$last_line = ob_get_contents();
ob_end_clean();[/php]

Any ideas on why the 2nd one does not work with wget, but works fine from command line?

What exact errors do you get? echo $last_line and paste the result here, please. Also, $9 . :stuck_out_tongue:

Sorry, I posted the wrong command for the one that does not work. Forgot to escape the $9. Here is the one that doesn’t work… Thanks to all for your help on this, as I am just learning.

[php]ob_start();
passthru(“grep “fail” /var/log/syslog | awk ‘{ print $9 }’ | sort | uniq -c”);
$last_line = ob_get_contents();
ob_end_clean();[/php]

Half of the process in debugging code involves looking at errors returned. passthru passes all the output of wget to stdout, which is then picked up and cleared by $last_line. Can you mail yourself the content of that var, or store it somewhere to view it?

I figured out my issue. The wget hits the apache hosted page which runs under the www-data user, which does not have access to open the syslog. I manually opened the permissions and the script to works, however, I cannot leave the permissions like this, as you generally would never add www-data to the root user permissions. Huge no-no. What I am thinking is to run the php script directly via cron instead of wget via cron. php will run as the root user as called from root cron - which has access. That being said, to have cron run the script itself, would this be my cron entry?

*/6 * * * * php /var/www/cron/send_email_failures.php > /dev/null

You’ve almost got it correctly - you might need to specify the full executable path to PHP. Other than that, looks good!

Sebrunauld - this cron runs every 6 minutes. I need it to run every 6 hours. Here is what I am using:

*/6 * * * * php /var/www/cron/send_mail_failures.php > /dev/null

Oh, sorry! I corrected you for nothing earlier, I thought you said 6 minutes.

Change */6 * * * * to * */6 * * * to get it to run every 6 hours.

I tried to quute one of your previous responses, but it did not attach to this thread for some reason. You responded the following to my question about running cron every 6 hours, but that makes it run every 6 minutes, I need it to be hours. Still trying to make sense of this cron stuff.

With that line, you’re running it once at 6am, 12am, 6pm, 12pm. The correct format is:

*/6 * * * * your_command_here

(Minutes, Hours, DoM, month, DoW)

The cron format is pretty simple. You’ve figured out the command bit - the rest is the frequency. Each space-separated thing is a parameter. In order of appearance:

  • Minute. The minutes to match
  • Hours. The hours to match
  • Day of month. 1-31 or less
  • Month. 1-12
  • Day of week. 0-7.
  • means “any”. */x means “integer multiples of x”.

So, if you want to run it every 6 hours:
0 */6 * * *

This tells cron:

  • On the hour
  • Every six hours
  • Every day
  • Every month
  • Every day of the week

so what is the difference between the following? Anything?

00 */6 * * *

and

0 */6 * * *

Sponsor our Newsletter | Privacy Policy | Terms of Service