class cmd: """
Execute a command on local or remote host.
Use bkg() instead to run a command in the background. """ def __init__(self, comm, shell=True, fail=True, ns=None, background=False,
host=None, timeout=5, ksft_wait=None): if ns:
comm = f'ip netns exec {ns} ' + comm
self.comm = comm if host:
self.proc = host.cmd(comm) else: # ksft_wait lets us wait for the background process to fully start, # we pass an FD to the child process, and wait for it to write back. # Similarly term_fd tells child it's time to exit.
pass_fds = ()
env = os.environ.copy() if ksft_wait isnotNone:
rfd, ready_fd = os.pipe()
wait_fd, self.ksft_term_fd = os.pipe()
pass_fds = (ready_fd, wait_fd, )
env["KSFT_READY_FD"] = str(ready_fd)
env["KSFT_WAIT_FD"] = str(wait_fd)
if self.proc.returncode != 0 and fail: if len(stderr) > 0 and stderr[-1] == "\n":
stderr = stderr[:-1] raise CmdExitFailure("Command failed: %s\nSTDOUT: %s\nSTDERR: %s" %
(self.proc.args, stdout, stderr), self)
class bkg(cmd): """
Run a command in the background.
Examples usage:
Run a command on remote host, and wait for it to finish.
This is usually paired with wait_port_listen() to make sure
the command has initialized:
with bkg("socat ...", exit_wait=True, host=cfg.remote) as nc:
...
Run a command and expect it to let us know that it's ready
by writing to a special file descriptor passed via KSFT_READY_FD.
Command will be terminated when we exit the context manager:
def bpftrace(expr, json=None, ns=None, host=None, timeout=None): """
Run bpftrace andreturn map data (if json=True).
The output of bpftrace is inconvenient, so the helper converts
to a dict indexed by map name, e.g.:
{ "@": { ... }, "@map2": { ... },
} """
cmd_arr = ['bpftrace'] # Throw in --quiet if json, otherwise the output has two objects if json:
cmd_arr += ['-f', 'json', '-q'] if timeout:
expr += ' interval:s:' + str(timeout) + ' { exit(); }'
cmd_arr += ['-e', expr]
cmd_obj = cmd(cmd_arr, ns=ns, host=host, shell=False) if json: # bpftrace prints objects as lines
ret = {} for l in cmd_obj.stdout.split('\n'): ifnot l.strip(): continue
one = _json.loads(l) if one.get('type') != 'map': continue for k, v in one["data"].items(): if k.startswith('@'):
k = k.lstrip('@')
ret[k] = v return ret return cmd_obj
def rand_port(type=socket.SOCK_STREAM): """
Get a random unprivileged port. """ with socket.socket(socket.AF_INET6, type) as s:
s.bind(("", 0)) return s.getsockname()[1]
pattern = f":{port:04X} .* " if proto == "tcp": # for tcp protocol additionally check the socket state
pattern += "0A"
pattern = re.compile(pattern)
whileTrue:
data = cmd(f'cat /proc/net/{proto}*', ns=ns, host=host, shell=True).stdout for row in data.split("\n"): if pattern.search(row): return if time.monotonic() > end: raise Exception("Waiting for port listen timed out")
time.sleep(sleep)
def wait_file(fname, test_fn, sleep=0.005, deadline=5, encoding='utf-8'): """
Wait for file contents on the local system to satisfy a condition.
test_fn() should take one argument (file contents) andreturn whether
condition is met. """
end = time.monotonic() + deadline
with open(fname, "r", encoding=encoding) as fp: whileTrue: if test_fn(fp.read()): break
fp.seek(0) if time.monotonic() > end: raise TimeoutError("Wait for file contents failed", fname)
time.sleep(sleep)
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.