Exemple #1
0
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')