Beispiel #1
0
def get_maestral_pid(config_name):
    """
    Returns Maestral's PID if the daemon is running and responsive, ``None``
    otherwise. If the daemon is unresponsive, it will be killed before returning.

    :param str config_name: The name of the Maestral configuration to use.
    :returns: The daemon's PID.
    :rtype: int
    """

    lockfile = PIDLockFile(pidpath_for_config(config_name))
    pid = lockfile.read_pid()

    if pid:
        try:
            if not is_pidfile_stale(lockfile):
                return pid
        except OSError:
            os.kill(pid, signal.SIGKILL)
            logger.debug(
                f"Daemon process with PID {pid} is not responsive. Killed.")
    else:
        logger.debug("Could not find PID file")

    lockfile.break_lock()
Beispiel #2
0
def get_pid_lock_file(pidfile_path, logger, app_name):
    pidlock = PIDLockFile(pidfile_path)
    if pidlock.is_locked():
        old_pid = pidlock.read_pid()
        logger.info("Lock file exists for PID %d." % old_pid)
        if os.getpid() == old_pid:
            logger.info("Stale lock since we have the same PID.")
        else:
            try:
                old = psutil.Process(old_pid)
                if os.path.basename(__file__) in old.cmdline():
                    try:
                        logger.info("Trying to terminate old instance...")
                        old.terminate()
                        try:
                            old.wait(10)
                        except psutil.TimeoutExpired:
                            logger.info("Trying to kill old instance.")
                            old.kill()
                    except psutil.AccessDenied:
                        logger.error(
                            "The process seems to be %s, but "
                            "can not be stopped. Its command line: %s" %
                            app_name, old.cmdline())
                else:
                    logger.info(
                        "Process does not seem to be {}.".format(app_name))
            except psutil.NoSuchProcess:
                pass
                logger.info("No such process exist anymore.")
        logger.info("Breaking old lock.")
        pidlock.break_lock()
    return pidlock
Beispiel #3
0
 def main(cls, argv):
     service_name = cls.__name__.lower()
     pidfilepath = '/var/run/{service_name}.pid'.format(
         service_name=service_name)
     usage = '{service_name} [options]\n'.format(service_name=service_name) \
      + ' -h                   display this message\n' \
      + ' --pidfile=<pidfile>  define pidfile (default = {pidfilepath})\n'.format(pidfilepath=pidfilepath)
     try:
         opts, args = getopt.getopt(argv, "h", ["pidfile="])
     except getopt.GetoptError:
         print(usage)
         exit(2)
     for opt, arg in opts:
         if opt == '-h':
             print(usage)
             exit(0)
         elif opt == '--pidfile':
             pidfilepath = arg
     pidfile = PIDLockFile(pidfilepath, timeout=-1)
     try:
         with pidfile:
             service = cls()
             service.run()
     except AlreadyLocked:
         print('{service_name} already running? (pid={pid})'.format(
             service_name=service_name, pid=pidfile.read_pid()))
         exit(1)
     except LockFailed:
         print(
             'Cannot write pid file to {pidfilepath}, please fix permissions'
             .format(pidfilepath=pidfilepath))
         exit(1)
Beispiel #4
0
def daemon_stop(pid_file=None):
    """
    If pid is provided - then run try to stop daemon.
    Else - just return.
    """
    logging.debug('Stop daemon')
    if not pid_file:
        logging.debug('No pid file provided - nothing to stop')
        return
    pid_path = os.path.abspath(pid_file)
    pidfile = PIDLockFile(pid_path, timeout=-1)
    try:
        pid_num = pidfile.read_pid()
        os.kill(pid_num, signal.SIGTERM)
        # number of tries to check (every 1 sec) if agent is stoped
        tries = 600
        success = False
        while tries:
            tries -= 1
            time.sleep(1)
            try:
                os.kill(pid_num, 0)
            except OSError:  #No process with locked PID
                success = True
                break
        if success:
            logging.debug('Daemon successfully stopped')
        else:
            logging.warn('Unable to stop daemon')

    except TypeError: # no pid file
        logging.debug('Pid file not found')
    except OSError:
        logging.debug('Process not running')
Beispiel #5
0
def run_with_lock(remove=False):
    lock = PIDLockFile(
        getattr(
            settings, "HYPERKITTY_JOBS_UPDATE_INDEX_LOCKFILE",
            os.path.join(gettempdir(), "hyperkitty-jobs-update-index.lock")))
    try:
        lock.acquire(timeout=-1)
    except AlreadyLocked:
        if check_pid(lock.read_pid()):
            logger.warning("The job 'update_index' is already running")
            return
        else:
            lock.break_lock()
            lock.acquire(timeout=-1)
    except LockFailed as e:
        logger.warning(
            "Could not obtain a lock for the 'update_index' "
            "job (%s)", e)
        return
    try:
        update_index(remove=remove)
    except Exception as e:
        logger.exception("Failed to update the fulltext index: %s", e)
    finally:
        lock.release()
Beispiel #6
0
def check_if_pidfile_process_is_running(pid_file: str, process_name: str):
    """
    Checks if a pidfile already exists and process is still running.
    If process is dead then pidfile is removed.

    :param pid_file: path to the pidfile
    :param process_name: name used in exception if process is up and
        running
    """
    pid_lock_file = PIDLockFile(path=pid_file)
    # If file exists
    if pid_lock_file.is_locked():
        # Read the pid
        pid = pid_lock_file.read_pid()
        if pid is None:
            return
        try:
            # Check if process is still running
            proc = psutil.Process(pid)
            if proc.is_running():
                raise AirflowException(
                    f"The {process_name} is already running under PID {pid}.")
        except psutil.NoSuchProcess:
            # If process is dead remove the pidfile
            pid_lock_file.break_lock()
Beispiel #7
0
def create_pid_file(path):
    pid_file = PIDLockFile(arguments['--pid'])
    if pid_file.is_locked():
        pid = pid_file.read_pid()
        try:
            os.kill(pid, 0)
            raise Exception("process already running")
        except OSError, e:
            if e.errno in (errno.ESRCH, errno.ENOENT):
                pid_file.break_lock()
            else:
                raise
Beispiel #8
0
def main():
    serverCfg = piccolo.PiccoloServerConfig()

    # start logging
    handler = piccoloLogging(logfile=serverCfg.cfg['logging']['logfile'],
                             debug=serverCfg.cfg['logging']['debug'])
    log = logging.getLogger("piccolo.server")

    if serverCfg.cfg['daemon']['daemon']:
        import daemon
        try:
            import lockfile
        except ImportError:
            print(
                "The 'lockfile' Python module is required to run Piccolo Server. Ensure that version 0.12 or later of lockfile is installed."
            )
            sys.exit(1)
        try:
            from lockfile.pidlockfile import PIDLockFile
        except ImportError:
            print(
                "An outdated version of the 'lockfile' Python module is installed. Piccolo Server requires at least version 0.12 or later of lockfile."
            )
            sys.exit(1)
        from lockfile import AlreadyLocked, NotLocked

        # create a pid file and tidy up if required
        pidfile = PIDLockFile(serverCfg.cfg['daemon']['pid_file'], timeout=-1)
        try:
            pidfile.acquire()
        except AlreadyLocked:
            try:
                os.kill(pidfile.read_pid(), 0)
                print('Process already running!')
                exit(1)
            except OSError:  #No process with locked PID
                print('PID file exists but process is dead')
                pidfile.break_lock()
        try:
            pidfile.release()
        except NotLocked:
            pass

        pstd = open(serverCfg.cfg['daemon']['logfile'], 'w')
        with daemon.DaemonContext(pidfile=pidfile,
                                  files_preserve=[handler.stream],
                                  stderr=pstd):
            # start piccolo
            piccolo_server(serverCfg)
    else:
        # start piccolo
        piccolo_server(serverCfg)
Beispiel #9
0
def stop_maestral_daemon_process(config_name='maestral', timeout=10):
    """Stops maestral by finding its PID and shutting it down.

    This function first tries to shut down Maestral gracefully. If this fails, it will
    send SIGTERM. If that fails as well, it will send SIGKILL.

    :param str config_name: The name of the Maestral configuration to use.
    :param float timeout: Number of sec to wait for daemon to shut down before killing it.
    :returns: ``Exit.Ok`` if successful, ``Exit.Killed`` if killed and ``Exit.NotRunning``
        if the daemon was not running.
    """

    logger.debug('Stopping daemon')
    lockfile = PIDLockFile(pidpath_for_config(config_name))
    pid = lockfile.read_pid()

    try:
        if not pid or not _process_exists(pid):
            return Exit.NotRunning

        try:
            with MaestralProxy(config_name) as m:
                m.stop_sync()
                m.shutdown_pyro_daemon()
        except Pyro5.errors.CommunicationError:
            logger.debug('Could not communicate with daemon, sending SIGTERM')
            _send_term(pid)
        finally:
            logger.debug('Waiting for shutdown')
            while timeout > 0:
                if not _process_exists(pid):
                    logger.debug('Daemon shut down')
                    return Exit.Ok
                else:
                    time.sleep(0.2)
                    timeout -= 0.2

            # send SIGTERM after timeout and delete PID file
            _send_term(pid)

            time.sleep(1)

            if not _process_exists(pid):
                logger.debug('Daemon shut down')
                return Exit.Ok
            else:
                os.kill(pid, signal.SIGKILL)
                logger.debug('Daemon killed')
                return Exit.Killed
    finally:
        lockfile.break_lock()
Beispiel #10
0
def stop_maestral_daemon_process(config_name="maestral", timeout=10):
    """Stops maestral by finding its PID and shutting it down.

    This function first tries to shut down Maestral gracefully. If this fails, it will
    send SIGTERM. If that fails as well, it will send SIGKILL.

    :param str config_name: The name of the Maestral configuration to use.
    :param float timeout: Number of sec to wait for daemon to shut down before killing it.
    :returns: ``Exit.Ok`` if successful, ``Exit.Killed`` if killed and ``Exit.NotRunning``
        if the daemon was not running.
    """

    logger.debug("Stopping daemon")
    lockfile = PIDLockFile(pidpath_for_config(config_name))
    pid = lockfile.read_pid()

    if not pid or is_pidfile_stale(lockfile):
        lockfile.break_lock()
        return Exit.NotRunning

    try:
        # tell maestral daemon to shut down
        with MaestralProxy(config_name) as m:
            m.stop_sync()
            m.shutdown_pyro_daemon()
    except Pyro5.errors.CommunicationError:
        logger.debug("Could not communicate with daemon")
        try:
            os.kill(pid, signal.SIGTERM)  # try to send SIGTERM to process
            logger.debug("Terminating daemon process")
        except ProcessLookupError:
            logger.debug("Daemon was not running")
            return Exit.NotRunning
    finally:
        # wait for maestral to carry out shutdown
        logger.debug("Waiting for shutdown")
        while timeout > 0:
            try:
                os.kill(pid, signal.SIG_DFL)  # query if still running
            except ProcessLookupError:
                logger.debug("Daemon shut down")
                return Exit.Ok  # return True if not running anymore
            else:
                time.sleep(0.2)  # wait for 0.2 sec and try again
                timeout -= 0.2

        # send SIGKILL after timeout, delete PID file and return False
        os.kill(pid, signal.SIGKILL)
        logger.debug("Daemon process killed")
        lockfile.break_lock()
        return Exit.Killed
Beispiel #11
0
def _get_lock(theargs, stage):
    """Create lock file to prevent this process from running on same data.

       This uses ``PIDLockFile`` to create a pid lock file in celppdir
       directory named celprunner.<stage>.lockpid
       If pid exists it is assumed the lock is held otherwise lock
       is broken and recreated

       :param theargs: return value from argparse and should contain
                       theargs.celppdir should be set to path
       :param stage: set to stage that is being run
       :return: ``PIDLockFile`` upon success
       :raises: LockException: If there was a problem locking
       :raises: Exception: If valid pid lock file already exists
       """
    mylockfile = os.path.join(theargs.celppdir,
                              "celpprunner." + stage + ".lockpid")
    logger.debug("Looking for lock file: " + mylockfile)
    lock = PIDLockFile(mylockfile, timeout=10)

    if lock.i_am_locking():
        logger.debug("My process id" + str(lock.read_pid()) +
                     " had the lock so I am breaking")
        lock.break_lock()
        lock.acquire(timeout=10)
        return lock

    if lock.is_locked():
        logger.debug("Lock file exists checking pid")
        if psutil.pid_exists(lock.read_pid()):
            raise Exception("celpprunner with pid " + str(lock.read_pid()) +
                            " is running")

    lock.break_lock()
    logger.info("Acquiring lock")
    lock.acquire(timeout=10)
    return lock
Beispiel #12
0
def get_maestral_pid(config_name):
    """
    Returns Maestral's PID if the daemon is running, ``None`` otherwise.

    :param str config_name: The name of the Maestral configuration to use.
    :returns: The daemon's PID.
    :rtype: int
    """

    lockfile = PIDLockFile(pidpath_for_config(config_name))
    pid = lockfile.read_pid()

    if pid and not is_pidfile_stale(lockfile):
        return pid
    else:
        lockfile.break_lock()
Beispiel #13
0
def _get_atm_process(pid_path):
    """Return `psutil.Process` of the `pid` file. If the pidfile is stale it will release it."""
    pid_file = PIDLockFile(pid_path, timeout=1.0)

    if pid_file.is_locked():
        pid = pid_file.read_pid()

        try:
            process = psutil.Process(pid)
            if process.name() == 'atm':
                return process
            else:
                pid_file.break_lock()

        except psutil.NoSuchProcess:
            pid_file.break_lock()
Beispiel #14
0
        def wrapped(*args, **kwargs):
            logging.debug('Start daemon')
            if not pid_file and not force_daemon:
                if signal_map:
                    for key in signal_map.keys():
                        signal.signal(key, signal_map[key])
                logging.debug('Daemons pid: %s', os.getpid())
                f(*args, **kwargs)
                if clean:
                    clean()
                return
            if pid_file and pid_file not in ['-']:
                pid_path = os.path.abspath(pid_file)

                # clean old pids
                pidfile = PIDLockFile(pid_path, timeout=-1)
                try:
                    pidfile.acquire()
                    pidfile.release()
                except (AlreadyLocked, LockTimeout):
                    try:
                        os.kill(pidfile.read_pid(), 0)
                        logging.warn('Process already running!')
                        exit(2)
                    except OSError:  #No process with locked PID
                        pidfile.break_lock()

                pidfile = PIDLockFile(pid_path, timeout=-1)

                context = _daemon.DaemonContext(
                    pidfile=pidfile
                )
            else:
                context = _daemon.DaemonContext()

            if signal_map:
                context.signal_map = signal_map

            context.open()
            with context:
                logging.debug('Daemons pid: %s', os.getpid())
                f(*args, **kwargs)
                if clean:
                    clean()
Beispiel #15
0
def putioCheck():
    """ Should probably be in a class """
    global instance 
    instance = putioDaemon()
    instance.getinputs(sys.argv[1:])
    instance.readconfig()
    instance.setuplogging()
    pidfile = PIDLockFile(instance.pidfile, timeout=-1)
    try:
        pidfile.acquire()
    except AlreadyLocked:
        try: 
            os.kill(pidfile.read_pid(),0)
            print 'Process already running!'
            exit (1)
        except OSError:
            pidfile.break_lock()
    except: 
        print "Something failed:", sys.exc_info()
        exit (1)
    logging.debug('Listen is %s', instance.listen)
    if instance.listen:
       WebServer()
    signal.signal(signal.SIGTERM,handler)
    while True:
        if os.path.exists(instance.torrentdir):
            onlyfiles = [ f for f in os.listdir(instance.torrentdir) if os.path.isfile(os.path.join(instance.torrentdir,f))] 
            if len(onlyfiles):  
                client = putio.Client(instance.token)
                for torrent in onlyfiles:
                    logging.info('working on %s', torrent) 
                    # if we are listening then use the callback_url
                    callback_url = None
                    if instance.listen:
                       callback_url = 'http://'+instance.callback+'/'+instance.httppath+'/api/'+instance.token
                    logging.info('Calling add_torrent for %s with %s',torrent,callback_url)
                    client.Transfer.add_torrent(instance.torrentdir+"/"+torrent, callback_url=callback_url)
                    os.remove(instance.torrentdir+"/"+torrent)
        time.sleep(5)
Beispiel #16
0
 def main(argv):
     pidfilepath = "/var/run/nabd.pid"
     if sys.platform == 'linux':
         from .nabio_hw import NabIOHW
         nabiocls = NabIOHW
     else:
         nabiocls = NabIOVirtual
     usage = 'nabd [options]\n' \
      + ' -h                   display this message\n' \
      + ' --pidfile=<pidfile>  define pidfile (default = {pidfilepath})\n'.format(pidfilepath=pidfilepath) \
      + ' --nabio=nabio_class  define nabio implementation (default = {module}.{name})'.format(module=nabiocls.__module__, name=nabiocls.__name__)
     try:
         opts, args = getopt.getopt(argv, "h", ["pidfile=", "nabio="])
     except getopt.GetoptError:
         print(usage)
         exit(2)
     for opt, arg in opts:
         if opt == '-h':
             print(usage)
             exit(0)
         elif opt == '--pidfile':
             pidfilepath = arg
         elif opt == '--nabio':
             nabiocls = locate(arg)
     pidfile = PIDLockFile(pidfilepath, timeout=-1)
     try:
         with pidfile:
             nabio = nabiocls()
             nabd = Nabd(nabio)
             nabd.run()
     except AlreadyLocked:
         print('nabd already running? (pid={pid})'.format(
             pid=pidfile.read_pid()))
         exit(1)
     except LockFailed:
         print(
             'Cannot write pid file to {pidfilepath}, please fix permissions'
             .format(pidfilepath=pidfilepath))
         exit(1)
Beispiel #17
0
def run_with_lock(remove=False):
    lock = PIDLockFile(getattr(
        settings, "HYPERKITTY_JOBS_UPDATE_INDEX_LOCKFILE",
        os.path.join(gettempdir(), "hyperkitty-jobs-update-index.lock")))
    try:
        lock.acquire(timeout=-1)
    except AlreadyLocked:
        if check_pid(lock.read_pid()):
            logger.warning("The job 'update_index' is already running")
            return
        else:
            lock.break_lock()
            lock.acquire(timeout=-1)
    except LockFailed as e:
        logger.warning("Could not obtain a lock for the 'update_index' "
                       "job (%s)", e)
        return
    try:
        update_index(remove=remove)
    except Exception as e: # pylint: disable-msg=broad-except
        logger.exception("Failed to update the fulltext index: %s", e)
    finally:
        lock.release()
Beispiel #18
0
    def stop(station, home_dir, kill_after):
        """ Stop workers """

        kill_after = int(kill_after or 0)

        pid_files_dir = os.path.join(home_dir, "pid_files")
        pid_name = "{}.station.pid".format(station)
        pid_file_name = os.path.join(pid_files_dir, pid_name)

        pid_file = PIDLockFile(pid_file_name)
        pid = pid_file.read_pid()

        if not pid:
            return

        os.kill(pid, signal.SIGTERM)

        start_time = time.monotonic()
        while Worker._is_running(
                pid) and start_time + kill_after > time.monotonic():
            time.sleep(0.1)

        if Worker._is_running(pid):
            os.kill(pid, signal.SIGKILL)
Beispiel #19
0
def main():
    """Standard main function."""
    parser = ArgumentParser(description=__doc__,
                            usage="$(prog)s [options] command")
    parser.add_argument("command",
                        nargs='?',
                        default="start",
                        type=str,
                        help="Daemon action (start|stop|restart|status)")
    parser.add_argument("-c",
                        "--config",
                        default="/etc/mqttorrd.ini",
                        type=str,
                        help="Path to config file.",
                        metavar="<file>")
    parser.add_argument("-i",
                        "--info",
                        action="store_true",
                        help="more verbose logging level INFO is set")
    parser.add_argument("-d",
                        "--debug",
                        action="store_true",
                        help="DEBUG logging level is set")
    parser.add_argument("-f",
                        "--foreground",
                        action="store_true",
                        help="Run as script on foreground")

    args = parser.parse_args()
    try:
        config = Config(args)
        daemon = Daemon(config, args.foreground)
        if args.foreground:
            print("Starting process ...")
            return daemon.run(False)

        pid_file = PIDLockFile(config.pid_file)
        pid = pid_file.read_pid() if pid_file.is_locked() else None

        if args.command == "stop":
            if pid and check_process(pid):
                print("Stopping service with pid", pid)
                kill(pid, SIGTERM)
            else:
                print("Service not running")
            return 0

        if args.command == "status":
            if pid and check_process(pid):
                print("Service running with pid", pid)
                return 0
            print("Service not running")
            return 1

        if args.command == "restart":
            if pid and check_process(pid):
                print("Restarting service with pid", pid)
                kill(pid, SIGTERM)

        if pid:
            if not check_process(pid):
                pid_file.break_lock()
            else:
                print("Service is already running")
                return 1

        context = DaemonContext(working_directory=config.data_dir,
                                pidfile=pid_file,
                                signal_map={SIGTERM: daemon.shutdown})
        if geteuid() == 0:
            context.uid = config.uid
            context.gid = config.gid
        if config.log_handler == "file":
            context.files_preserve = [daemon.handler.stream]
        else:  # SysLogHandler
            context.files_preserve = [daemon.handler.socket]

        print("Starting service ...")
        with context:
            daemon.logger.info("Starting service with pid %d",
                               pid_file.read_pid())
            retval = daemon.run()
            daemon.logger.info("Shutdown")
            return retval
    except Exception as exc:  # pylint: disable=broad-except
        logger.info("%s", args)
        logger.debug("%s", format_exc())
        logger.fatal("%s", exc)
        parser.error("%s" % exc)
        return 1
Beispiel #20
0
class SimpleMainLock:
    """
    Tools like gprecoverseg prohibit running multiple instances at the same time
    via a simple lock file created in the MASTER_DATA_DIRECTORY.  This class takes
    care of the work to manage this lock as appropriate based on the mainOptions
    specified.

    Note that in some cases, the utility may want to recursively invoke
    itself (e.g. gprecoverseg -r).  To handle this, the caller may specify
    the name of an environment variable holding the pid already acquired by
    the parent process.
    """
    def __init__(self, mainOptions):
        self.pidfilename = mainOptions.get(
            'pidfilename', None)  # the file we're using for locking
        self.parentpidvar = mainOptions.get(
            'parentpidvar', None)  # environment variable holding parent pid
        self.parentpid = None  # parent pid which already has the lock
        self.ppath = None  # complete path to the lock file
        self.pidlockfile = None  # PIDLockFile object
        self.pidfilepid = None  # pid of the process which has the lock
        self.locktorelease = None  # PIDLockFile object we should release when done

        if self.parentpidvar is not None and self.parentpidvar in os.environ:
            self.parentpid = int(os.environ[self.parentpidvar])

        if self.pidfilename is not None:
            self.ppath = os.path.join(gp.get_masterdatadir(), self.pidfilename)
            self.pidlockfile = PIDLockFile(self.ppath)

    def acquire(self):
        """
        Attempts to acquire the lock this process needs to proceed.

        Returns None on successful acquisition of the lock or 
          the pid of the other process which already has the lock.
        """
        # nothing to do if utiliity requires no locking
        if self.pidlockfile is None:
            return None

        # look for a lock file
        self.pidfilepid = self.pidlockfile.read_pid()
        if self.pidfilepid is not None:

            # we found a lock file
            # allow the process to proceed if the locker was our parent
            if self.pidfilepid == self.parentpid:
                return None

            # cleanup stale locks
            try:
                os.kill(self.pidfilepid, signal.SIG_DFL)
            except OSError, exc:
                if exc.errno == errno.ESRCH:
                    self.pidlockfile.break_lock()
                    self.pidfilepid = None

        # try and acquire the lock
        try:
            self.pidlockfile.acquire(1)

        except LockTimeout:
            self.pidfilepid = self.pidlockfile.read_pid()
            return self.pidfilepid

        # we have the lock
        # prepare for a later call to release() and take good
        # care of the process environment for the sake of our children
        self.locktorelease = self.pidlockfile
        self.pidfilepid = self.pidlockfile.read_pid()
        if self.parentpidvar is not None:
            os.environ[self.parentpidvar] = str(self.pidfilepid)

        return None
Beispiel #21
0
        super(PermalinkServer, self).__init__(handlers_list)


if __name__ == "__main__":
    import tornado.options
    from tornado.options import define, options

    define("port", default=8080, help="run on the given port", type=int)
    tornado.options.parse_command_line()

    from lockfile.pidlockfile import PIDLockFile
    pidfile_path = PERMALINK_PID_FILE
    pidlock = PIDLockFile(pidfile_path)
    if pidlock.is_locked():
        old_pid = pidlock.read_pid()
        if os.getpid() != old_pid:
            try:
                old = psutil.Process(old_pid)
                if os.path.basename(__file__) in old.cmdline():
                    try:
                        old.terminate()
                        try:
                            old.wait(10)
                        except psutil.TimeoutExpired:
                            old.kill()
                    except psutil.AccessDenied:
                        pass
            except psutil.NoSuchProcess:
                pass
        pidlock.break_lock()
Beispiel #22
0
    import argparse
    parser = argparse.ArgumentParser(description='Launch a SageCell web server',
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('-p', '--port', type=int, default=8888,
                        help='port to launch the server')
    parser.add_argument('-b', '--baseurl', default="", help="base url")
    parser.add_argument('--interface', default=None, help="interface to listen on (default all)")
    parser.add_argument('--dir', default=config.get("dir"), help="directory for user files")
    args = parser.parse_args()

    logger.info("starting tornado web server")
    from lockfile.pidlockfile import PIDLockFile
    pidfile_path = config.get('pid_file')
    pidlock = PIDLockFile(pidfile_path)
    if pidlock.is_locked():
        old_pid = pidlock.read_pid()
        logger.info("Lock file exists for PID %d." % old_pid)
        if os.getpid() == old_pid:
            logger.info("Stale lock since we have the same PID.")
        else:
            try:
                old = psutil.Process(old_pid)
                if os.path.basename(__file__) in old.cmdline():
                    try:
                        logger.info("Trying to terminate old instance...")
                        old.terminate()
                        try:
                            old.wait(10)
                        except psutil.TimeoutExpired:
                            logger.info("Trying to kill old instance.")
                            old.kill()
Beispiel #23
0
class SimpleMainLock:
    """
    Tools like gprecoverseg prohibit running multiple instances at the same time
    via a simple lock file created in the MASTER_DATA_DIRECTORY.  This class takes
    care of the work to manage this lock as appropriate based on the mainOptions
    specified.

    Note that in some cases, the utility may want to recursively invoke
    itself (e.g. gprecoverseg -r).  To handle this, the caller may specify
    the name of an environment variable holding the pid already acquired by
    the parent process.
    """

    def __init__(self, mainOptions):
        self.pidfilename = mainOptions.get('pidfilename', None)  # the file we're using for locking
        self.parentpidvar = mainOptions.get('parentpidvar', None)  # environment variable holding parent pid
        self.parentpid = None  # parent pid which already has the lock
        self.ppath = None  # complete path to the lock file
        self.pidlockfile = None  # PIDLockFile object
        self.pidfilepid = None  # pid of the process which has the lock
        self.locktorelease = None  # PIDLockFile object we should release when done

        if self.parentpidvar is not None and self.parentpidvar in os.environ:
            self.parentpid = int(os.environ[self.parentpidvar])

        if self.pidfilename is not None:
            self.ppath = os.path.join(gp.get_masterdatadir(), self.pidfilename)
            self.pidlockfile = PIDLockFile(self.ppath)

    def acquire(self):
        """
        Attempts to acquire the lock this process needs to proceed.

        Returns None on successful acquisition of the lock or 
          the pid of the other process which already has the lock.
        """
        # nothing to do if utiliity requires no locking
        if self.pidlockfile is None:
            return None

        # look for a lock file
        self.pidfilepid = self.pidlockfile.read_pid()
        if self.pidfilepid is not None:

            # we found a lock file
            # allow the process to proceed if the locker was our parent
            if self.pidfilepid == self.parentpid:
                return None

            # cleanup stale locks
            try:
                os.kill(self.pidfilepid, signal.SIG_DFL)
            except OSError, exc:
                if exc.errno == errno.ESRCH:
                    self.pidlockfile.break_lock()
                    self.pidfilepid = None

        # try and acquire the lock
        try:
            self.pidlockfile.acquire(1)

        except LockTimeout:
            self.pidfilepid = self.pidlockfile.read_pid()
            return self.pidfilepid

        # we have the lock
        # prepare for a later call to release() and take good
        # care of the process environment for the sake of our children
        self.locktorelease = self.pidlockfile
        self.pidfilepid = self.pidlockfile.read_pid()
        if self.parentpidvar is not None:
            os.environ[self.parentpidvar] = str(self.pidfilepid)

        return None
Beispiel #24
0
def proxy_command(ctx, auth_type, auth_url, port, user, domain, password,
                  foreground, no_check):
    """
    Start a caching proxy server to the Keystone service
    """
    address = ('127.0.0.1', port)

    # Скрытие аргументов запуска прокси из списка процессов
    setproctitle.setproctitle('ostoken proxy')

    if not user:
        click.echo('Username required', err=True)
        sys.exit(1)

    if 'password' in auth_type:
        if not domain:
            click.echo('User domain name required', err=True)
            sys.exit(1)

        if not password:
            click.echo('Password required', err=True)
            sys.exit(1)

        PasswordAuth.user = user
        PasswordAuth.domain = domain
        PasswordAuth.password = password

        KeystoneProxyServer.auth_plugin = PasswordAuth
    else:
        KerberosAuth.user = user
        KeystoneProxyServer.auth_plugin = KerberosAuth

    if not auth_url:
        click.echo('Keystone URL required', err=True)
        sys.exit(1)

    # Удялем из URL параметры запроса и фрагменты
    p = urlparse(auth_url)
    path = p.path.strip('/')
    auth_url = '{scheme:s}://{netloc:s}/{path:s}'.format(scheme=p.scheme,
                                                         netloc=p.netloc,
                                                         path=path +
                                                         '/' if path else '')
    # Удаляем избыточное указание версии протокола
    auth_url = auth_url.replace('/v3', '')
    KeystoneProxyServer.auth_url = auth_url

    if not no_check:
        try:
            resp = requests.post(
                auth_url + 'v3/auth/tokens',
                auth=KeystoneProxyServer.auth_plugin('unscoped'))
        except requests.ConnectionError as e:
            click.echo(e, err=True)
            sys.exit(1)

        if resp.status_code != 201:
            click.echo('Failed to get unscope token to check credentials: '
                       '%s %s\n%s' %
                       (resp.status_code, resp.reason, resp.content),
                       err=True)
            sys.exit(1)

        token_info = resp.json()
        headers = resp.headers.copy()
        CACHE.set(token_info, headers)

    proxy_access_f, proxy_error_f = \
        setup_logging(debug=ctx.obj.get('debug', False), console=foreground)

    logger.info('auth_type: %s', auth_type)
    logger.info('auth_url: %s', auth_url)
    logger.info('user: %s@%s', user, domain)
    logger.info('password: %s', '*' * len(password))
    logger.info('uid: %d', KeystoneProxyServer.uid)

    server = HTTPServer(address, KeystoneProxyServer)
    host, port = server.socket.getsockname()[:2]
    click.echo('export OS_AUTH_URL=http://%s:%d/%s/v3' %
               (host, port, KeystoneProxyServer.access_key))

    # Проверяем наличие уже запущенного сервера
    pidfile = PIDLockFile(os.path.join(CACHE_DIR, 'proxy.pid'), timeout=5)
    if pidfile.is_locked():
        # Останавливаем предыдущий сервер
        prev_pid = pidfile.read_pid()
        os.kill(prev_pid, signal.SIGTERM)

    try:
        if foreground:
            with pidfile:
                try:
                    server.serve_forever()
                except KeyboardInterrupt:
                    logger.info('Stopping server: '
                                'keyboard interrupt received.')
        else:
            daemon_ctx = daemon.DaemonContext(
                working_directory=CACHE_DIR,
                umask=0o077,
                pidfile=pidfile,
                files_preserve=[proxy_access_f, proxy_error_f, server.socket],
                signal_map={
                    signal.SIGTERM: 'terminate',
                    signal.SIGINT: 'terminate'
                })
            try:
                with daemon_ctx:
                    # После старта демона перенаправляем stdout/stderr в
                    # систему логирования
                    sys.stdout = StreamToLogger('STDOUT', logging.INFO)
                    sys.stderr = StreamToLogger('STDERR', logging.ERROR)
                    logger.info('Server started')
                    server.serve_forever()
            except SystemExit as e:
                logger.info('Stopping server: %s', e)
    finally:
        server.server_close()
    logger.info('Server stopped')
Beispiel #25
0
def main():
    """Standard main function."""
    parser = ArgumentParser(
        description="HTTP/WSGI server for Python",
        usage="poorhttp [options] command"
    )
    parser.add_argument(
        "command", nargs='?', default="start", type=str,
        help="Daemon action (start|stop|logrotate|restart|status)")
    parser.add_argument(
        "-v", "--version", action="store_true",
        help="only print server version")

    parser.add_argument(
        "-f", "--foreground", action="store_true",
        help="Run as script on foreground")
    parser.add_argument(
        "-c", "--config", type=str,
        help="Path to config file.", metavar="<FILE>")
    parser.add_argument(
        "-p", "--pidfile", type=str,
        help="Path to pid file", metavar="<FILE>")
    parser.add_argument(
        "-a", "--address", type=str,
        help="IP listening address (host or IP)", metavar="<ADDRESS>")
    parser.add_argument(
        "-b", "--port", type=str,
        help="TCP/IP listening port", metavar="<PORT>")
    parser.add_argument(
        "-w", "--wsgi", type=str,
        help="wsgi application (Python module or file)", metavar="<MODULE>")
    parser.add_argument(
        "-i", "--info", action="store_true",
        help="More verbose logging level INFO is set.")
    parser.add_argument(
        "-d", "--debug", action="store_true",
        help="DEBUG logging level is set.")

    args = parser.parse_args()
    if args.version:
        print("%s %s version." % (__name__, __version__))
        return 0

    try:
        config = Config(args)

        pid_file = PIDLockFile(config.pid_file)

        if args.command == "stop":
            if pid_file.is_locked():
                log.info(
                    "Stoping service with pid %d", pid_file.read_pid())
                kill(pid_file.read_pid(), SIGTERM)
            return 0
        elif args.command == "status":
            if pid_file.is_locked():
                log.info(
                    "Service running with pid %d", pid_file.read_pid())
                return 0
            log.info("Service not running")
            return 1
        elif args.command == "logrotate":
            if pid_file.is_locked():
                log.info(
                    "Reopening service logs")
                kill(pid_file.read_pid(), SIGHUP)
                return 0
            log.info("Service not running")
            return 1
        elif args.command == "restart":
            if pid_file.is_locked():
                log.info(
                    "Restarting service with pid %d", pid_file.read_pid())
                kill(pid_file.read_pid(), SIGTERM)
        elif args.command == "start":
            pass
        elif not args.foreground:
            parser.error("Unknown command %s")
            return 1

        daemon = Daemon(config)
        daemon.check(not args.foreground)

        if args.foreground:
            return daemon.run(False)

        context = DaemonContext(
            working_directory="./",
            pidfile=pid_file,
            stderr=daemon.stderr, stdout=daemon.stdout,
            signal_map={SIGTERM: daemon.shutdown,
                        SIGHUP: daemon.logrotate},
            files_preserve=[daemon.stderr, daemon.stdout])

        if geteuid() == 0:
            context.uid = config.uid
            context.gid = config.gid
            daemon.set_chown()

        with context:
            daemon.logger.info(
                "Starting service with pid %d", pid_file.read_pid())
            daemon.run()
        return 0

    except KeyboardInterrupt:
        log.info('Shotdown server (keyboard interrupt)')
        return 1
    except SocketError:
        log.exception("Shutdown by SocketError")
        return 1
    except Exception as err:
        log.info("%s", args)
        log.debug("%s", format_exc())
        log.fatal("%s", err)
        parser.print_usage()
        return 1
Beispiel #26
0
    def __init__(self, cfg, debug=False):
        """Create and run a daemon.
        cfg: a DaemonConfig object
        debug: True if debug messages should be logged
        """

        logging.getLogger('hifi_appliance').setLevel(LOGGING_LEVEL)

        self._daemon_config = cfg
        self._log_debug = debug
        self._io_loop = None

        self._preserve_files = []

        if debug:
            self._log_file = sys.stderr
        else:
            try:
                self._log_file = open(cfg.log_file, 'at')
            except IOError as e:
                sys.exit('error opening {0}: {1}'.format(cfg.log_file, e))

            self._preserve_files.append(self._log_file)

        # Figure out which IDs to run as, if any
        self._uid = None
        self._gid = None

        if cfg.user:
            try:
                pw = pwd.getpwnam(cfg.user)
                self._uid = pw.pw_uid
                self._gid = pw.pw_gid
            except KeyError:
                raise DaemonError('unknown user: {0}'.format(cfg.user))

        if cfg.group:
            if not cfg.user:
                raise DaemonError("can't set group without user in config")

            try:
                gr = grp.getgrnam(cfg.group)
                self._gid = gr.gr_gid
            except KeyError:
                raise DaemonError('unknown group: {0}'.format(cfg.user))

        # Now kick off the daemon

        self.log('-' * 60)
        self.log('starting {}', sys.argv[0])

        if debug:
            # Just run directly without forking off.
            self.setup_prefork()
            self.setup_postfork()
            self._drop_privs()
            self.run()

        else:
            self.create_pid_directory(cfg.pid_file)

            # Fail early if daemon appear to be locked
            pid_lock = PIDLockFile(path=cfg.pid_file, timeout=0)
            if pid_lock.is_locked():
                sys.exit(
                    'daemon already running (pid {}) since lock file is present: {}'
                    .format(pid_lock.read_pid(), cfg.pid_file))

            # Run in daemon context, forking off and all that
            self.setup_prefork()

            context = DaemonContext(
                initgroups=False,  # We'll drop privs ourselves
                files_preserve=self._preserve_files,
                pidfile=pid_lock,
                stdout=self._log_file,
                stderr=self._log_file,
            )

            with context:
                self.setup_postfork()
                self._drop_privs()
                self.run()