OSSIM开源安全信息管理系统(六)

2021SC@SDUSC

(接上一篇文章:)

__daemonize__(self) : 守护进程方法

如果收到信号 signal.SIGTERM(终止进程),调用 self.stop
当用户输入 kill sigterm pid 。 对应的进程就会收到这个信号,这个信号进程是可以捕获并指定函数处理, 例如做一下程序清理等工作,也可以忽视这个信号

def __daemonize__(self):
    signal.signal(signal.SIGTERM, self.stop)

创建一个子进程

try: 
    pid = os.fork()
    #如果是pid>0,表明当前处于父进程(pid的值为子进程的进程号)
    if pid > 0:
        #退出第一个父进程
        sys.exit(0)
#创建子进程失败,输出相应错误信息
except OSError, e:
    sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
    sys.exit(1)

与父环境解耦

os.setsid() :当进程是会话的领头进程时setsid()调用失败并返回(-1)。
setsid()调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。

# os.chdir() 方法用于改变当前工作目录到指定的路径。
os.chdir("/")
#调用系统调用 setsid()
os.setsid()
#设置当前的数值 umask 并返回之前的 umask
os.umask(0)

创建第二个子进程,过程与创建第一个子进程时相同

try:
    pid = os.fork()
    if pid > 0:
        #退出第二个父进程
        sys.exit(0)
except OSError, e:
    sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
    sys.exit(1)

重定向标准文件描述符

sys.stdout.flush()、sys.stderr.flush():标准输出和标准出错流

sys.stdout.flush()
sys.stderr.flush()

file(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None):

r:以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

a+:打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

0:报错级别

si = file('/dev/null', 'r')
so = file('/dev/null', 'a+')
se = file('/dev/null', 'a+', 0)

os.dup2() :用于将一个文件描述符 fd 复制到另一个文件描述符 fd2。
fileno() :返回一个整型的文件描述符( file descriptor FD 整型),可用于底层操作系统的 I/O 操作。

将输入、输出、出错文件描述符复制到标准输入、标准输出、标准出错流

os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

编写pid文件

atexit.register() :用于在 python 解释器中注册一个退出函数,这个函数在解释器正常终止时自动执行,一般用来做一些资源清理的操作(这里是删除 pid 文件)

atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile, 'w+').write("%s\n" % pid)
os.chmod(self.pidfile, 0644)

delpid(self) :删除pid文件

def delpid(self):
    Delete the pid file
    os.remove(self.pidfile)

stop(self, sig, params) :终止 frameworkd 进程

def stop(self, sig, params):
    try:
       pf = file(self.pidfile, 'r')
       pid = int(pf.read().strip())
       pf.close()
    except IOError:
       pid = None
    if not pid:
       message = "pidfile %s does not exist. Daemon not running? or not in daemon mode?\n"
       sys.stderr.write(message % self.pidfile)
       return

终止守护进程

try:
    while 1:
        os.kill(pid, signal.SIGTERM)
        time.sleep(0.1)
except OSError, err:
    err = str(err)
    if err.find("No such process") > 0:
        if os.path.exists(self.pidfile):
            os.remove(self.pidfile)
else:
    print str(err)
    sys.exit(1)

waitforever(self) : 等待Control-C并终止所有线程

def waitforever(self):

    while 1:
        try:
            time.sleep(1)
            #isAlive方法是从threading继承而来, is_alive() 方法查询线程是否还在运行
            if not self.__listener.isAlive():
                logger.info("Listener in down... exiting...")
                pid = os.getpid()
                os.kill(pid, signal.SIGKILL)
                break
        except KeyboardInterrupt:
            pid = os.getpid()
            os.kill(pid, signal.SIGKILL)

__init_log(self, daemon_mode)

def __init_log(self, daemon_mode):
    verbose = "info"
    Logger.add_file_handler('%s/frameworkd.log' % self.__conf[VAR_LOG_DIR])
    Logger.add_error_file_handler('%s/frameworkd_error.log' % self.__conf[VAR_LOG_DIR])

    if daemon_mode:
        Logger.remove_console_handler()

前面解析命令行函数 __parse_options(self) 中 -v参数
parser.add_option("-v", "--verbose", dest="verbose", action="count",help="make lots of noise")

命令行参数
-v -> self.options.verbose = 1
-vv -> self.options.verbose = 2

if self._options.verbose is not None:
    for i in range(self._options.verbose):
        verbose = Logger.next_verbose_level(verbose)
    Logger.set_verbose(verbose)
try:
    os.chmod('%s/frameworkd.log' % self.__conf[VAR_LOG_DIR], 0644)
    os.chmod('%s/frameworkd_error.log' % self.__conf[VAR_LOG_DIR], 0644)
except Exception, e:
    print str(e)

checkEncryptionKey(self) :检查加密密钥文件。

检查文件是否存在,key 是否存于数据库中

def checkEncryptionKey(self):
    mydb = OssimDB(self.__conf[VAR_DB_HOST], self.__conf[VAR_DB_SCHEMA],
                   self.__conf[VAR_DB_USER], self.__conf[VAR_DB_PASSWORD])
    mydb.connect()
    select_query = "select value from config where conf=\"encryption_key\";"
    insert_query = "REPLACE INTO config VALUES ('encryption_key', '%s')"
    data = mydb.exec_query(select_query)
        keyFilePath = self.__conf[VAR_KEY_FILE]
        if keyFilePath == "" or keyFilePath is None:
            logger.error("Frameworkd can't start. Please check the value of %s in the config table" % VAR_KEY_FILE)
            sys.exit(2)

        if not os.path.isfile(self.__conf[VAR_KEY_FILE]) or data is None or data == "" or len(data) == 0:
            logger.info(
                "Encryption key file doesn't exist... making it at .. %s and save it to db" % self.__conf[VAR_KEY_FILE])
            output = sub.Popen('/usr/bin/alienvault-system-id', stdout=sub.PIPE)
            s_uuid = output.stdout.read().upper()
            reg_str = "(?P[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12})"
            pt = re.compile(reg_str, re.M)
            match_data = pt.search(s_uuid)
            key = ""
            extra_data = ""
            d = datetime.today()
            if match_data is not None:
                key = match_data.group('uuid')
                extra_data = "#Generated using alienvault-system-id\n"
            else:
                logger.error(
                    "I can't obtain system uuid. Generating a random uuid. Please do backup your encrytion key file: %s" %
                    self.__conf[VAR_KEY_FILE])
                extra_data = "#Generated using random uuid on %s\n" % d.isoformat(' ')
                key = uuid.uuid4()
            newfile = open(self.__conf[VAR_KEY_FILE], 'w')
            mydb.exec_query(insert_query % key)
            key = "key=%s\n" % key
            newfile.write("#This file is generated automatically by ossim. Please don't modify it!\n")
            newfile.write(extra_data)
            newfile.write("[key-value]\n")
            newfile.write(key)
            newfile.close()
            # insert the key in db..
            pw = pwd.getpwnam('www-data')
            os.chown(self.__conf[VAR_KEY_FILE], pw.pw_uid, pw.pw_gid)
            os.chmod(self.__conf[VAR_KEY_FILE], stat.S_IRUSR)

__check_pid(self) :检查 pid 文件是否存在

def __check_pid(self):
    try:
        pf = file(self.pidfile, 'r')
        pid = int(pf.read().strip())
        pf.close()
    except IOError:
        pid = None
    if pid:
        message = "pidfile %s already exist. Daemon already running?\n"
        sys.stderr.write(message % self.pidfile)
        sys.exit(1)



上一篇(Framework 源码分析(一)):OSSIM开源安全信息管理系统(五)
下一篇(Framework 源码分析(三)):

你可能感兴趣的:(2021SC@SDUSC,安全,运维,自动化)