def __enter__(self): # Get lock on the "waiting" pid file. wait_pidfile_path = self.pidfilepath + '-waiting' self.wait_pidfile = pidfile.PidFile(wait_pidfile_path) while True: try: self.wait_pidfile.__enter__() break except SystemExit: # Terminate a prior waiting process. kill_from_pid_file(wait_pidfile_path, signal.SIGHUP) # Get the main pid file lock. self.pidfile = pidfile.PidFile(self.pidfilepath) t_start = datetime.datetime.now() t_elapsed = lambda: (datetime.datetime.now() - t_start).total_seconds() while True: if t_elapsed() > self.timeout_sec: raise RuntimeError('Timed out trying to get PID file lock') try: self.pidfile.__enter__() break except SystemExit: sleep(2) try: self.wait_pidfile.__exit__(None, None, None) except: pass
if __name__ == '__main__': args, opts = parse_args() class SimpleSFTPServer(asyncssh.SFTPServer): def __init__(self, conn): super().__init__(conn, chroot=args.sftp_root) class SimpleSSHServer(asyncssh.SSHServer): def server_requested(self, listen_host, listen_port): return listen_port == args.port loop = asyncio.get_event_loop() loop.run_until_complete( start_sftp_server( sftp_factory=SimpleSFTPServer if args.sftp_root else True, **opts, server_factory=SimpleSSHServer, )) # Cleanup properly when terminated signal.signal(signal.SIGINT, loop.stop) signal.signal(signal.SIGTERM, loop.stop) try: # Wait until the server is completely ready to go before creating a PID file for the loop with pidfile.PidFile(args.pid_file): loop.run_forever() except KeyboardInterrupt: loop.stop()
cmd.add_argument("-rport", help="Redis port", metavar="number", type=int) cmd.add_argument("-zsrv", help="Zabbix server host", metavar="name_or_addr") cmd.add_argument("-zport", help="Zabbix server port", metavar="number", type=int) cmd.add_argument("-zhost", help="Zabbix monitored host ID", metavar="name", required=True) cmd.add_argument("-interval", help="How frequently to poll/send ({interval})".format(**defaults), metavar="sec", type=int, default=defaults["interval"]) cmd.add_argument("-action", help="Action to perform on successful data retrieval ({action})".format(**defaults), choices=defaults["actions"], default=defaults["action"]) cmd.add_argument("-l", metavar="address_or_path", help="Address of the syslog socket ({})".format(defaults["syslog_address"]), default=defaults["syslog_address"]) cmd.add_argument("-ll", help="Logging severity level ({})".format(defaults["severity"]), choices=defaults["severities"], default=defaults["severity"]) cmd.add_argument("-oneshot", help="Poll/send once and exit ({})".format(defaults["oneshot"]), action="store_true", default=defaults["oneshot"]) cmd.add_argument("-daemonpidfile", help='Daemonize and write PID to the path specified. ' '"oneshot" and "action" will be set to False and "send". ' 'For correct operation, please specify an absolute path to the file', metavar="full_path_to_file") cmdargs = cmd.parse_args() if cmdargs.daemonpidfile is not None: if not os.path.isabs(cmdargs.daemonpidfile): raise RuntimeError("The path \"{}\" is not absolute".format(cmdargs.daemonpidfile)) cmdargs.oneshot = False cmdargs.action = "send" print('Daemon mode enabled. "oneshot" and "action" are reset to False and "send"') with daemon.DaemonContext(pidfile=pidfile.PidFile(cmdargs.daemonpidfile)): do_main_program(cmdargs) else: do_main_program(cmdargs)