Reputation: 780
Objective*
I am trying to use aws ecs execute-command
in conjunction with pexpect.spawn()
to start an interactive bash session in a container running on an EC2 instance.
Sample Code
import sys
import time
import boto3
import pexpect
import pexpect.expect
import pexpect.replwrap
def spawn_session(container, family, cluster, ecs_client):
print(f'Spawning Session: {container}, {family}, {cluster}')
rsp = ecs_client.list_tasks(cluster=cluster, family=family)
print(rsp)
task_arn = rsp.get('taskArns')[0]
local_argv = [
'aws', 'ecs', 'execute-command',
'--command', '/bin/bash',
'--interactive', '--task', task_arn, '--container', container,
'--cluster', cluster
]
ps = pexpect.spawn(' '.join(local_argv), timeout=900, logfile=sys.stdout.buffer)
ps.expect('ecs-execute-command.*# ', timeout=15)
return ps
def repl_session_example(container, family, cluster, ecs_client):
rsp = ecs_client.list_tasks(cluster=cluster, family=family)
print(rsp)
task_arn = rsp.get('taskArns')[0]
# bash = pexpect.replwrap.bash()
local_argv = [
'aws', 'ecs', 'execute-command',
'--command', '/bin/bash',
'--interactive', '--task', task_arn, '--container', container,
'--cluster', cluster
]
bash = pexpect.replwrap.REPLWrapper(' '.join(local_argv), '#', None)
return bash
def bash_session_example(container, family, cluster, ecs_client):
rsp = ecs_client.list_tasks(cluster=cluster, family=family)
print(rsp)
task_arn = rsp.get('taskArns')[0]
local_argv = [
'aws', 'ecs', 'execute-command',
'--command', '/bin/bash',
'--interactive', '--task', task_arn, '--container', container,
'--cluster', cluster
]
bash = pexpect.replwrap.bash()
bash.run_command(' '.join(local_argv))
return bash
if __name__ == '__main__':
ecs = boto3.client('ecs')
container = 'CONTAINER'
family = 'TASK_FAMILY'
cluster = 'CLUSTER_ARN'
# bash = repl_session_example(container, family, cluster, ecs)
# bash = bash_session_example(container, family, cluster, ecs)
bash = spawn_session(container, family, cluster, ecs)
for cmd in ['pwd', 'python --version', 'sleep 5', 'echo 2']:
# print(f'Sending: {cmd}')
bash.sendline(cmd)
bash.expect('# ')
# print(f'before: {bash.before}')
# print(f'after: {bash.after}')
# out = bash.run_command(cmd)
# print(out)
pass
Results The output seems out of order and I have to send additional input to actually get the output of the previous command.
# python temp.py
Spawning Session: CONTAINER, FAMILY, CLUSTER
...
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
Starting session with SessionId: ecs-execute-command-<ID_STRING>
bash-4.2# pwd <- Sending pwd to active session
bash-4.2# python --version
pwd
/var/task/package <- Results of pwd after sending the python --version line
bash-4.2# sleep 5
python --version
Python 3.10.14 <- Version sting for python finally printed
bash-4.2# echo 2
sleep 5
echo 2 <- The 2 is not actually print out but appears reprinted
It looks like sendline()
is not actually executing the command until a second command is actually sent. As a workaround I could send the command twice but it seems like I am missing something here.
Upvotes: 0
Views: 53