OSSIM-agent源代码分析(五)

本文详细介绍了OSSIM-Agent中task.py模块的功能,主要负责数据处理和测试任务的管理,包括进程的启动、监控、终止以及错误处理。Task类作为核心,实现了异步子进程的管理,支持标准方式的数据发送和子进程的独立运行。同时,提供了Wait、Kill和Status等方法来交互和控制子进程,确保了数据的有序传输和处理效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021SC@SDUSC

task.py
OSSIM-agent源代码分析(五)

简述

OSSIM Agent的主要职责是收集网络上存在的各种设备发送的所有数据,然后按照一种标准方式(standardized way)有序的发送给OSSIM Server,Agent收集到数据后在发送给Server之前要对这些数据进行标准化处理,这样Server就可以依一种统一的方式来处理这些信息,并且也简化了Server的处理过程

其中对于各种数据的处理任务调度就是非常关键的一环,task.py完整的负责各种数据的具体处理和测试任务

相关代码

初始导包

import os
import signal
import sys
import time

忽略异常处理

class error(Exception):
    pass
class _ready(Exception):
    pass

在执行路径查找可执行文件。如果没有可执行文件被找到,返回None

def which(filename):
    """Find the file 'filename' in the execution path. If no executable
       file is found, return None"""

    for dir in os.environ['PATH'].split(os.pathsep):
        fn=os.path.join(dir,filename)

        if os.path.exists(fn):
            if os.stat(fn)[0]&0111:
                return fn

    else:
        return None

进程杀死函数

 def Kill(self,signal=signal.SIGTERM):
        if self.status is None:     
            return os.kill(self.pid,signal)

Task类:管理异步子流程任务。

但这和subproc类不同!

  • subproc通过管道连接子进程
  • task允许子进程自主运行。
  • subproc是一个os.popen()
  • task是一个os.system()

在开始任务后,我们可以:

1、问它是否完成了

2、等待直到它完成

3、在等待时执行一个“空闲”任务(例如Tkinter的主循环)

4、子流程终止

5、用特定的信号杀死子进程

6、询问exit code

包含错误处理和命令处理的构造函数

    def __init__(self,command):
        if type(command)==type(''):
            self.cmd=command
            self.words=command.split()
        elif type(command)==type([]) or type(command)==type(()):
            self.cmd="'"+"' '".join(command)+"'"
            self.words=tuple(command)
        else:
            raise error("command must be tuple, list, or string")
        self.pid=None
        self.status=None

执行函数,只能执行一次

Usesh:如果为1,则执行’sh -c command’,如果为0,则拆分命令再运行它

​ 如果usesh=1, Kill方法会杀死’sh’进程,而不是具体命令

detach:如果是1,执行’sh -c ‘command&’(无论“usesh”)。因为’sh’进程将立即执行,终止时,创建的任务将被继承init

​ 如果detach=1, Kill(), Done()和Status()将会操作sh,但无法知道detached process

stdout:不为None要用作子进程的标准输出的文件名

​ 如果为None,将使用父对象的标准输出。

stdin:不为None filename用于子进程的stdin

​ 如果为None,将使用父对象的stdin

stderr:不为None filename用于子进程的stderr。

​ 如果为None,将使用父节点的标准错误。

 def Run(self,usesh=0,detach=0,stdout=None,stdin=None,stderr=None):
        if self.pid!=None:
            raise error("Second run on task forbidden")

        self.pid=os.fork()

        if not self.pid:
            for fn in range(3,256): 
                try:
                    os.close(fn)

                except os.error:
                    pass

            if stdout: 
                os.close(1)
                i=os.open(stdout,os.O_CREAT|os.O_WRONLY|os.O_TRUNC,0666)

                if i!=1:
                    sys.stderr.write("stdout not opened on 1!\n")

            if stdin: 
                os.close(0)
                i=os.open(stdin,os.O_RDONLY)

                if i!=0:
                    sys.stderr.write("stdin not opened on 0!\n")

            if stderr: 
                os.close(2)
                i=os.open(stderr,os.O_CREAT|os.O_WRONLY|os.O_TRUNC,0666)

                if i!=2:
                    sys.stdout.write("stderr not opened on 2!\n")

            try:
                if detach:
                    os.execv('/bin/sh',('sh','-c',self.cmd+'&'))

                elif usesh:
                    os.execv('/bin/sh',('sh','-c',self.cmd))

                elif self.words[0]=='/':
                    os.execv(self.words[0],self.words)

                else:
                    os.execvp(self.words[0],self.words)

            except:
                print self.words
                sys.stderr.write("Subprocess '%s' execution failed!\n"%self.cmd)
                sys.exit(1)

        else:
            if detach:
                self.Wait()

进程等待函数

def TextAbortableWait(self,text):
        print text
        try:
            return self.Wait()
        except KeyboardInterrupt:
            print "Interrupted."
            stat=self.Status()
            if stat is None:
                self.Kill(signal=2)
                return self.Wait()

等待子进程终止函数。如果进程已经终止,该函数将返回而不引发错误

  def AbortableWait(self,interval=0.1,master=None,text=None):
        if master is None:
            return self.TextAbortableWait(text)

        import Pmw
        d=Pmw.MessageDialog(master,
                            message_text=text,
                            title='Working...',
                            buttons=('Abort',),
                            command=self._buttonkill)

        try:
            from misc import config
            d.configure(message_background=config.bgbusy)

        except ImportError:
            pass

        d.component('message').pack(ipadx=15,ipady=15)
        def doit(d=d,self=self,idlefunc=master.update,interval=interval):
            d.update()
            self.Wait(idlefunc=idlefunc,interval=interval)
            raise _ready

        d.configure(activatecommand=doit)

        try:
            try:
                d.activate()

            except _ready:
                pass

        finally:
            d.deactivate()
            d.destroy()

        return self.status


等待子进程终止函数,idlefunc=None:一个可调用对象(函数,类,绑定方法)每0.1秒调用一次’interval’变量)要终止的子进程。这可以是Tkinter的“更新”程序,使GUI跑的时候不会死。如果设置为’None’,这个过程会等待。idlefunc应该不会花很长时间

 def Wait(self,idlefunc=None,interval=0.1):
        if self.status!=None:
          
            return self.status

        if callable(idlefunc):
            while 1:
                try:
                    pid,status=os.waitpid(self.pid,os.WNOHANG)
                    if pid==self.pid:
                        self.status=status
                        return status
                    else:
                        idlefunc()
                        time.sleep(interval)
                except KeyboardInterrupt:
                    try:
                        self.Kill(signal=signal.SIGINT)
                    except OSError:
                        pass
                except OSError:
                    print "WARNING: Unfindable process. Somebody else asked for my status!"
                    self.status=0
                    return 0
        elif idlefunc:
            raise error("Non-callable idle function")
        else:
            while 1:
                try:
                    pid,status=os.waitpid(self.pid,0)
                    self.status=status
                    return status
                except KeyboardInterrupt:
                    try:
                        self.Kill(signal=signal.SIGINT)
                    except OSError:
                        pass
                except OSError:
                    print "WARNING: Unfindable process. Somebody else asked for my status!"
                    self.status=0
                    return 0

向正在运行的子进程发送信号函数

  def Kill(self,signal=signal.SIGTERM):
        if self.status is None:
            return os.kill(self.pid,signal)
        else:
            print "DBG> trying to send signal to finished program"

询问该过程是否已经完成,Done函数

    def Done(self):
        if self.status!=None:
            return 1
        else:
            pid,status=os.waitpid(self.pid,os.WNOHANG)

            if pid==self.pid:
                self.status=status
                return 1
            else:
                return 0

询问任务的状态函数

def Status(self):
        self.Done()
        return self.status

Attach类,测试任务进程是否可正常进行类

class Attach:
    def __init__(self,pid):
        self.pid=pid

    def Kill(self,signal=signal.SIGTERM):
        return os.kill(self.pid,signal)

    def Status(self):
        try:
            self.Kill(signal=0)

        except OSError:
            return 0 
        return None

if __name__=="__main__":
    print "Testing simple program run"
    done=0
    t=Task('ls /tmp')
    print t
    t.Run()
    print t
    print "done,status=",t.Done(),t.Status()
    time.sleep(2)
    print "done,status=",t.Done(),t.Status()
    print t
    print "Superfluous wait=",t.Wait()
    print "Testing interruption of task"
    done=0
    t=Task('sleep 10')
    t.Run()
    print "done,status=",t.Done(),t.Status()
    t.Kill()
    print "done,status=",t.Done(),t.Status()
    t.Wait()
    print "done,status=",t.Done(),t.Status()
	print "Testing wait for simple program run"
    done=0
    t=Task('ls /tmp')
    t.Run()
    t.Wait()
    print "done,status=",t.Done(),t.Status()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值