#!/usr/bin/env python import os import subprocess import signal import six import time import empty import io_ut import tm_ut import dbg PIPE = subprocess.PIPE SIGKILL = signal.SIGKILL SIGINT = signal.SIGINT def call(cmd, defval='', b2s=False): try: s = subprocess.check_output( cmd, shell=True ) if six.PY3 and b2s: s = s.decode() return s except: return defval def kill_pid(pid, sig=SIGKILL): os.killpg(pid, sig) def proc_new(cmd, stdin=None, stdout=None, stderr=None, preexec_fn=os.setsid, sudo_pw=''): proc = None try: if sudo_pw: cmd = 'sudo -S ' + cmd proc = subprocess.Popen( cmd, shell=True, stdin=stdin, stdout=stdout, stderr=stderr, preexec_fn=preexec_fn ) if sudo_pw: proc.stdin.write(sudo_pw + '\n') proc.stdin.flush() except: pass def is_alive(): if not proc: return False proc.poll() return proc.returncode == None def kill(sig=SIGKILL): if proc and is_alive(): if sudo_pw: cmd = 'echo {} | sudo -S kill -{} -{} >/dev/null 2>&1'.format(sudo_pw, sig, proc.pid) call(cmd) else: kill_pid(proc.pid, sig) def wait(timeout=None): if six.PY2: proc.wait() else: proc.wait(timeout) def communicate(input=None, timeout=None): if not proc: return (None, None) if six.PY2: return proc.communicate(input) return proc.communicate(input, timeout) get_stdin = lambda : proc.stdin if proc else None get_stdout = lambda : proc.stdout if proc else None get_stderr = lambda : proc.stderr if proc else None def write_stdin_flush(b): stdin = get_stdin() if stdin: stdin.write(b) stdin.flush() def read_stdout(defval=None): stdout = get_stdout() return stdout.read() if stdout else defval return empty.new( locals() ) def cb_line(cmd, cb, preexec_fn=os.setsid): proc = proc_new( cmd, stdout=PIPE, preexec_fn=preexec_fn ) f = proc.get_stdout() while True: s = f.readline().decode() if not s: break cb( s ) proc.kill() proc.wait() def call_show(cmd): # show stdout stderr, and return bool proc = proc_new( cmd ) proc.wait() return proc.proc.returncode == 0 def call_comm(cmd, in_b): proc = proc_new(cmd, stdin=PIPE, stdout=PIPE) out_b = proc.communicate(in_b)[0] proc.wait() return out_b def proc_new_comm_tm2(cmd, tmout1, tmout2): proc = proc_new(cmd, stdin=PIPE, stdout=PIPE) kill = proc.kill wait = proc.wait stdout = proc.get_stdout() rdr = io_ut.reader_new( stdout, tmout2, no_buf=True ) def write(s): proc.write_stdin_flush( s.encode() ) def read(): if not io_ut.readable(stdout, tmout1): return None # timeout return rdr.read() # use tmout2 def comm(s): write(s) return read() return empty.new( locals() ) def cmd_py(name): path = name + '.py' if os.path.exists(path): return './' + path return 'python -m ' + name def cmd_stdio_conn(cmd1, cmd2, fifo='fifo'): cmd = 'rm -f {} ; mkfifo {} ; {} < {} | {} > {} ; rm -f {}' return cmd.format( fifo, fifo, cmd1, fifo, cmd2, fifo, fifo ) def call_stdio_conn(cmd1, cmd2, fifo='fifo', defval=''): cmd = cmd_stdio_conn( cmd1, cmd2, fifo ) return call( cmd, defval ) def proc_stdio_conn(cmd1, cmd2, fifo='fifo', sudo_pw=''): cmd = cmd_stdio_conn( cmd1, cmd2, fifo ) return proc_new( cmd, sudo_pw=sudo_pw ) def rm_rf(fn): if os.path.exists(fn): cmd = 'rm -rf {}'.format(fn) call(cmd) return cmd return '' def mk_tmp_dir(pre='tmp_'): name = pre while True: sec = tm_ut.now_sec() name = tm_ut.sec_to_fn( pre, sec ) if not os.path.exists( name ): break time.sleep( 1 ) call( 'mkdir ' + name ) return name # EOF