示例#1
0
def check_pidfile(kill_other=False, scan_proc=True):
    """
    Check to see if there's already a pidfile. If so, check to see if the
    indicated process is alive and is Hubble.

    kill_other
        Default false, if set to true, attempt to kill detected running Hubble processes;
        otherwise exit with an error.

    """
    pidfile_path = __opts__['pidfile']
    if os.path.isfile(pidfile_path):
        with open(pidfile_path, 'r') as pidfile:
            xpid = pidfile.readline().strip()
            try:
                xpid = int(xpid)
            except (TypeError, ValueError):
                xpid = 0
                log.warn('unable to parse pid="%d" in pidfile=%s', xpid,
                         pidfile_path)
            if xpid:
                log.warn('pidfile=%s exists and contains pid=%d', pidfile_path,
                         xpid)
                kill_other_or_sys_exit(xpid, kill_other=kill_other)
    if scan_proc:
        scan_proc_for_hubbles(kill_other=kill_other)
示例#2
0
文件: daemon.py 项目: zachsis/hubble
def check_pidfile(kill_other=False, scan_proc=True):
    '''
    Check to see if there's already a pidfile. If so, check to see if the
    indicated process is alive and is Hubble.

    kill_other
        Default false, if set to true, attempt to kill detected running Hubble
        processes; otherwise exit with an error.

    '''
    pidfile = __opts__['pidfile']
    if os.path.isfile(pidfile):
        with open(pidfile, 'r') as f:
            xpid = f.readline().strip()
            try:
                xpid = int(xpid)
            except:
                xpid = 0
                log.warn(
                    'unable to parse pid="{pid}" in pidfile={file}'.format(
                        pid=xpid, file=pidfile))
            if xpid:
                log.warn('pidfile={file} exists and contains pid={pid}'.format(
                    file=pidfile, pid=xpid))
                kill_other_or_sys_exit(xpid, kill_other=kill_other)

    if scan_proc:
        scan_proc_for_hubbles(kill_other=kill_other)
示例#3
0
def kill_other_or_sys_exit(xpid,
                           hname=r'hubble',
                           ksig=signal.SIGTERM,
                           kill_other=True,
                           no_pgrp=True):
    """ Attempt to locate other hubbles using a cmdline regular expression and kill them when found.
        If killing the other processes fails (or kill_other is False), sys.exit instead.

        params:
          hname      :- the regular expression pattern to use to locate hubble (default: hubble)
          ksig       :- the signal to use to kill the other processes (default: signal.SIGTERM=15)
          kill_other :- (default: True); when false, don't attempt to kill,
                        just locate and exit (if found)
          no_pgrp    :- Avoid killing processes in this pgrp (avoid suicide). When no_pgrp is True,
                        invoke os.getprgp() to populate the actual value.

        caveats:
            There are some detailed notes on the process scanning in the function as comments.

            The most important caveat is that the hname regular expressions must match expecting
            that /proc/$$/cmdline text is null separated, not space separated.

            The other main caveat is that we can't actually examine the /proc/$$/exe file (that's
            always just a python). We have to scan the invocation text the kernel stored at launch.
            That text is not immutable and should not (normally) be relied upon for any purpose
            -- and this method does rely on it.
    """

    if no_pgrp is True:
        no_pgrp = os.getpgrp()
    if isinstance(no_pgrp, int):
        no_pgrp = str(no_pgrp)
    if os.path.isdir("/proc/{pid}".format(pid=xpid)):
        # NOTE: we'd prefer to check readlink(/proc/[pid]/exe), but that won't do
        # any good the /opt/whatever/bin/hubble is normally a text file with a
        # shebang; which the kernel picks up and uses to execute the real binary
        # with the "bin" file as an argument; so we'll have to live with cmdline
        pfile = '/proc/{pid}/cmdline'.format(pid=xpid)
        log.debug('searching %s for hubble procs matching %s', pfile, hname)
        with open(pfile, 'r') as pidfile:
            # NOTE: cmdline is actually null separated, not space separated
            # that shouldn't matter much for most hname regular expressions, but one never knows.
            cmdline = pidfile.readline().replace('\x00', ' ').strip()
        if re.search(hname, cmdline):
            if no_pgrp:
                pstatfile = '/proc/{pid}/stat'.format(pid=xpid)
                with open(pstatfile, 'r') as fh2:
                    # NOTE: man proc(5) § /proc/[pid]/stat
                    # (pid, comm, state, ppid, pgrp, session, tty_nr, tpgid, flags, ...)
                    pgrp = fh2.readline().split()[4]
                    if pgrp == no_pgrp:
                        log.debug(
                            "process (%s) exists and seems to be a hubble, "
                            "but matches our process group (%s), ignoring",
                            xpid, pgrp)
                        return False
            if kill_other:
                log.warn(
                    "process seems to still be alive and seems to be hubble,"
                    " attempting to shutdown")
                os.kill(int(xpid), ksig)
                time.sleep(1)
                if os.path.isdir("/proc/{pid}".format(pid=xpid)):
                    log.error(
                        "fatal error: failed to shutdown process (pid=%s) successfully",
                        xpid)
                    sys.exit(1)
                else:
                    return True
            else:
                log.error(
                    "refusing to run while another hubble instance is running")
                sys.exit(1)
    else:
        # pidfile present, but nothing at that pid. Did we receive a sigterm?
        log.warning(
            'Pidfile found on startup, but no process at that pid. Did hubble receive a SIGTERM?'
        )
    return False