#!/usr/bin/python # Licensed under http://www.apache.org/licenses/LICENSE-2.0 import os import sys import tempfile rd = tempfile.gettempdir() + "/awsr_rd" wr = tempfile.gettempdir() + "/awsr_wr" def run_client(): with open(rd, "w") as out: out.write(" ".join(sys.argv)) out.write("\n") if "-" in sys.argv: while True: data = sys.stdin.read(4096) if data == "": break out.write(data) last = None with open(wr, "r") as inp: while True: result = inp.read(4096) if len(result) == 0: break if last is not None: sys.stdout.write(last) sys.stdout.write(result[:-1]) last = result[-1:] return ord(last) def run_daemon(): from awscli.clidriver import CLIOperationCaller, LOG, create_clidriver, HISTORY_RECORDER def patchedInit(self, session): self._session = session self._client = None def patchedInvoke(self, service_name, operation_name, parameters, parsed_globals): if self._client is None: LOG.debug("Creating new %s client" % service_name) self._client = self._session.create_client( service_name, region_name=parsed_globals.region, endpoint_url=parsed_globals.endpoint_url, verify=parsed_globals.verify_ssl) client = self._client response = self._make_client_call( client, operation_name, parameters, parsed_globals) self._display_response(operation_name, response, parsed_globals) return 0 CLIOperationCaller.__init__ = patchedInit CLIOperationCaller.invoke = patchedInvoke driver = create_clidriver() while True: with open(rd, "r") as inp: os.dup2(inp.fileno(), 0) args = bytes() while True: ch = os.read(inp.fileno(), 1) if ch == b"\n" or ch == b"": break args += ch args = args.decode("utf-8").split(" ")[1:] if len(args) > 0 and args[0] == "exit": sys.exit(0) sys.stdin = inp old_stdout = sys.stdout try: with open(wr, "w") as sys.stdout: try: rc = driver.main(args) except SystemExit as e: rc = 2 # encode return code in the last byte of stdout sys.stdout.write(chr(rc)) HISTORY_RECORDER.record('CLI_RC', rc, 'CLI') except BrokenPipeError: pass sys.stdout = old_stdout def main(): if not os.access(rd, os.R_OK | os.W_OK): os.mkfifo(rd) if not os.access(wr, os.R_OK | os.W_OK): os.mkfifo(wr) if os.environ.get("AWSR_CLIENT") == "True": rc = run_client() sys.exit(rc) elif os.environ.get("AWSR_DAEMON") == "True": try: run_daemon() finally: os.remove(rd) os.remove(wr) return # fork if awsr daemon is not already running import psutil import subprocess ps = psutil.process_iter(attrs=["cmdline"]) procs = 0 for p in ps: cmd = p.info["cmdline"] if cmd and len(cmd) > 1 and cmd[0].endswith("python") and cmd[1] == sys.argv[0]: procs += 1 if procs < 2: sys.stderr.write("Forking new awsr background process\n") with open(os.devnull, 'r+b', 0) as DEVNULL: # new instance will see env var, and run itself as daemon p = subprocess.Popen(sys.argv, stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL, close_fds=True, env={ "AWSR_DAEMON": "True", "AWS_PROFILE": os.environ.get("AWS_PROFILE", "default"), }) run_client() else: run_client() if __name__ == "__main__": main()