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 源码分析(三)):