PHP Script as Cron doesn't work, but does from CLI - php

I have a php script that triggers some magento actions, and I set it to a cron of:
cd /home/dir/public_html; php -f file.php;
This starts the script, however it does not finish executing for some reason, the cron runs as the user "user", and when I run the command from the terminal as root it works perfectly. All the files it uses are chowned to user however. I thought it was an issue with paths which is why I added the CD command to the front of it, however that wasn't it.
I'm thinking this may be an issue with the creation of a lock file, I have it create a lock file, run the script, then delete the lock file in order to prevent it from running if it already is. The lock file is generated but never deleted, my knowledge is if it creates it as user "user" then it should be able to delete it as that user as well.
Any thoughts? Much appreciated.

Try to put the full path of PHP, or define the PATH variable in the first lines of crontab:
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games:/sbin:/usr/sbin
Edit : moreover, you can log your script like that :
* * * * * cd /home/dir/public_html; /usr/bin/php -f file.php; &>/tmp/file.log

Instead of calling the php from within the cronjob, call a shell script which is calling the php file then.
You can then change the environment the script is running in w/o the need to change the cronjob and you can easier test-drive the cron command (as you can just call the shell-script).
You can then, in the shell script, change the directory where the php-script expects to be in which will most certainly solve your issue.
Additionally you can change ini directives, handle logging and shell error handling, like piping STDERR to a file etc.
This is not exactly your problem, but the information given in this question might solve your issue: How can I force PHP Version for Command Line?.

Related

Running php script with cron: Could not open logfile, so such file or directory

I have a Raspberry Pi set up as a seedbox. I have a cron job that will run every 10 minutes, check for finished files using transmission-remote -l, grep for entries that are done (100%), get the names of the folders, copy these to the external drive, and then delete the original files on my Pi.
For every action that is done (A torrent is added, a torrent is finished, a file transfer has started, a file transfer has finished and the files have been deleted) an entry is written to my logfile.log, which is located in the same directory as all scripts, ´/home/pi/dev/´. Inside that folder I have a subfolder, logs that keeps logfiles on all moves from the pi to the external drive. These logfiles are all named after the folder/file being moved.
As I said, every 10 minutes, torrentfinished.phpis run through the cron job
*/10 * * * * php -f /home/pi/dev/torrentfinished.php
All output from the job is sent to my mail at /var/mail/pi.
Now, if I run the script manually, I can run it from anywhere by writing
php -f /home/pi/dev/torrentfinished.php
I have some debug lines written in right beneath the execution of each command. (I use shell_exec to run the commands because I'm more comfortable writing in php than bash).
It'll output
Started transfer
Wrote transfer to logfile
In logfilean entry is then added, with the text $timestamp : started transfer of data from torrent $torrentname. A separate file is created in logs/$torrentname.log. Basically, everything works perfectly.
However, when the cron job runs, I get the following output in /var/mail/pi
Unable to open logfile: No such file or directory
Started transfer
Wrote transfer to logfile
But as you've probably guessed, nothing happens. The files remain in their spot on the Pi and are not transferred. In addition, nothing is written to logfile or logs/$torrentname.log.
I've been wracking my brain over this, and been using chmod 777 on more files than could possibly be considered necessary nor safe, simply to make sure this isn't a permissions issue. I may have missed something of course, but I wouldn't think so. I've also tried renaming the file logfile to something else, but I still get the same error.
I have no more ideas on what to do, so if any of you have ideas, please do tell!
When you use this:
php -f /home/pi/dev/torrentfinished.php
You stay at /home/pi/dev/ directory. And logfile is written at /home/pi/dev/logs
When you run script in cron, base directory is another (for example it may be /bin or /usr/bin).
Try to use DIR or FILE constants to set a logfile path.
It might help to see the actual php code. My first step here would be to have the code print the path to logfile so I could figure out why it thinks it doesn't exist (are you using a relative path or some environment variable, because cron tends to run in a sanitized environment).

Running Cronjob from a specific directory

I created a php script for generating RSS feeds which is to eventually be run via a Cronjob.
All the php files and the resulting RSS xml will be within a sub folder in a website. The php script runs fine on my local dev if I use terminal or the browser while within the same directory on my local development machine.
e.g. php /Library/WebServer/Documents/clientname/siteroot/rss/dorss.php
works fine as does navigating to the dorss.php file in Chrome.
The CronJob has executed though with errors related to the fact that it cannot find the files specified with require_once() which are located in the same folder as rss or in a subfolder of that.
Long story short I need to have the Cronjob run from within the same directory as the dorss.php file so it can reference the include files correctly.
My knowledge on setting up a cronjob is VERY limited so I wanted to ask if this is at all possible (Change directory before running command) to do this on the same command line of the crontab or if not how can it be achieved please?
The current cronjob command is
0 0,6,12,18 * * * /usr/bin/php /var/www/vhosts/clientname/stagingsite/rss/dorss.php
TIA
John
You can change directory to the one you want and then run the php from that directory by doing this:
cd /var/www/vhosts/clientname/stagingsite/rss/
&&
/usr/bin/php dorss.php
It's easier than creating bash scripts, here is the result:
0 0,6,12,18 * * * cd /var/www/vhosts/clientname/stagingsite/rss/ && /usr/bin/php dorss.php
I don't know if there's a better solution, but I would suggest to write a bash script that changes to the correct directory before executing the PHP file, and use cron to execute this script. E.g:
#!/bin/bash
cd /Library/WebServer/Documents/clientname/siteroot/rss/
php dorss.php
Or even just:
#!/bin/bash
php /Library/WebServer/Documents/clientname/siteroot/rss/dorss.php
Save it somewhere and use cron to run that.

Cronjob not working - trying to run PHP script

I am running a cronjob that runs a PHP script to do a couple of things; first, it opens the database and stores the contents of the tables into memcache; second it creates a Javascript file that is basically a couple of arrays so that the client browser can do a lot of the work and save the server from being overloaded. This is newly added.
The script runs manually very well, and for over a year it has done its job, updating memcache every 10 minutes. The Javascript file add on is the big problem here; the cronjob s/b creating a new, updated edition of this file every 10 minutes, but appears to be not working unless I run it manually from the command line.
I can check this by doing:
ls -al id_index.js
and checking the timestamp in the file listing.
Is there some problem with creating a Javascript file from a script started by crontab?
Btw, the cronjob file entry looks like this:
# m h dom mon dow command
*/10 * * * * php /home/accountname/public_html/mc_store_arrays.php
Any and all help is appreciated.
In which directory are you expecting the javascript file to be created? It probably is being created somewhere ... wherever cron's working directory happens to be when the script runs (/root/ perhaps?). Make sure your output file is specified with an absolute path or with e.g:
file_put_contents(__DIR__ . '/id_index.js', $content);
which will create the file based on the path of the php script that's running, rather than the path from which it was executed.
Most likely you will have to specify the absolute path to the php cli interpreter, since the cron environment rarely defines a usable PATH environment variable.
Try using LYNX (just the way you use a web browser);
Example: LYNX http://www.MyDomain.Com/MyScript.php?MyParameter=MyValue&And=SoOn

How do I get a PHP file to automatically run itself?

I have a PHP file, x.php, that outputs b.xml every time it is run. The way I do this is by using crontab to run the x.php file. The problem is that due to the server's settings, the new file has permissions of 400. So I also have another crontab line to change file b.xml permissions to 777 so that x.php can run over it next time.
I feel like I am making this too complicated. Is there any way to make this a bit simpler?
Quick Answer
You'll need to chmod the file to be 777 in the x.php script.
After b.xml has been created, run this line:
chmod('path/b.xml', 0777);
Note you should always specify octals when using chmod.
A better way?
When you run a cron job, you should take special note of the user that is running the cronjob.
Generally on a shared server you will have your own login and thus the cron job runs as that user. My question to you - is that user the same as your web server? often php runs as "apache" and cron might be running as "tanner". In that case, setting b.xml to be owned by tanner, and having a permissions 400 means that only tanner can change the file.
To solve this, if you don't have access to umask, one way would be to change your cron job to run as the webserver:
su -c "php /home/jonathan/public_html/b.php" apache
This may or may not work depending if you are allowed to switch to apache as the user. do not forget to switch apache to the actual web servers username.
Now, if that doesn't work, then the alternative is to go for the 777 permissions. Keep in mind on a shared server this means anyone on that server could potentially get to that file if they knew the path.
Another way as suggested by OP:
0,10,20,30,40,50 * * * * /usr/bin/wget http://example.com/user/x.php
This way will always run as the apache (or whatever) user that apache runs as, ensuring the next time it is accessed, the file will be useable.
Ask the server admin to create a new user who owns the folder where the script writes the xml file.
Run your php script through your cron job as such user. If you run your script as the folder's owner you might change the permissions through your php script.
This should work:
// set permission
chmod('path/to/b.xml', 777);
// do other stuff
To solve this issue, I ended up just creating a cronjob such as this:
0,10,20,30,40,50 * * * * /usr/bin/wget http://example.com/user/x.php
This executed the file which created b.xml and since the user who executed the script was public, the permissions remained public as well.

PHP & cron: security issues

Whats the best way to ensure that only CRON executes PHP scripts, and not someone else who stumbled upon your php scripts..
I was thinking a Password Variable.... but is this a legal CRON command? :
/usr/local/bin/php -f /home/mysite/public_html/dir/script?password=12345
This way people cannot be able to execute the same commands when visiting the PHP script via HTTP (unless they know the password)
Thanks.
You should keep this file outside of public_html
/usr/local/bin/php -f /home/mysite/script
// is secure from public access
Suppose if u don't want anybody to run the file via http then set the cron by using php command as you are doing and add htacess to cron folder to block http request to the folder
by adding
deny from all to htacess
Suppose if u want the cron folder to be password protected then it can be done as mentioned in the URl
http://www.elated.com/articles/password-protecting-your-pages-with-htaccess/
Don't put the script inside your public_html (or anywhere under your document root) directory if you only need to execute it from cron. It really is that simple.
You can send params to a PHP file via the command line. Just not like you are thinking.
http://www.php.net/manual/en/reserved.variables.argc.php
However, you also want to keep this out of the public html folder, like the others are saying. So you CAN'T surf to them. PHP run from command line doesn't need to be in any kind of webserver watch folder.
Or you can block execution by IP
do something like this:
($_SERVER['REMOTE_ADDR'] == "127.0.0.1") or die('NO ACCESS');
Having a password could work, but :
Writing a password in your crontab is a bad idea because other local users might be able to read it
Your syntax won't work (it would try to run the script "script?password=12345". Parameters can't be named in shell script, so you would have to run "script.php 12345"
A valid solution would be to check in your PHP script, that the current environment looks like the one provided by cron when launching commands. Cron specific environment variables might help you ensure your script is being run fby cron and not a user.

Categories