Set the working directory for PHP scripts that run via cron

There are fundamental differences between PHP scripts that are run by a web request, and those that are run from the command line. One of the main ones is that the environment settings will be completely different, including the path. Every few years I forget this and it comes back to bite me.

Generally I use relative paths for require_once() and similar functions. This is because it makes the code more portable when moving to a different storage location or a different server (e.g. working with development and live servers). The downside is that the relative paths are likely to point to completely the wrong location for scripts that are called via the command line. There are various reasons for wanting to run PHP scripts on the command line, one of the most common being for cron jobs. Of course they can be run using wget or curl or suchlike, but that causes extra overhead with the web server, not to mention potential problems with timeouts and so on.

To avoid this kind of problem, when writing a script that will be run as a cron job, I now always put the following code at the top:

chdir( __DIR__ );

This changes the current working directory to the path of the script, which means that require_once() will work as expected. In addition, I strongly recommend writing cron scripts that do not produce any output unless there is an error, and making sure that your cron settings will notify you by email of any output produced. This follows standard best practice guidelines for cron jobs. It always surprises me how many cron jobs I see where the author couldn’t be bothered to differentiate between correct behaviour and errors, and then redirects all output to /dev/null because they are sick of being bombarded with emails.

Comments

I had a problem related to this and your suggestion of the chdir at the top solved it. Thanks very much!

Christopher Brown - Sat, 26/11/2022 - 10:18

Permalink

Can understand switching to current directory to run scripts / includes within one folder ... but what about when you need to access folders OUTSIDE of the current directory? Let's say I am in "/cgi-bin/sales/sales_cron.php", and now wish to access a file in "/cgi-bin/track/data/this,dat"

Offline testing, I used "getCWD", and then broke it apart / reconstructed to get back to cgi-bin (/home/domain/cgi-bin/). I then append that to the other file ("/home/domain/cgi-bin/"."track/data/this.dat") ... but not sure if "getCWD" will work like this on CRON

Or should I use some other method?

Hi Christopher,

This depends a bit on how your code is structured, and particularly how the different folders are related. One option would be to use a configuration variable to specify where the file(s) are located. Another one would be something like this:

$dir = realpath(__DIR__ . '/../track/data/this.dat');

My preference is to use a configuration variable when the data is from a separate source, and the __DIR__ method when it's part of the same source tree, because in that case you can be fairly sure that the relative structure will remain the same between deployments.

Hope that helps!

Add new comment

CAPTCHA