-1

I have written a python script which is reading some logs and then writing the required info into a csv file.Its working fine if I execute it manually by python myscript.py .However when I m calling it through cron its not working. I have tried:

* * * * * python /path/to/myscript.py
* * * * * /path/to/myscript.py
* * * * * /usr/bin/python /path/to/myscript.py

After some failed attempts I put python myscript.py in a shell script and ran it manually,it worked but again in cron it did not.

Piku
  • 31
  • 7
  • 1
    _I have written a python script_ Where is your relevant code? – B001ᛦ Aug 19 '16 at 08:56
  • Whatever is in python script is not relevant. The problem is that the default shell for cron is not `/bin/bash` – ElmoVanKielmo Aug 19 '16 at 08:59
  • I'll assume you use some form of linux. Is your python script executable? Did you put `#!/path/to/python` in the first line? (That would probably be `#!/usr/bin/python` in your case.) – Alex Aug 19 '16 at 09:00
  • 1
    Sorry but my crystal ball is out for repair. But perhaps could you start by logging the error or whatever your script outputs so you'd have a clue about what happens ? – bruno desthuilliers Aug 19 '16 at 09:00
  • @Alex Yes I made it executable and also added the shebang line – Piku Aug 19 '16 at 09:02
  • 1
    Is there any corresponding error message in `/var/log/syslog?` – ralfg Aug 19 '16 at 09:03
  • @ElmoVanKielmo That is actually not true. If he uses relative paths, there's a chance that the script runs to a certain point but then throws an error. – deepbrook Aug 19 '16 at 09:09
  • 1
    @j4ck the difference is that `bash` sets up the environment for the user and changes directory to $HOME while in cron the default `sh` doesn't. – ElmoVanKielmo Aug 19 '16 at 09:20
  • Huh. That's interesting. Cheers, I didn't know! – deepbrook Aug 19 '16 at 09:21
  • Try set your cron job as `* * * * * /path/to/python /path/to/myscript.py 2>&1 >> /tmp/myscript.log`. Then see whether there are error messages in `/tmp/myscript.log` file after one minute. – acw1668 Aug 19 '16 at 09:45

3 Answers3

0
  • Tpye "which python" (if you are using python3 or python3.6 then you need to use which python3)
  • It will display python path : /bin/python.
  • Set value in Cron job - * * * * * /bin/python

If you want to execute python file inside the bash script by help of cronjob. you should use full path of python (Example:/bin/python /path of python file/file.py) inside of bash script.

Birendra Rawat
  • 1,307
  • 1
  • 8
  • 8
-1

Default shell for cron is not /bin/bash, so you need to give the full path to Python executable.
Check the output of which python. On my machine it's /usr/bin/python.
Assuming this, your cron job entry should be:

* * * * * /usr/bin/python /path/to/myscript.py

Sometimes you want to use virtualenv or set some environment variables or change working directory before you run the script.
In that case it's handy to create a wrapper script in bash:

#!/bin/bash
# Change working directory
cd /path/to
# Activate Python virtual environment
source bin/activate
# Set some environment variable
export LOG_FILE_PATH="/var/log/whatever.log"
# Finally run your python script
python myscript.py

Given that you save the above script to /path/to/myscript_wrapper.sh, your cron job entry will look like:

* * * * * /bin/bash /path/to/myscript_wrapper.sh
ElmoVanKielmo
  • 10,907
  • 2
  • 32
  • 46
  • Also the second solution? – ElmoVanKielmo Aug 19 '16 at 09:12
  • ..if you did try it already, you should have a log message, no? What does that say? – deepbrook Aug 19 '16 at 09:17
  • Haven't try the second approach yet. I am not exactly getting it. – Piku Aug 19 '16 at 09:20
  • Once again then. Cront is using `/bin/sh` and not `/bin/bash`. With `/bin/sh` your default environment e.g. `.bashrc` is not loaded and also the working directory is not changed to your $HOME. This always causes headache you're experiencing. Just write the bash script I'm showing you. If you aren't using virtualenv and env vars, delete lines `source bin/activate` and `export LOG_FILE_PATH="/var/log/whatever.log"`, and start this wrapper script from cron and not python script directly. – ElmoVanKielmo Aug 19 '16 at 09:24
  • `* * * * * root(username) /path/to/myscript_wrapper.sh ` will it helps?? – karthik Aug 19 '16 at 09:54
-1

Make sure that you do not use any kind of relative paths inside your python script. This can cause your script to exit with an error.

So make sure that within your script you do not use ../to/something, but instead /path/to/something.

ie

with open('../file.txt', 'r') as f:

should become

with open('/full/path/to/file.txt', 'r') as f:
deepbrook
  • 2,523
  • 4
  • 28
  • 49
  • Yeah I am using absolute path only. – Piku Aug 19 '16 at 09:13
  • 1
    Hardcoding absolute paths in Python scripts is not a good idea. Imagine you will deploy it to production server and you will see the error like `No such file or directory: /home/j4ck/...` right away, cause noramally you don't run services in production on behalf of your unix user and therefore all your service's code and relevant files will land in other directory than your home directory. – ElmoVanKielmo Aug 19 '16 at 09:17
  • 1
    True, if it were such a case I'd still not recommend `..` - rather something like `os.abspath(__file__)`, and work from that instead. But I might just be branded by past troubles I've had with this and cron jobs, and I don't have much experience with deploying to foreign systems. – deepbrook Aug 19 '16 at 09:19
  • 1
    Now you're talking. You are 100% right - `os.abspath(__file__)` is the way to go in basic setup. However if one is using deployment automation tools, then these tools are responsible for passing correct command line arguments, environment variables or configuration files, so that the actual service gets all the information about paths, remote services and so on. – ElmoVanKielmo Aug 19 '16 at 09:27