3

I would like to ask for help with the python-crontab module. I have a simple shell script to record an internet radio stream using the curl command. I want to schedule recordings ahead by scheduling them in a crontab. I found the python-crontab module that alows me to write directly to crontab. But each time I schedule a new recording the older crontab entry is over-written. Is it possible to write persistant crontab entries using the python-crontab?

I simplified my code to demonstrate my problem:


from crontab import CronTab

def get_recording_parameters(Min,Hour,day,month,job_number):
    radio_cron = CronTab()
    cmd = "sh /home/pifik/Documents/record_radio.sh"
    cron_job = radio_cron.new(cmd, comment='job_'+str(job_number))
    cron_job.setall(Min, Hour, day, month, None)   
    radio_cron.write()

If I run it with the following parameters: get_recording_parameters(0,22,23,12,1), and check the crontab in Terminal with the crontab -l command I get 0 22 23 12 * sh /home/pifik/Documents/record_radio.sh # job_1. If I run it again with different parameters, for example: get_recording_parameters(10,23,25,12,2) and check the crontab with crontab -l I get 10 23 25 12 * sh /home/pifik/Documents/record_radio.sh # job_2, the job 1 is overwritten.

I tried to change the 3rd line of code to radio_cron = CronTab(tabfile='/home/pifik/Documents/filename.tab') and it helps that all new entries are appended in the filename.tab but nothing is written to the crontab. I am running Ubuntu 14.04 and Python 3.4.3.

Pifik
  • 43
  • 1
  • 7

3 Answers3

1

It looks like each time you add a job and write it back out it's overwriting what was already in the crontab. I read the documentation and I can't make heads or tails out of it. It seems you should be able to read in what was already there and add to it but for the life of me I can't figure out how from the docs.

You can get around that issue by re-working it as a class that puts together all the jobs before it writes them back out. Of course that paints you into the same corner you're already in which is appending doesn't work (unless you lay in the old entries again before writing):

#!/home/sklassen/py/try-pycrontab/env/bin/python
from crontab import CronTab

class CronSet:
    def __init__(self):
        self._crontab = CronTab()

    def add_job(self, min, hour, day, month, job_number):
        cmd = "sh /home/pifik/Documents/record_radio.sh"
        job = self._crontab.new(cmd, comment='job'+str(job_number))
        job.setall(min, hour, day, month, None)

    def save(self):
        self._crontab.write()


def main():
    c = CronSet()
    c.add_job(0, 22, 23, 12, 1)
    c.add_job(0, 23, 23, 12, 2)
    c.save()

if __name__ == '__main__':
    main()


# running 'crontab -l' produces the following
# 0 22 23 12 * sh /home/pifik/Documents/record_radio.sh # job1
# 0 23 23 12 * sh /home/pifik/Documents/record_radio.sh # job2
1

I modified Steven's code to make it work for me. In order not to lose the previously scheduled crontab jobs I create a cron_jobs.txt file and copy all existing scheduled jobs from crontab to cron_jobs.txt with the subprocess call "crontab -l > /home/pifik/Documents/cron_jobs.txt". Every time I do it I overwrite everything in the file. Then I create a new recording job and append it to the cron_jobs.txt file. After that I overwrite the crontab by running "subprocess.call('crontab /home/pifik/Documents/cron_jobs.txt', shell=True)".

This is a workaround to make it work but I am still interested to know if it is possible to use the python-crontab module to append new jobs directly without the need for the cron_jobs.txt file. Arguably, the way I do it now, it could be also done without the module but the module makes it easier for me to further manage the jobs by activating or deactivating them and deleting the expired jobs. I will put some tkinter GUI on it and I'll be done for now.

import subprocess
from crontab import CronTab

class CronSet:
    def __init__(self):
        self._crontab = CronTab(tabfile="/home/pifik/Documents/cron_jobs.txt")

    def add_job(self, minute, hour, day, month, title):
        subprocess.call('crontab -l > /home/pifik/Documents/cron_jobs.txt', shell=True)        
        choice=input('''1. Cesky Rozhlas 1
2. Cesky Rozhlas 2
Enter your choice (1 or 2):  ''') 
        length = int(input("Enter the length of recording in minutes: "))*60
        if choice ==str(1):
            stream = "http://amp.cesnet.cz:8000/cro1-256.ogg"
        else:
            stream = "http://amp.cesnet.cz:8000/cro2-256.ogg"
    cmd = "curl %s -m %i -o /home/pifik/Documents/Recordings/%s.ogg" %(stream, length, title)
        job = self._crontab.new(cmd, comment=title)
        job.setall(minute, hour, day, month, None)

    def save(self):
        self._crontab.write()

def main():
    c = CronSet()
    month = input("Enter month(1-12): ")
    day = input("Enter day(1-31): ")
    hour = input("Enter hour(0-24): ")
    minute = input("Enter minute(0-59): ")
    title = input("Enter title of recording: ")
    c.add_job(minute, hour, day, month, title)
    c.save()
    subprocess.call('crontab /home/pifik/Documents/cron_jobs.txt', shell=True)

if __name__ == '__main__':
    main()
Siyual
  • 16,415
  • 8
  • 44
  • 58
Pifik
  • 43
  • 1
  • 7
0

The issue is that you haven't specified any user or filename for CronTab to load from. So it doesn't. The bug is that it writes out the empty crontab to the user by default, even if you don't specify the user.

The existing documentation says:

from crontab import CronTab
empty_cron    = CronTab()
my_user_cron  = CronTab(user=True)
users_cron    = CronTab(user='username')

Which is correct in that you're making an empty crontab. So I've gone ahead and committed a fix and a test to make sure it causes an error if you try and write an empty_cron without specifying the user or filename.

Please add user=True to your code to make it work as you expect.