Pixelastic

You can cut our wings but we will always remember what it was like to fly.

Posts tagged with "shell"

Running a cakePHP shell script as cronjob on Dreamhost

Dreamhost as a wonderful wiki on how to set cron jobs and cakePHP has a cookbook page on how to do it too, but getting it just right was a little frustrating.

I finally managed to run my shell task as a cronjob, and here is how I did it.

The magic command

First, here is the command I wrote in my Dreamhost panel :

/home/username/domain.com/cake/console/cake -app /home/username/domain.com/app/ shell_name

You have to set the full path to the cake console because it obviously is not in the pre-saved paths on a default Dreamhost install.

You also have to specify the app directory otherwise cake will search your shell in the wrong directories. This is even more important if your shell is located in a plugin directory.

But, this won't work as-is, you'll have to do several other stuff, mostly explained by Miles Johnson, but I'll recap them

Setting the file as executable

You have to set the cake/console/cake file as executable. It is kind of obvious, but you have to do it anyway.

Set the TERM variable

Update you cake/console/cake to replace the first lines with :

LIB=${0/%cake/}
APP='pwd'
TERM=linux
export TERM

If you don't, you'll have notice errors in the resulting log. No big deal, but it is cleaner that way.

Forcing using php5

While in command line, the php command refer to the php4 version. If you need to use php5 (and I guess you should), you would have to manually reference the binary file. Hence, you have to update your cake/console/cake file one more time and change the exec line to :

exec /usr/local/php5/bin/php -q ${LIB}cake.php -working "${APP}" "$@"

And it's ok

Your cronjob should not work effortlessly. It took me some long hours to track all this down (along with other issues on my local dev machine that make debugging even more cloudy).

Knowing dev from prod in a cakePHP shell

I wrote a cakePHP shell to synchronize an IMAP mailbox with a mysql table. I wanted to test my shell on local first, then upload it and make a CRON job of it.

Whenever I tried to run the shell from my development environment I was greeted with various "Database table is missing" messages.

After some digging, it occurs that the shell was connecting to my prod database, not the dev one.

The culprit

I wrote a little snippet to automatically switch to the correct database based on the current server name. If it was localhost, I used the $dev credentials, while keeping the $default credentials for other cases (ie. production).

This worked great and I added this little code to my database.php file.

But when running a shell, the env('SERVER_ADDR') was empty, thus my test was always selecting the prod database.

I couldn't find anyway to guess if I was running a shell from prod or dev. I sure had access to a lot of config informations through env and $_SERVER but none seemed to be enough to guess the correct environment.

Solution

I finally decided that the only way was to manually pass a flag to my shell call to tell if it was to use the dev or prod credentials.

I decided that adding a dev arg to the shell call will switch to dev mode, while not adding it will use production mode.

My final shell call looked like : cake -app "path/to/app" mail_import dev

And I added the following logic in my database switching logic :

// Defining the Environment (prod or dev)
if (defined('CAKEPHP_SHELL')) {
// Based on the prod/dev flag
$args = env('argv');
$environment = 'prod';
foreach($args as $flag) {
if ($flag=='dev') {
$environment = 'dev';
break;
}
}
} else {
// Based on the server url
$environment = (env('SERVER_ADDR')=='127.0.0.1') ? 'dev' : 'prod';
}

Note that I checked if the script was accessed through normal server/php delegation or through the CLI using defined('CAKEPHP_SHELL')