Invoking cron from php is not working - php

Cron is not working properly. i have created a file inside /etc/cron.d with following command
$ touch /etc/cron.d/php-crons
$ chown www-data /etc/cron.d/php-crons
i got error like (*system*php-crons) WRONG FILE OWNER (/etc/cron.d/php-crons)
so i changed file owner as root
$ chown root /etc/cron.d/php-crons
even though cron is not working.
my php file (cron.php) is as follows
$fp = fopen('/etc/cron.d/php-crons', 'a');
fwrite($fp, '10 * * * * root usr/bin/php PATH TO SCRIPT/email.php'.PHP_EOL);
fclose($fp);
when i open the /etc/cron.d/php-crons there i can able to see the job.
10 * * * * root usr/bin/php /var/www/PATH TO SCRIPT/email.php
In email.php i included
#!/usr/bin/php
mail ("examplemail#gmail.com", "Cron Successful Public HTML!", "Hello World from cron.php!");
if i change (/etc/cron.d/php-crons)file owner as root and then run cron.php in browser , then i not able to write anything inside /etc/cron.d/php-crons and get warning as follows.
Warning: fopen(/etc/cron.d/php-crons): failed to open stream: Permission denied in /var/www/cron.php on line 2 Warning: fwrite() expects parameter 1 to be resource, boolean given in /var/www/cron.php on line 3 Warning: fclose() expects parameter 1 to be resource, boolean given in /var/www/cron.php on line 4 .
please someone guide me!!

There are several issues. As you noticed, your implementation of the cron daemon does not allow to be the files owned by non-root-users and you will not be allowed to make the file world-writable for the same reason of security.
Your cron job line, at least in the example, lists a relative path ("usr/bin/php") that should be absolute. That your cron.php file is owned by root does not mean it is run as root user. It is executed and run by PHP because it has the appropriate group and/or other permission bits. And you shouldn't change the permissions in a way it is run as root (e.g. with setuid-chmods).
What you probably should do is a cronjob line that acts as a wrapper to a PHP script. The PHP script reads all your jobs from a database and executes them, or even a text file similar to what you already created.
This way you can run the wrapper script as a non-root user. Most cron implementations allow you to name the user (e.g. www-data) on others you use the "su" command before your script (see man 5 crontab etc.).

which operating system are you using? Normally for something like this you want to use per user crontabs. so the commands are run as that user. /etc/cron.d is used for system crontabs. (/var/spool/cron/crontabs) is where user crontabs are stored, but they will need to be enabled. Normally by adding the user that is allowed to use them to /etc/cron.allow. Allowing the web process to make changes to files that run as root is really a bad idea. With the per user option it would only be able to touch things that it could normally touch anyways, so less of security risk.

Related

PHP fopen can not read file if called with cronjob [duplicate]

This question already has answers here:
Crontab - Run in directory
(2 answers)
Closed 8 years ago.
I have a php script that sends out a email report with an attached pdf document. I use fopen. If I call the php file manualy it works without any problems and the mails are beeing send as expected.
But:
If the same file should is call by cron job, it does not work at all. The error is:
Warning: fopen(filename.pdf): failed to open stream: No such file or directory in /home/public_html/util.php on line 29
Any ideas how to fix this?
Every cron runs in a minimal environment, which can be a different shell and a different profile than your user account. Also scripts are started not from the containing directory themselves.
In most cases it works, if you just change your directory to the one containing the script like you do when execute the script on the command line shell. Instead of
* * * * * /usr/bin/php /path/to/your/file.php
write this:
* * * * * cd /path/to/your/ && /usr/bin/php ./file.php
If this is not sufficient, you can load your default user shell and your PATH variable with writing
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
at the top of your crontab (with the right settings of course, which might be /bin/bash and the output of echo $PATH).
Cron jobs run without any environment, including a current directory. That means that you'll need to use the full path to any files that you want to work with.
If you add a valid email address at the top of your crontab:
MAILTO=your-email#example.com
you'll get any output the cron job does sent to your email. This includes error messages, which can be useful for debugging.

PHP cron job include absolute file path

I'm running a cron job configurated in CPanel:
**cd /home/DOMAIN_A/public_html/ ; php host_cron_job.php**
In the host_cron_job.php file I am trying to access with the absolute file path other file in the same server but it's other domain, something like:
**include "/home/DOMAIN_B/public_html/config.php";**
But I get this error:
**<b>Warning</b>: include(/home/DOMAIN_B/public_html/config.php) [<a href='function.include'>function.include</a>]: failed to open stream: Permission denied in <b>/home/DOMAIN_A/public_html/host_cron_job.php</b>**
Anyone having solution to this issue?
The UNIX user running the Cron task does not have the authorisation to access /home/DOMAIN_B/public_html/config.php. Log-in as this user, and try to access this path step-by-step. Adjust permissions as required using the chmod command.
The user must be able to "eXecute" the following directories (which means "enter those directories" for UNIX permissions) :
/
/home
/home/DOMAIN_B
/home/DOMAIN_B/public_html
And it must have a Read permission on both /home/DOMAIN_B/public_html/config.php and /home/DOMAIN_B/public_html/config.php :
Basically, your task should be :
* * * * * php /home/DOMAIN_A/public_html/host_cron_job.php
or
* * * * * cd /home/DOMAIN_A/public_html && php host_cron_job.php
depending on your environment needs, and with the scheduling parameters of your choice.
Note : I'd rather use && than ';', this will avoid the execution of the PHP script if going to the directory fails at first.

Don't want php script to execute the shell command as apache user when it is executed through browser?

I have created a PHP script that generates some .gz files, when I execute the PHP script through command line (cli), it generate the .gz file having 'desert' as user but when the script is executed through browser it generates the .gz file with 'nobody' as user which should not happen. I want the generated file to have 'desert' user rather than 'nobody' user when the script is executed through browser.
Here is the code I have created:
$file='test';
$newFileGZipCommand = 'cat '.$file.'_new | gzip > '.$file.'.gz';
//$newFileGZipCommand = 'sudo -u desert cat '.$file.'_new | gzip > '.$file.'.gz'; // This does not work
$newFileGZipCommandExecute = shell_exec($newFileGZipCommand);
//chmod($file.'.gz',0777) or die("Unable to change file permission");
//chown($file.'.gz', 'directu') or die("Unable to change file Owner");
I tried doing changing the file permissions and owner through chmod() and chown() functions in php but it say "chown(): operation not permitted".
Any pointer to this is highly appreciated.
[Note: I cannot change the httpd.conf or any other configuration files]
Sudo normally requires an interactive shell to enter your password. That's obviously not going to happen in a PHP script. If you're sure you know what you're doing and you've got your security issues covered, try allowing the Apache user to run sudo without a password, but only for certain commands.
For example, adding the following line in your sudoers file will allow Apache to run sudo without a password, only for the gzip command.
nobody ALL=NOPASSWD: gzip
Adjust the path and add any arguments to suit your needs.
Caution:
There might still be complications due to the way PHP calls shell
commands.
Remember that it's very risky to allow the web server to
run commands as root!
Another alternative:
Write a shell script with the suid bit to make it run as root no matter who calls it.
Probably a better alternative:
Write the commands to a queue and have cron pick them up, validate them (only allow known good requests), and run them, then mark that queue complete with the date and result.
Your end-user can then click/wait for update using ajax.
Hope it helps resolve your answer.

php ftp_get() returns permission denied

I'm using a ftp upload script to transfer one server to another. It works fine in a browser window, and works great from an ssh command line by running:
php /var/www/vhosts/domain.com/httpdocs/ftp_shell.php
but when I run the exact same command from a cron, I get this:
PHP Warning: ftp_get(ftp.tmp): failed to open stream: Permission denied in /var/www/vhosts/domain.com/httpdocs/ftp_shell.php on line 516
PHP Warning: ftp_get(): Error opening ftp.tmp in /var/www/vhosts/domain.com/httpdocs/ftp_shell.php on line 516
I looked on line 516, which is:
if((ftp_get($ftp_from,"ftp".$tmp.".tmp",$fname,FTP_BINARY) ||
ftp_get($ftp_from,"ftp".$tmp.".tmp",$fname,FTP_ASCII)) &&
(ftp_put($ftp_to,$fname,"ftp".$tmp.".tmp",FTP_BINARY) ||
ftp_put($ftp_to,$fname,"ftp".$tmp.".tmp",FTP_ASCII)) &&
ftp_site($ftp_to,"chmod ".base_convert($chmod,10,8)." $fname") &&
f_size()&&unlink("ftp".$tmp.".tmp")) {echoout(" (".$size_b." bytes) ok<br>");$count_f++;}
I know that it's writing the file to a temp file, but why would it allow me to do it in the browser and command line, but not a cron?
Probably the temp file was created by php script(apache user) and you want to read it from cron job (root user). Temp files are not readable from one users to others for security reasons.
You have to change your cron job to be executed by apache user, or you can alter the permissions of the temp file to be readable for everyone, but this is not recommended as any other procesess could read the file.
Jobs run under cron will have a different default working directory than whatever you're running from a webserver and/or the command line. Most likely whatever directory IS being used as the default while in cron does not have appropriate permissions for the cron job to use.
Try using absolute paths, e.g.
ftp_get($ftp_from,"/real/path/to/file/ftp".$tmp.".tmp",$fname,FTP_BINARY)
^^^^^^^^^^^^^^^^^^^
instead of the relative paths you're using otherwise.
The error says:
PHP Warning: ftp_get(ftp.tmp): failed to open stream
and the line is:
if((ftp_get( $ftp_from, "ftp" . $tmp . ".tmp", $fname ...
so the error must be in a empty $tmp variable

How to set up a cron job via PHP (not CPanel)?

How to set up a cron job via PHP (not CPanel)?
Most Linux systems with crond installed provides a few directories you can set up jobs with:
/etc/cron.d/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
...
The idea here is to create a file in one of these directories. You will need to set the proper permissions/ownership to those (or one of those) directories so that the user launching the PHP script can write to it (Apache user if it's a web script, or whatever CLI user if CLI is used).
The easiest thing is to create an empty file, assign proper permission/ownership to it, and have the PHP script append/modify it.
Per example:
$ touch /etc/cron.d/php-crons
$ chown www-data /etc/cron.d/php-crons
Then in PHP:
$fp = fopen('/etc/cron.d/php-crons', 'a');
fwrite($fp, '* 23 * * * echo foobar'.PHP_EOL);
fclose($fp);
If what you're getting at is dynamically adding lots of jobs to crontab form your application, a better way to do that is manually add ONE cron job:
php -f /path/to/your/runner.php
Store your jobs that you would be adding to cron manually in a table (or one table per task-type), and then have your runner go through the table(s) every minute/hour/day/whatever and execute all the ones that should be executed at that time.
From pure PHP I will create deamon that will manage this (those) cron job(s).
how to create it:
http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/ to start with
Finding crontab file isn't easy on shared hosting and there's no certainty that cron will read that file again while it's already running.
Actually I the best way is to use corntab command.
If you don't have access to shell you can use for example PHPShell. Try this.
Uplode a txt file via FTP with jobs in crontab fomat for example
5 * * * * /some/file/to/run.sh > /dev/null
(remember to put a newline at the end of that line)
Log in to your PHPShell and run
crontab uploded_filename.txt
Remember to change file permissions
chmod 775 uploded_filename.txt
Check your cron jobs using
crontab -l
Cheers
There is an embargo on the use of PHP to edit crontabs which has been in place since 2004. You may not be allowed to do this if you live outside of the United States, check with your local government agency.
But seriously, you could always call "crontab -" with a system call. If you need to do this for some user other than the webserver, you'll need some ssh or sudo magic. But it all seems like a bad idea.

Categories