def __main(): ''' Neubot auto-updater process ''' # Process command line options logopt = syslog.LOG_PID daemonize = True try: options, arguments = getopt.getopt(sys.argv[1:], 'adv') except getopt.error: sys.exit('Usage: neubot/updater/unix.py [-adv]') if arguments: sys.exit('Usage: neubot/updater/unix.py [-adv]') check_for_updates = 0 # By default we don't check for updates for tpl in options: if tpl[0] == '-a': check_for_updates = 1 elif tpl[0] == '-d': daemonize = False elif tpl[0] == '-v': logopt |= syslog.LOG_PERROR|syslog.LOG_NDELAY # We must be run as root if os.getuid() != 0 and os.geteuid() != 0: sys.exit('FATAL: You must be root.') # Open the system logger syslog.openlog('neubot(updater)', logopt, syslog.LOG_DAEMON) # Clear root user environment utils_posix.chuser(utils_posix.getpwnam('root')) # Daemonize if daemonize: utils_posix.daemonize('/var/run/neubot.pid') # # TODO We should install a signal handler that kills # properly the child process when requested to exit # gracefully. # firstrun = True pid = -1 signal.signal(signal.SIGUSR1, __sigusr1_handler) # # Loop forever, catch and just log all exceptions. # Spend many time sleeping and wake up just once every # few seconds to make sure everything is fine. # while True: if firstrun: firstrun = False else: time.sleep(15) # Read configuration files CONFIG.update(utils_rc.parse_safe('/etc/neubot/updater')) CONFIG.update(utils_rc.parse_safe('/etc/neubot/users')) try: # If needed start the agent if pid == -1: syslog.syslog(syslog.LOG_INFO, 'Starting the agent') pid = __start_neubot_agent() # Check for updates now = time.time() updates_check_in = 1800 - (now - STATE['lastcheck']) if updates_check_in <= 0: STATE['lastcheck'] = now if check_for_updates: nversion = _download_and_verify_update() if nversion: if pid > 0: __stop_neubot_agent(pid) pid = -1 __install_new_version(nversion) __switch_to_new_version() raise RuntimeError('Internal error') # # We have not found an update, while here make # sure that we keep clean our base directory, # remove old files and directories, the tarball # of this version, etc. # else: __clear_base_directory() else: syslog.syslog(syslog.LOG_DEBUG, 'Auto-updates are disabled') elif check_for_updates: syslog.syslog(syslog.LOG_DEBUG, 'Auto-updates check in %d sec' % updates_check_in) # Monitor the agent rpid, status = __waitpid(pid, 0) if rpid == pid: pid = -1 # Signaled? if os.WIFSIGNALED(status): raise RuntimeError('Agent terminated by signal') # For robustness if not os.WIFEXITED(status): raise RuntimeError('Internal error in __waitpid()') syslog.syslog(syslog.LOG_WARNING, 'Child exited with status %d' % os.WEXITSTATUS(status)) except: try: why = asyncore.compact_traceback() syslog.syslog(syslog.LOG_ERR, 'In main loop: %s' % str(why)) except: pass
def go_background(): ''' Detach from the shell and run in background ''' utils_posix.daemonize(pidfile='/var/run/neubot.pid')