diff options
-rw-r--r-- | .SRCINFO | 14 | ||||
-rw-r--r-- | PKGBUILD | 52 | ||||
-rwxr-xr-x | systemd-crontab-generator | 301 |
3 files changed, 42 insertions, 325 deletions
@@ -1,26 +1,26 @@ pkgbase = systemd-crontab-generator pkgdesc = systemd generator to generate timers/services from crontab and anacrontab files - pkgver = 0.8 + pkgver = 0.9.0 pkgrel = 1 - url = https://github.com/kstep/systemd-crontab-generator - arch = any + url = https://github.com/systemd-cron/systemd-crontab-generator + arch = i686 + arch = x86_64 license = GPL3 + makedepends = rust depends = python2 depends = systemd provides = cron provides = anacron replaces = cron replaces = anacron - source = systemd-crontab-generator + source = https://github.com/systemd-cron/systemd-crontab-generator/archive/master.zip source = systemd-crontab-update - source = cron.target source = crontab source = systemd-crontab-generator.1 source = crontab.1 source = crontab.5 - md5sums = 3e6e2fb5bf3a6f05cacfbbb113516026 + md5sums = 35e308952f6e4f7d80c50d83ba981c2a md5sums = 6f00710ad710e319b52edef3e98bd010 - md5sums = 97450f27b69a1e88f1b21faad403df7c md5sums = 4ac2cfc8de6dabf2e08f39b3c3557879 md5sums = 15acf6fd2a9533c13ce21c6e03210194 md5sums = d863925d682395cef72701725f180884 @@ -1,42 +1,60 @@ # Maintainer: Konstantin Stepanov <me@kstep.me> pkgname=systemd-crontab-generator -pkgver=0.8 +pkgver=0.9.0 pkgrel=1 pkgdesc="systemd generator to generate timers/services from crontab and anacrontab files" -url="https://github.com/kstep/systemd-crontab-generator" -arch=('any') +url="https://github.com/systemd-cron/systemd-crontab-generator" +arch=('i686' 'x86_64') license=('GPL3') depends=('python2' 'systemd') +makedepends=('rust') provides=('cron' 'anacron') replaces=('cron' 'anacron') -source=(systemd-crontab-generator - systemd-crontab-update - cron.target - crontab - systemd-crontab-generator.1 - crontab.1 - crontab.5) -md5sums=('3e6e2fb5bf3a6f05cacfbbb113516026' +source=('https://github.com/systemd-cron/systemd-crontab-generator/archive/master.zip' + 'systemd-crontab-update' + 'crontab' + 'systemd-crontab-generator.1' + 'crontab.1' + 'crontab.5') +md5sums=('35e308952f6e4f7d80c50d83ba981c2a' '6f00710ad710e319b52edef3e98bd010' - '97450f27b69a1e88f1b21faad403df7c' '4ac2cfc8de6dabf2e08f39b3c3557879' '15acf6fd2a9533c13ce21c6e03210194' 'd863925d682395cef72701725f180884' 'f5e92c03bcb37acd580e2e27f5facc6a') +prepare() { + RUSTVER=$(rustc --version | awk '{ print $2 }') + if [[ -n "$RUSTVER" && ("$RUSTVER" < "1.3.0") ]]; then + error "Rust nightly is required to build this package." + error "Possible ways to get Rust nightly:" + error " - AUR package 'rust-nightly-bin'," + error " - AUR package 'multirust', and then choose" + error " nightly channel with 'multirust default nightly' command," + error " - from official site: http://www.rust-lang.org/install.html." + return 1 + fi +} + build() { - echo + cd "$srcdir/systemd-crontab-generator-master" + make release } package() { - install --mode=0755 -D systemd-crontab-generator ${pkgdir}/usr/lib/systemd/system-generators/systemd-crontab-generator + cd "$srcdir/systemd-crontab-generator-master" + make install PREFIX="$pkgdir/usr" + + cd "$srcdir/" install --mode=0644 -D systemd-crontab-generator.1 ${pkgdir}/usr/share/man/man1/systemd-crontab-generator.1 gzip ${pkgdir}/usr/share/man/man1/systemd-crontab-generator.1 - install --mode=0755 -D systemd-crontab-update ${pkgdir}/usr/bin/systemd-crontab-update - install --mode=0644 -D cron.target ${pkgdir}/usr/lib/systemd/system/cron.target - install --mode=0755 -D crontab ${pkgdir}/usr/bin/crontab + install --mode=0644 -D crontab.1 ${pkgdir}/usr/share/man/man1/crontab.1 gzip ${pkgdir}/usr/share/man/man1/crontab.1 + install --mode=0644 -D crontab.5 ${pkgdir}/usr/share/man/man5/crontab.5 gzip ${pkgdir}/usr/share/man/man5/crontab.5 + + install --mode=0755 -D systemd-crontab-update ${pkgdir}/usr/bin/systemd-crontab-update + install --mode=0755 -D crontab ${pkgdir}/usr/bin/crontab } diff --git a/systemd-crontab-generator b/systemd-crontab-generator deleted file mode 100755 index 0f6408b516e9..000000000000 --- a/systemd-crontab-generator +++ /dev/null @@ -1,301 +0,0 @@ -#!/usr/bin/python2 -import sys -import pwd -import os -import re - -def files(dirname): - try: - return filter(os.path.isfile, map(lambda f: os.path.join(dirname, f), os.listdir(dirname))) - except OSError: - return [] - -envvar_re = re.compile(r'^([A-Za-z_0-9]+)\s*=\s*(.*)$') - -CRONTAB_FILES = ['/etc/crontab'] + files('/etc/cron.d') -ANACRONTAB_FILES = ['/etc/anacrontab'] -USERCRONTAB_FILES = files('/var/spool/cron') - -TARGER_DIR = sys.argv[1] -TIMERS_DIR = os.path.join(TARGER_DIR, 'cron.target.wants') -SELF = os.path.basename(sys.argv[0]) - -MINUTES_SET = range(0, 60) -HOURS_SET = range(0, 24) -DAYS_SET = range(0, 32) -DOWS_SET = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] -MONTHS_SET = range(0, 13) - -ROOT_USER = pwd.getpwnam('root') - -try: - os.makedirs(TIMERS_DIR) -except OSError as e: - if e.errno != os.errno.EEXIST: - raise - -def parse_crontab(filename, withuser=True, monotonic=False): - basename = os.path.basename(filename) - environment = { - 'SHELL': '/bin/sh', - 'PATH': '/usr/bin:/bin', - } - with open(filename, 'r') as f: - for line in f.readlines(): - if line.startswith('#'): - continue - - line = line.rstrip('\n') - envvar = envvar_re.match(line) - if envvar: - environment[envvar.group(1)] = envvar.group(2) - continue - - parts = line.split() - line = ' '.join(parts) - - if monotonic: - if len(parts) < 4: - continue - - period, delay, jobid = parts[0:3] - command = ' '.join(parts[3:]) - period = { - '1': 'daily', - '7': 'weekly', - '@midnight': 'daily' - }.get(period, None) or period.lstrip('@') - - environment['LOGNAME'] = environment['USER'] = 'root' - environment['HOME'] = ROOT_USER.pw_dir - yield { - 'e': ' '.join('"%s=%s"' % kv for kv in environment.iteritems()), - 's': environment['SHELL'], - 'l': line, - 'f': filename, - 'p': period, - 'd': delay, - 'j': jobid, - 'c': command, - 'u': 'root' - } - - else: - if line.startswith('@'): - if len(parts) < 2: - continue - - period = parts[0] - period = { - '1': 'daily', - '7': 'weekly', - '@midnight': 'daily' - }.get(period, None) or period.lstrip('@') - - user, command = (parts[1], ' '.join(parts[2:])) if withuser else (basename, ' '.join(parts[1:])) - - environment['LOGNAME'] = environment['USER'] = user - environment['HOME'] = pwd.getpwnam(user).pw_dir - - yield { - 'e': ' '.join('"%s=%s"' % kv for kv in environment.iteritems()), - 's': environment['SHELL'], - 'l': line, - 'f': filename, - 'p': period, - 'u': user, - 'c': command - } - else: - if len(parts) < 6 + int(withuser): - continue - - minutes, hours, days = parts[0:3] - months, dows = parts[3:5] - user, command = (parts[5], ' '.join(parts[6:])) if withuser else (basename, ' '.join(parts[5:])) - - environment['LOGNAME'] = environment['USER'] = user - environment['HOME'] = pwd.getpwnam(user).pw_dir - - yield { - 'e': ' '.join('"%s=%s"' % kv for kv in environment.iteritems()), - 's': environment['SHELL'], - 'l': line, - 'f': filename, - 'm': parse_time_unit(minutes, MINUTES_SET), - 'h': parse_time_unit(hours, HOURS_SET), - 'd': parse_time_unit(days, DAYS_SET), - 'w': parse_time_unit(dows, DOWS_SET, dow_map), - 'M': parse_time_unit(months, MONTHS_SET, month_map), - 'u': user, - 'c': command - } - -def parse_time_unit(value, values, mapping=int): - if value == '*': - return ['*'] - return sorted(list(reduce(lambda a, i: a.union(set(i)), map(values.__getitem__, - map(parse_period(mapping), value.split(','))), set()))) - -def month_map(month): - try: - return int(month) - except ValueError: - return ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'nov', 'dec'].index(month.lower()[0:3]) + 1 - -def dow_map(dow): - try: - return ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'].index(dow[0:3].lower()) - except ValueError: - return int(dow) % 7 - -def parse_period(mapping=int): - def parser(value): - try: - range, step = value.split('/') - except ValueError: - value = mapping(value) - return slice(value, value + 1) - - if range == '*': - return slice(None, None, int(step)) - - try: - start, end = range.split('-') - except ValueError: - return slice(mapping(range), None, int(step)) - - return slice(mapping(start), mapping(end), int(step)) - - return parser - -def generate_timer_unit(job, seq): - n = next(seq) - unit_name = "cron-%s-%s" % (job['u'], n) - - if 'p' in job: - if job['p'] == 'reboot': - schedule = 'OnBootSec=%sm' % job.get('d', 5) - else: - try: - schedule = 'OnCalendar=*-*-1/%s 0:%s:0' % (int(job['p']), job.get('d', 0)) - except ValueError: - schedule = 'OnCalendar=%s' % job['p'] - - accuracy = job.get('d', 1) - - else: - dows = ','.join(job['w']) - dows = '' if dows == '*' else dows + ' ' - - schedule = 'OnCalendar=%s*-%s-%s %s:%s:00' % (dows, ','.join(map(str, job['M'])), - ','.join(map(str, job['d'])), ','.join(map(str, job['h'])), ','.join(map(str, job['m']))) - accuracy = 1 - - with open('%s/%s.timer' % (TARGER_DIR, unit_name), 'w') as f: - f.write('''# Automatically generated by %s -# Source crontab: %s - -[Unit] -Description=[Cron] "%s" -PartOf=cron.target -RefuseManualStart=true -RefuseManualStop=true - -[Timer] -Unit=%s.service -Persistent=true -AccuracySec=%sm -%s -''' % (SELF, job['f'], job['l'], unit_name, accuracy, schedule)) - - try: - os.symlink('%s/%s.timer' % (TARGER_DIR, unit_name), '%s/%s.timer' % (TIMERS_DIR, unit_name)) - except OSError as e: - if e.errno != os.errno.EEXIST: - raise - - with open('%s/%s.service' % (TARGER_DIR, unit_name), 'w') as f: - f.write('''# Automatically generated by %s -# Source crontab: %s - -[Unit] -Description=[Cron] "%s" -RefuseManualStart=true -RefuseManualStop=true - -[Service] -Type=oneshot -User=%s -Environment=%s -ExecStart=%s -c '%s' -''' % (SELF, job['f'], job['l'], job['u'], job['e'], job['s'], job['c'])) - - return '%s.timer' % unit_name - -def generate_path_unit(): - combinedcronfiles = [ '/etc/crontab', '/etc/cron.d', '/etc/anacrontab', '/var/spool/cron' ] - with open('%s/systemd-crontab-update.path' % (TARGER_DIR), 'w') as f: - f.write('''# Automatically generated by %s - -[Unit] -Description=[Cron] Update cron units -RefuseManualStart=true -RefuseManualStop=true - -[Path] -%s -''' % (SELF,'\n'.join([ "PathChanged="+f for f in combinedcronfiles ]) )) - - try: - os.symlink('%s/systemd-crontab-update.path' % (TARGER_DIR), '%s/systemd-crontab-update.path' % (TIMERS_DIR)) - except OSError as e: - if e.errno != os.errno.EEXIST: - raise - - with open('%s/systemd-crontab-update.service' % (TARGER_DIR), 'w') as f: - f.write('''# Automatically generated by %s - -[Unit] -Description=[Cron] Update cron units - -[Service] -Type=oneshot -ExecStart=/usr/bin/systemd-crontab-update -''' % (SELF)) - - return "systemd-crontab-update.path" - -seqs = {} -def count(): - n = 0 - while True: - yield n - n += 1 - - -for filename in CRONTAB_FILES: - try: - for job in parse_crontab(filename, withuser=True): - generate_timer_unit(job, seqs.setdefault(job['u'], count())) - except IOError: - pass - -for filename in ANACRONTAB_FILES: - try: - for job in parse_crontab(filename, monotonic=True): - generate_timer_unit(job, seqs.setdefault(job['u'], count())) - except IOError: - pass - -for filename in USERCRONTAB_FILES: - try: - for job in parse_crontab(filename, withuser=False): - generate_timer_unit(job, seqs.setdefault(job['u'], count())) - except IOError: - pass - -try: - generate_path_unit() -except IOError: - pass |