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
def main(): args = sys.argv[1:] if not len(args) >= 3: print("Usage: openspendingetld <job_id> <config_file> <task> [args, ...]" % args, file=sys.stderr) sys.exit(1) # No two jobs with the same job_id can run at the same time job_id = args.pop(0) configfile_path = os.path.abspath(args.pop(0)) task = args.pop(0) _create_directories() pidfile = PIDLockFile(pidfile_path(job_id)) context = DaemonContext( stdout=open(logfile_path(job_id), 'w+'), stderr=open(logfile_path(job_id), 'w+', buffering=0), pidfile=pidfile ) # NB: There *is* a possible race condition here, if a job with the same # name is able to start between this job calling is_locked() below, and # acquiring the lock when daemonizing. # # The problem is that we want to provide immediate feedback to the # web front end, which calls this file as "openspendingetld", that it # is trying to start a job with an already used job_id, without having # to open another log file. # # This is unlikely to crop up in practice, but ideally we should FIXME. if pidfile.is_locked(): raise AlreadyLocked("Can't start two jobs with id '%s'!" % job_id) with context: try: # Configure logger log = logging.getLogger('openspending.etl') handler = logging.StreamHandler(sys.stderr) handler.setFormatter(logging.Formatter( '%(asctime)s %(levelname)s: %(message)s', '%Y-%m-%d %H:%M:%S' )) log.addHandler(handler) log.setLevel(logging.INFO) # Load pylons environment from specified config file _load_environment(configfile_path) # Run task, passing leftover arguments tasks.__dict__[task](*args) except KeyError: raise TaskNotFoundError("No task called '%s' exists in openspending.tasks!" % task)
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
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()
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
#self.ioloop.set_blocking_log_threshold(.5) 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
if __name__ == "__main__": 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.")
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
def __init__( self, pidfile, **kwargs ): argv = list(sys.argv) filename = self.filename = os.path.abspath( argv.pop(0) ) path = os.path.dirname(filename) kwargs.setdefault( 'working_directory', path ) if isinstance( pidfile, basestring ): if pidfile[0] != '/': pidfile = '%s/%s' % (path, pidfile ) pidfile = PIDLockFile( pidfile ) if argv: cmd = argv.pop(0) if cmd=='stop': self._stop( pidfile ) sys.exit(0) elif cmd=='restart': self._stop( pidfile ) c = 10 while pidfile.is_locked(): c-=1 gevent.sleep(1) if not c: raise Exception('Cannot stop daemon (Timed out)') # should just work without this - but it does not :/ cmd = [sys.executable, filename]+argv cmd.append('&') os.system( ' '.join(cmd) ) exit(0) """ elif cmd!='start': sys.stderr.write('try %s %s start|stop|restart\r\n' % (sys.executable, sys.argv[0])) exit(0) """ if pidfile.is_locked(): sys.stderr.write( 'Daemon seems to be already running\r\n' ) sys.exit(-1) self.exit_hooks = kwargs.pop('exit_hooks',[]) files_preserve = kwargs.pop('files_preserve',[]) stderr = kwargs.get('stderr') if stderr: files_preserve.append( stderr ) for logger in kwargs.pop('loggers',()): for handler in logger.handlers: if hasattr( handler, 'stream' ): files_preserve.append( handler.stream ) self.loggers = [] filename = os.path.basename( self.filename) try: from setproctitle import setproctitle setproctitle( filename ) except ImportError: import ctypes try: libc = ctypes.CDLL("libc.so.6") libc.prctl(15, filename, 0, 0, 0) except: pass _DaemonContext.__init__( self, pidfile=pidfile, files_preserve=files_preserve, **kwargs )
def __init__(self, pidfile, **kwargs): argv = list(sys.argv) filename = self.filename = os.path.abspath(argv.pop(0)) path = os.path.dirname(filename) kwargs.setdefault('working_directory', path) if isinstance(pidfile, basestring): if pidfile[0] != '/': pidfile = '%s/%s' % (path, pidfile) pidfile = PIDLockFile(pidfile) if argv: cmd = argv.pop(0) if cmd == 'stop': self._stop(pidfile) sys.exit(0) elif cmd == 'restart': self._stop(pidfile) c = 10 while pidfile.is_locked(): c -= 1 gevent.sleep(1) if not c: raise Exception('Cannot stop daemon (Timed out)') # should just work without this - but it does not :/ cmd = [sys.executable, filename] + argv cmd.append('&') os.system(' '.join(cmd)) exit(0) """ elif cmd!='start': sys.stderr.write('try %s %s start|stop|restart\r\n' % (sys.executable, sys.argv[0])) exit(0) """ if pidfile.is_locked(): sys.stderr.write('Daemon seems to be already running\r\n') sys.exit(-1) self.exit_hooks = kwargs.pop('exit_hooks', []) files_preserve = kwargs.pop('files_preserve', []) stderr = kwargs.get('stderr') if stderr: files_preserve.append(stderr) for logger in kwargs.pop('loggers', ()): for handler in logger.handlers: if hasattr(handler, 'stream'): files_preserve.append(handler.stream) self.loggers = [] filename = os.path.basename(self.filename) try: from setproctitle import setproctitle setproctitle(filename) except ImportError: import ctypes try: libc = ctypes.CDLL("libc.so.6") libc.prctl(15, filename, 0, 0, 0) except: pass _DaemonContext.__init__(self, pidfile=pidfile, files_preserve=files_preserve, **kwargs)
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')
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()