Beispiel #1
0
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)
Beispiel #2
0
    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
Beispiel #3
0
    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