111

I'm trying to execute a Python script using the Linux crontab. I want to run this script every 10 minutes.

I found a lot of solutions and none of them worked. For example: edit the anacron at /etc/cron.d or use crontab -e. I put this line at the end of the file, but it doesn't change anything. Do I have to restart any service(s)?

*/2 * * * * /usr/bin/python /home/souza/Documets/Listener/listener.py

What file must I edit to configure this?


Here is the script.

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-

import json
import os
import pycurl
import sys
import cStringIO

if __name__ == "__main__":

    name_server_standart = "Server created by script %d"
    json_file_standart = "{ \"server\" : {  \"name\" : \"%s\", \"imageRef\" : \"%s\", \"flavorRef\" : \"%s\" } }"

    curl_auth_token = pycurl.Curl()

    gettoken = cStringIO.StringIO()

    curl_auth_token.setopt(pycurl.URL, "http://192.168.100.241:8774/v1.1")
    curl_auth_token.setopt(pycurl.POST, 1)
    curl_auth_token.setopt(pycurl.HTTPHEADER, ["X-Auth-User: cpca",
                          "X-Auth-Key: 438ac2d9-689f-4c50-9d00-c2883cfd38d0"])

    curl_auth_token.setopt(pycurl.HEADERFUNCTION, gettoken.write)
    curl_auth_token.perform()
    chg = gettoken.getvalue()

    auth_token = chg[chg.find("X-Auth-Token: ")+len("X-Auth-Token: ") : chg.find("X-Server-Management-Url:")-1]

    token = "X-Auth-Token: {0}".format(auth_token)
    curl_auth_token.close()

    #----------------------------

    getter = cStringIO.StringIO()
    curl_hab_image = pycurl.Curl()
    curl_hab_image.setopt(pycurl.URL, "http://192.168.100.241:8774/v1.1/nuvemcpca/images/7")
    curl_hab_image.setopt(pycurl.HTTPGET, 1) #tirei essa linha e funcionou, nao sei porque
    curl_hab_image.setopt(pycurl.HTTPHEADER, [token])

    curl_hab_image.setopt(pycurl.WRITEFUNCTION, getter.write)
    #curl_list.setopt(pycurl.VERBOSE, 1)
    curl_hab_image.perform()
    curl_hab_image.close()

    getter = cStringIO.StringIO()

    curl_list = pycurl.Curl()
    curl_list.setopt(pycurl.URL, "http://192.168.100.241:8774/v1.1/nuvemcpca/servers/detail")
    curl_list.setopt(pycurl.HTTPGET, 1) #tirei essa linha e funcionou, nao sei porque
    curl_list.setopt(pycurl.HTTPHEADER, [token])

    curl_list.setopt(pycurl.WRITEFUNCTION, getter.write)
    #curl_list.setopt(pycurl.VERBOSE, 1)
    curl_list.perform()
    curl_list.close()

    #----------------------------

    resp = getter.getvalue()

    con = int(resp.count("status"))

    s = json.loads(resp)

    lst = []

    for i in range(con):
        lst.append(s['servers'][i]['status'])

    for j in range(len(lst)):
        actual = lst.pop()
        print actual

        if actual != "ACTIVE" and actual != "BUILD" and actual != "REBOOT" and actual != "RESIZE":

            print "Entra no If"

            f = file('counter', 'r+w')

            num = 0
            for line in f:
                num = line

            content = int(num)+1

            ins = str(content)

            f.seek(0)
            f.write(ins)
            f.truncate()
            f.close()

            print "Contador"

            json_file = file('json_file_create_server.json','r+w')

            name_server_final = name_server_standart % content
            path_to_image = "http://192.168.100.241:8774/v1.1/nuvemcpca/images/7"
            path_to_flavor = "http://192.168.100.241:8774/v1.1/nuvemcpca/flavors/1"

            new_json_file_content = json_file_standart % (name_server_final, path_to_image, path_to_flavor)

            json_file.seek(0)
            json_file.write(new_json_file_content)
            json_file.truncate()
            json_file.close()

            print "Json File"

            fil = file("json_file_create_server.json")
            siz = os.path.getsize("json_file_create_server.json")

            cont_size = "Content-Length: %d" % siz
            cont_type = "Content-Type: application/json"
            accept = "Accept: application/json"

            c_create_servers = pycurl.Curl()

            logger = cStringIO.StringIO()

            c_create_servers.setopt(pycurl.URL, "http://192.168.100.241:8774/v1.1/nuvemcpca/servers")

            c_create_servers.setopt(pycurl.HTTPHEADER, [token, cont_type, accept, cont_size])

            c_create_servers.setopt(pycurl.POST, 1)

            c_create_servers.setopt(pycurl.INFILE, fil)

            c_create_servers.setopt(pycurl.INFILESIZE, siz)

            c_create_servers.setopt(pycurl.WRITEFUNCTION, logger.write)

            print "Teste perform"

            c_create_servers.perform()

            print logger.getvalue()

            c_create_servers.close()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
guisantogui
  • 4,017
  • 9
  • 49
  • 93
  • When you say "it doesn't change anything". Does it show an error, does it not run? What is the behaviour? – Raul Marengo Jan 04 '12 at 15:47
  • is "Documets" instead of "Documents" intentional? – Raul Marengo Jan 04 '12 at 15:48
  • Simply doesn't occurs anything. :( – guisantogui Jan 04 '12 at 15:53
  • This sort of goes beyond the scope of the question but, what do you expect your "listener.py" script to do? Does it do anything that could indicate that it has run? Do ps -ef | grep 'crond' in your command line to check if cron is running. – Raul Marengo Jan 04 '12 at 15:57
  • No, this script send several cURL's commands to another computer. When I execute the "ps -f | grep 'crond'", it returns this: "souza 4736 3947 0 14:01 pts/1 00:00:00 grep --color=auto crond" – guisantogui Jan 04 '12 at 16:00
  • Well, make it do something that allows you to know that it has run like write a log file or send you an email. Try also running /usr/bin/python /home/souza/Documets/Listener/listener.py manually and see if it works. – Raul Marengo Jan 04 '12 at 16:02
  • i've tried make an echo, but it doesn't work! :/ – guisantogui Jan 04 '12 at 16:04
  • if you made it print and it doesn't work when you run it manually, then the problem is in the script and it's something you are going to have to post as a separate question. You won't see an echo from cron, when cron runs a task it runs it in it's own instance and you won't see any output from it. – Raul Marengo Jan 04 '12 at 16:05
  • No No, i put the echo at crontab like a task, if i run the script manually, it works. – guisantogui Jan 04 '12 at 16:08
  • Surprisingly you may not be running cron. Try /etc/init.d/crond start and then check the processes as before – Raul Marengo Jan 04 '12 at 16:08
  • Wow, when i try run this command return this: "sudo: /etc/init.d/crond: command not found" – guisantogui Jan 04 '12 at 16:11
  • Looks like the cron doesn't exists! – guisantogui Jan 04 '12 at 16:12
  • Do a "locate crond" or a "find / -name 'crond' . What OS are you running this on? – Raul Marengo Jan 04 '12 at 16:14
  • Ubuntu 11.04, and I can't find the "crond" – guisantogui Jan 04 '12 at 16:17
  • Well thats weird, i try to install the cron, but it returns that cron already is installed! But, i search by cron.d and i find some files, could be these files? – guisantogui Jan 04 '12 at 16:21
  • it can also be found in /usr/sbin/crond or just type crond and see what you get. – Raul Marengo Jan 04 '12 at 16:23
  • No, searching "cron.d" I got results only at etc directory – guisantogui Jan 04 '12 at 16:26
  • "crond" I don't retrieve anyone result running locate crond – guisantogui Jan 04 '12 at 16:31
  • Have a look at this post: http://serverfault.com/questions/103482/where-is-this-cron-job-running-from – Raul Marengo Jan 04 '12 at 16:38
  • Ok, i found an cron at /usr/sbin, but how can i configure that? – guisantogui Jan 04 '12 at 16:52
  • You already have, start by running /usr/sbin/crond and see if you script starts working. Afterwards, do chkconfig crond on to ensure crond runs on boot. Let me remind you that you have stretched the scope of this question and this should be answered on serverfault. – Raul Marengo Jan 04 '12 at 16:58
  • I've resolved the cron problem, but is occurring a strange problem, my script no executes completely, it stops at middle when i've to send some curl commands, I'll edit the topic with the source code. – guisantogui Jan 05 '12 at 11:24
  • I would suggest you close this question as it has been answered and you start a new one with this particular issue. Share the link in the comment and I will have a look. – Raul Marengo Jan 05 '12 at 11:40
  • Why are you updating this question (without adding anything significant) more than two years after asking it? – Maël Nison Aug 08 '14 at 16:37
  • Because I want to improve, in visual aspect, question quality – guisantogui Aug 08 '14 at 16:40
  • More concise `cron` troubleshooting tips: https://stackoverflow.com/questions/22743548/cronjob-not-running – tripleee Oct 12 '20 at 14:54

3 Answers3

161

Just use crontab -e and follow the tutorial here.

Look at point 3 for a guide on how to specify the frequency.

Based on your requirement, it should effectively be:

*/10 * * * * /usr/bin/python script.py
Luke Singham
  • 1,536
  • 2
  • 20
  • 38
Raul Marengo
  • 2,287
  • 1
  • 15
  • 10
  • 1
    I follow this tutorial, but when i save the file appears a message: "/tmp/crontab.JTQ0My/crontab":22: bad minute errors in crontab file, can't install. Do you want to retry the same edit? (y/n)" if I type "y", I've returned to file edit. And if I type "n" the file is not saved. I add this line at last line of the file: "/1 * * * * /usr/bin/python script.py" – guisantogui Jan 04 '12 at 13:56
  • @guisantogui there is a point in the tutorial that explains that using "/1" might not be supported by all operating systems. What operating system are you running this on? – Raul Marengo Jan 04 '12 at 14:02
  • 3
    @guisantogui just noticed you are missing a "*" before the "/" – Raul Marengo Jan 04 '12 at 14:03
  • another way is to add an env declaration in your script.py. See my comments to the accepted solution at: http://stackoverflow.com/questions/25633737/python-crontab-and-paths – Quetzalcoatl Sep 03 '14 at 14:56
  • What if you want to execute the `script.py` only in the given directory? – Shubham A. Jan 03 '18 at 10:09
  • Have you tried adding the full path to the file or look at the solution from greenqy below. – Raul Marengo Jan 07 '18 at 22:26
  • I want to run a python file and my project has a virtual environment(venv). Python interpreter also is inside of venv. How can I run that file? – Sashini Hettiarachchi Jan 30 '19 at 14:49
  • Have you had a look at https://stackoverflow.com/questions/3287038/cron-and-virtualenv ? – Raul Marengo Jan 31 '19 at 16:15
  • Can you take a look here: https://stackoverflow.com/questions/65586171/how-to-set-crontab-in-order-to-run-multiple-python-and-a-shell-scripts ? – Devilhorn Jan 05 '21 at 20:39
77

Put your script in a file foo.py starting with

#!/usr/bin/python

Then give execute permission to that script using

chmod a+x foo.py

and use the full path of your foo.py file in your crontab.

See documentation of execve(2) which is handling the shebang.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    @Tomer If they are POSIX `sh` shell scripts then yes. If they use nonstandard features specific to `ksh`, `zsh`, or `bash` then they need to be run using that specific shell. – tripleee Jul 22 '18 at 13:58
40

As you have mentioned it doesn't change anything.

First, you should redirect both standard input and standard error from the crontab execution like below:

*/2 * * * * /usr/bin/python /home/souza/Documets/Listener/listener.py > /tmp/listener.log 2>&1

Then you can view the file /tmp/listener.log to see if the script executed as you expected.

Second, I guess what you mean by change anything is by watching the files created by your program:

f = file('counter', 'r+w')
json_file = file('json_file_create_server.json', 'r+w')

The crontab job above won't create these file in directory /home/souza/Documets/Listener, as the cron job is not executed in this directory, and you use relative path in the program. So to create this file in directory /home/souza/Documets/Listener, the following cron job will do the trick:

*/2 * * * * cd /home/souza/Documets/Listener && /usr/bin/python listener.py > /tmp/listener.log 2>&1

Change to the working directory and execute the script from there, and then you can view the files created in place.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
greenqy
  • 656
  • 7
  • 7