我正在使用部署在子网中的一组 EC2 实例。
我一般使用aws ssm命令
aws ssm start-session --region us-east-2 --target i-01234567abcdef --profile profile-one
连接到该 ec2 实例并运行诸如
这样的命令ssh mirrora
从我连接到的子网进入不同的 ec2 实例
然后我可以在 mirrora 上运行 ls 来查看文件等。
现在我正在尝试使用 python 实现相同的自动化
我是 python 的新手(也是第一次使用子进程)。我研究了一下,了解到我可以使用 Popen 打开一个子进程,并将 stdin 和 stdout 参数设置为 subprocess.PIPE
这是我尝试执行的代码示例
command = "aws ssm start-session --region us-east-2 --target i-0123456abcdef --profile profile-one"
ssh = subprocess.Popen(command.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0, shell= True, universal_newlines=True)
ssh.stdin.write("ssh mirrora")
ssh.stdin.write("ls")
# output = ssh.stdout.read()
# output , err = ssh.communicate()
# print("output:" + output)
# print("err:" + err)
# output = ssh.stdout.read()
# print("Output of ls is:", output)
print("HERE")
如果我使用
stdout.read
或 communicate
方法,程序似乎卡住了,没有任何效果。我什至无法Ctrl + C终端。
如果我在没有任何标准输出或通信的情况下运行它,它会在终端中打印“HERE”(几乎是瞬间)并且服务器端似乎没有任何实际发生(因为我试图运行 shutdown 命令来关闭 mirrora,但它程序在没有标准输出或通信的情况下退出后仍在运行)。
我做错了什么?
理想情况下,我想在 aws ssm 打开的子进程中运行我想要的命令,并在其中一个 ec2 实例上运行某些命令,并在某些
stdout.read
之后使用
stdin.write
获取一个或多个命令的输出
在我看来你应该用
run-command
代替start-session
.
这是一个 SSM 功能,用于执行静态命令和脚本,其中会话类似于 ssh 连接。
我认为它应该像这样工作:
import boto3
script = f"""
ssh mirrora 'ls'
ssh mirrora 'ls; ps -aux'
"""
target = "i-01234567abcdef "
session = boto3.Session(profile_name="profile-one")
ssm_client = session.client("ssm")
response = ssm_client.send_command(
InstanceIds=[target],
DocumentName="AWS-RunShellScript", # https://eu-central-1.console.aws.amazon.com/systems-manager/documents/AWS-RunShellScript/description?region=eu-central-1
TimeoutSeconds=20,
Comment="Example of send command",
Parameters={
'commands': [
script,
],
'workingDirectory': "/home/user1",
},
)
在这里您可以找到发送命令 API 的文档。 https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.send_command
如果你想在 python 脚本中查看日志,那么你需要扩展它——可能最简单的方法是在
send_command
中设置一个 s3 桶(它会将你的 stdout
和 stderr
重定向到提供的 s3 桶), 下载保存在 s3 文件中,并 cat/print 它们。