def parse_crontab(crontab, timezone=None): """ Parses a list of crontab lines. Returns a pair comprising a list of cron jobs (as dictionaries) and a list of warning strings. """ env = {} jobs = [] warnings = [] for job in crontab: if (blankline.search(job) is not None or comment.search(job) is not None): continue m = variable.search(job) if m is not None: (var, value) = m.groups() if var == 'CRON_TZ': timezone = remove_quotes(value.rstrip()) elif var.startswith('CRAB'): env[var] = remove_quotes(value.rstrip()) continue m = cronrule.search(job) if m is not None: (time, full_command) = m.groups() # Process percent signs in command (indicating command input # and line breaks). input_lines = plain_percent.split(full_command) command = input_lines.pop(0).rstrip().replace('\%', '%') if input_lines: input_ = '\n'.join(x.replace('\%', '%') for x in input_lines) else: input_ = None # Process embedded environment variables. (command, jobvars) = split_crab_vars(command) vars_ = env.copy() vars_.update(jobvars) # Skip this job if CRABIGNORE is set, otherwise add it # to the jobs list. if 'CRABIGNORE' in vars_: if true_string(vars_['CRABIGNORE']): continue crabid = vars_.pop('CRABID', None) jobs.append({ 'crabid': crabid, 'command': command, 'time': time, 'timezone': timezone, 'input': input_, 'vars': vars_, 'rule': job, }) continue warnings.append('Did not recognise line: ' + job) return (jobs, warnings)
def save_crontab(self, host, user, crontab, timezone=None): """Takes a list of crontab lines and uses them to update the job records. It looks for the CRABID and CRON_TZ variables, but otherwise ignores everything except command lines. It also checks for commands starting with a CRABID= definition, but otherwise inserts them into the database as is. Returns a list of warning strings.""" # Save the raw crontab. self.write_raw_crontab(host, user, crontab) # These patterns do not deal with quoting or trailing spaces, # so these must be dealt with in the code below. blankline = re.compile('^\s*$') comment = re.compile('^\s*#') variable = re.compile('^\s*(\w+)\s*=\s*(.*)$') cronrule = re.compile('^\s*(@\w+|\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.*)$') idset = set() idsaved = set() warning = [] env = {} for job in self.get_jobs(host, user): idset.add(job['id']) with self.lock: # Iterate over the supplied cron jobs, removing each # job from the idset set as we encounter it. for job in crontab: if (blankline.search(job) is not None or comment.search(job) is not None): continue m = variable.search(job) if m is not None: (var, value) = m.groups() if var == 'CRON_TZ': timezone = remove_quotes(value.rstrip()) elif var.startswith('CRAB'): env[var] = remove_quotes(value.rstrip()) continue m = cronrule.search(job) if m is not None: (time, command) = m.groups() (command, jobvars) = split_crab_vars(command) vars = env.copy() vars.update(jobvars) if 'CRABIGNORE' in vars: if true_string(vars['CRABIGNORE']): continue command = command.rstrip() id_ = self._check_job(host, user, vars.get('CRABID'), command, time, timezone) if id_ in idsaved: warning.append('Indistinguishable duplicated job: ' + job) else: idsaved.add(id_) idset.discard(id_) continue warning.append('Did not recognise line: ' + job) # Set any jobs remaining in the id set to deleted # because we did not see them in the current crontab for id_ in idset: self._delete_job(id_) return warning
def save_crontab(self, host, user, crontab, timezone=None): """Takes a list of crontab lines and uses them to update the job records. It looks for the CRABID and CRON_TZ variables, but otherwise ignores everything except command lines. It also checks for commands starting with a CRABID= definition, but otherwise inserts them into the database as is. Returns a list of warning strings.""" # Save the raw crontab. self.write_raw_crontab(host, user, crontab) # These patterns do not deal with quoting or trailing spaces, # so these must be dealt with in the code below. blankline = re.compile("^\s*$") comment = re.compile("^\s*#") variable = re.compile("^\s*(\w+)\s*=\s*(.*)$") cronrule = re.compile("^\s*(@\w+|\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.*)$") idset = set() idsaved = set() warning = [] env = {} for job in self.get_jobs(host, user): idset.add(job["id"]) with self.lock: # Iterate over the supplied cron jobs, removing each # job from the idset set as we encounter it. for job in crontab: if blankline.search(job) is not None or comment.search(job) is not None: continue m = variable.search(job) if m is not None: (var, value) = m.groups() if var == "CRON_TZ": timezone = remove_quotes(value.rstrip()) elif var.startswith("CRAB"): env[var] = remove_quotes(value.rstrip()) continue m = cronrule.search(job) if m is not None: (time, command) = m.groups() (command, jobvars) = split_crab_vars(command) vars = env.copy() vars.update(jobvars) if "CRABIGNORE" in vars: if true_string(vars["CRABIGNORE"]): continue command = command.rstrip() id_ = self._check_job(host, user, vars.get("CRABID"), command, time, timezone) if id_ in idsaved: warning.append("Indistinguishable duplicated job: " + job) else: idsaved.add(id_) idset.discard(id_) continue warning.append("Did not recognise line: " + job) # Set any jobs remaining in the id set to deleted # because we did not see them in the current crontab for id_ in idset: self._delete_job(id_) return warning