César César - 27 days ago 5
Python Question

Fabric not working with cron job

I'm trying to run a deploy script using pexpect and Fabric. This is what is happening:

$ crontab -l
# m h dom mon dow command
30 04 * * * /bin/bash /home/pedregal/Deploy/deploy.sh

$ ls -l
total 20
-rwxrwxr-- 1 pedregal pedregal 239 Nov 11 09:00 deploy.sh
-rw-rw-r-- 1 pedregal pedregal 271 Nov 9 21:33 expectfile.py
-rw-rw-r-- 1 pedregal pedregal 900 Nov 10 07:28 fabfile.py


deploy.sh (I'm a total shell scripting newbie, bear with me)

#!/bin/bash

EXPECT_FILE=/home/pedregal/Deploy/expectfile.py
LOG_FILE=/home/pedregal/Deploy/deploy.log

touch $LOG_FILE
python $EXPECT_FILE > $LOG_FILE 2>&1
mail -s "Auto-update log" cbustios@elpedregalsa.com < $LOG_FILE


expectfile.py

# -*- coding: utf-8 -*-
import pexpect
import sys

child = pexpect.spawn('fab piura deploy', echo=False)
child.logfile = sys.stdout
child.expect('user:')
child.sendline('cesarbustios')
child.expect('password:')
child.sendline('************')
child.expect(pexpect.EOF)


fabfile.py

# -*- coding: utf-8 -*-
from __future__ import with_statement
import os
from os.path import join, dirname

from dotenv import load_dotenv
from fabric.api import cd, env, prefix, run, sudo, warn_only


DOTENV_PATH = join(dirname(__file__), '.env')
GESTAGRO_PATH = '/home/pedregal/Projects/gestagro/gestagro/'
VENV_PATH = '/home/pedregal/Environments/gestagro/venv/bin/activate'
ACTIVATE_VENV = 'source %s' % (VENV_PATH)
load_dotenv(DOTENV_PATH)


def piura():
env.hosts = [
'pedregal@192.168.5.20:22',
]
env.passwords = {
'pedregal@192.168.5.20:22': os.environ.get('PASSWORD_PIURA'),
}


def deploy():
with cd(GESTAGRO_PATH), prefix(ACTIVATE_VENV), warn_only():
run('hg pull -u')
run('python manage.py migrate --no-color')
run('python manage.py collectstatic --noinput --no-color')
sudo('nginx -s reload')
sudo('supervisorctl restart gestagro')


If I run
deploy.sh
manually it runs perfectly fine, however, I'm receiving an email with the following traceback from the cron job:

Traceback (most recent call last):
File "/home/pedregal/Deploy/expectfile.py", line 5, in <module>
child = pexpect.spawn('fab piura deploy', echo=False)
File "/usr/local/lib/python2.7/dist-packages/pexpect/pty_spawn.py", line 194, in __init__
self._spawn(command, args, preexec_fn, dimensions)
File "/usr/local/lib/python2.7/dist-packages/pexpect/pty_spawn.py", line 267, in _spawn
'executable: %s.' % self.command)
pexpect.exceptions.ExceptionPexpect: The command was not found or was not executable: fab.


I thought the installation of Fabric was system-wide, what am I missing?

Answer

A cronjob doesn't run load .bash_profile nor your .bashrc, these are source'd by your shell. But cron does not run through your shell so you have to setup the required environment variables (e.g. PATH) manually from the running script.