import argparse, re, sys, time import paramiko def parse_auth(): text = open("Authentication.md", encoding="utf-8").read() def find(label): m = re.search(label + r"\s*[::]\s*(\S+)", text) if not m: sys.exit("cannot parse " + label) return m.group(1) ip = find("IP地址") user = find("用户名") pw = find("密码") root_pw = find("root密码") return ip, user, pw, root_pw IP, USER, PW, ROOT_PW = parse_auth() def connect(): cli = paramiko.SSHClient() cli.set_missing_host_key_policy(paramiko.AutoAddPolicy()) cli.connect(IP, port=22, username=USER, password=PW, timeout=20, look_for_keys=False, allow_agent=False, banner_timeout=30) return cli def run(cmd, sudo=False, timeout=300): cli = connect() chan = cli.get_transport().open_session() chan.settimeout(timeout) chan.exec_command(cmd) if sudo: chan.sendall(PW + "\n") try: while True: if chan.recv_ready(): chunk = chan.recv(65536) if not chunk: break sys.stdout.buffer.write(chunk); sys.stdout.flush() if chan.recv_stderr_ready(): sys.stderr.buffer.write(chan.recv_stderr(65536)); sys.stderr.flush() if chan.exit_status_ready(): while chan.recv_ready(): chunk = chan.recv(65536) sys.stdout.buffer.write(chunk); sys.stdout.flush() while chan.recv_stderr_ready(): sys.stderr.buffer.write(chan.recv_stderr(65536)); sys.stderr.flush() break time.sleep(0.05) except Exception as e: print("\n[read-exception]", e) rc = chan.recv_exit_status() if chan.exit_status_ready() else -1 cli.close() print(f"\n[exit={rc}]") return rc def put(local, remote): cli = connect() sftp = cli.open_sftp() sftp.put(local, remote) sftp.close() cli.close() print(f"[uploaded {local} -> {USER}@{IP}:{remote}]") if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("command", nargs=argparse.REMAINDER) ap.add_argument("--sudo", action="store_true") ap.add_argument("--timeout", type=int, default=300) ap.add_argument("--put", nargs=2, metavar=("LOCAL", "REMOTE")) a = ap.parse_args() if a.put: put(a.put[0], a.put[1]) else: run(" ".join(a.command), sudo=a.sudo, timeout=a.timeout)