Search code examples
pythoncronfabricpexpect

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" [email protected] < $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 = [
        '[email protected]:22',
    ]
    env.passwords = {
        '[email protected]: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?


Solution

  • 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.