def get_execv_args(self): """Internal: turn a program name into a file name, using $PATH, make sure it exists / is executable, raising a ProcessException if not """ try: commandargs = shlex.split(self.config.command) except ValueError as e: raise BadCommand("can't parse command %r: %s" % \ (self.config.command, str(e))) if commandargs: program = commandargs[0] else: raise BadCommand("command is empty") if "/" in program: filename = program try: st = self.config.options.stat(filename) except OSError: st = None else: path = self.config.get_path() found = None st = None for dir in path: found = os.path.join(dir, program) try: st = self.config.options.stat(found) except OSError: pass else: break if st is None: filename = program else: filename = found # check_execv_args will raise a ProcessException if the execv # args are bogus, we break it out into a separate options # method call here only to service unit tests self.config.options.check_execv_args(filename, commandargs, st) return filename, commandargs
def get_execv_args(self): """Internal: turn a program name into a file name, using $PATH, make sure it exists / is executable, raising a ProcessException if not """ try: commandargs = shlex.split(self.config.command) except ValueError, e: raise BadCommand("can't parse command %r: %s" % \ (self.config.command, str(e)))
class Subprocess: """A class to manage a subprocess.""" # Initial state; overridden by instance variables pid = 0 # Subprocess pid; 0 when not running config = None # ProcessConfig instance state = None # process state code listener_state = None # listener state code (if we're an event listener) event = None # event currently being processed (if we're an event listener) laststart = 0 # Last time the subprocess was started; 0 if never laststop = 0 # Last time the subprocess was stopped; 0 if never delay = 0 # If nonzero, delay starting or killing until this time administrative_stop = 0 # true if the process has been stopped by an admin system_stop = 0 # true if the process has been stopped by the system killing = 0 # flag determining whether we are trying to kill this proc backoff = 0 # backoff counter (to startretries) dispatchers = None # asnycore output dispatchers (keyed by fd) pipes = None # map of channel name to file descriptor # exitstatus = None # status attached to dead process by finsh() spawnerr = None # error message attached by spawn() if any group = None # ProcessGroup instance if process is in the group def __init__(self, config): """Constructor. Argument is a ProcessConfig instance. """ self.config = config self.dispatchers = {} self.pipes = {} self.state = ProcessStates.STOPPED def removelogs(self): for dispatcher in self.dispatchers.values(): if hasattr(dispatcher, 'removelogs'): dispatcher.removelogs() def reopenlogs(self): for dispatcher in self.dispatchers.values(): if hasattr(dispatcher, 'reopenlogs'): dispatcher.reopenlogs() def drain(self): for dispatcher in self.dispatchers.values(): # note that we *must* call readable() for every # dispatcher, as it may have side effects for a given # dispatcher (eg. call handle_listener_state_change for # event listener processes) if dispatcher.readable(): dispatcher.handle_read_event() if dispatcher.writable(): dispatcher.handle_write_event() def write(self, chars): if not self.pid or self.killing: raise OSError(errno.EPIPE, "Process already closed") stdin_fd = self.pipes['stdin'] if stdin_fd is None: raise OSError(errno.EPIPE, "Process has no stdin channel") dispatcher = self.dispatchers[stdin_fd] if dispatcher.closed: raise OSError(errno.EPIPE, "Process' stdin channel is closed") dispatcher.input_buffer += chars dispatcher.flush() # this must raise EPIPE if the pipe is closed def get_execv_args(self): """Internal: turn a program name into a file name, using $PATH, make sure it exists / is executable, raising a ProcessException if not """ try: commandargs = shlex.split(self.config.command) except ValueError, e: raise BadCommand("can't parse command %r: %s" % \ (self.config.command, str(e))) if commandargs: program = commandargs[0] else: raise BadCommand("command is empty") if "/" in program: filename = program try: st = self.config.options.stat(filename) except OSError: st = None else: path = self.config.options.get_path() found = None st = None for dir in path: found = os.path.join(dir, program) try: st = self.config.options.stat(found) except OSError: pass else: break if st is None: filename = program else: filename = found # check_execv_args will raise a ProcessException if the execv # args are bogus, we break it out into a separate options # method call here only to service unit tests self.config.options.check_execv_args(filename, commandargs, st) return filename, commandargs
def get_execv_args(self): # 检查配置文件的执行文件夹,分解执行命令 """Internal: turn a program name into a file name, using $PATH, make sure it exists / is executable, raising a ProcessException if not """ try: # 分词,按照空格 commandargs = shlex.split(self.config.command) except ValueError as e: raise BadCommand("can't parse command %r: %s" % \ (self.config.command, str(e))) # 执行程序 # file_name ='/home/ejior/anaconda3/envs/web/bin/python3.6' # os.stat(file_name)) # os.stat_result(st_mode=33277, st_ino=5503447, st_dev=66307, st_nlink=1, st_uid=1000, st_gid=1000, # st_size=11944432, st_atime=1565227511, st_mtime=1552473391, st_ctime=1552473391) ''' st_mode: inode 保护模式 st_ino: inode 节点号。 st_dev: inode 驻留的设备。 st_nlink: inode 的链接数。 st_uid: 所有者的用户ID。 st_gid: 所有者的组ID。 st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。 st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。 st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows) 是创建时间(详细信息参见平台的文档)。 ''' if commandargs: program = commandargs[0] else: raise BadCommand("command is empty") if "/" in program: filename = program try: st = self.config.options.stat(filename) except OSError: st = None else: # 从各个bin目录中寻找该程序 path = self.config.get_path() found = None st = None for dir in path: found = os.path.join(dir, program) try: st = self.config.options.stat(found) except OSError: pass else: break if st is None: filename = program else: filename = found # check_execv_args will raise a ProcessException if the execv # args are bogus, we break it out into a separate options # method call here only to service unit tests # filename的绝对路径 self.config.options.check_execv_args(filename, commandargs, st) return filename, commandargs