Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running AWS ECS Task Attached (Not Detached)

Is there easy way to run an ECS Task attached or to follow the logs only while the container is Running (ie. Detach after displaying all of the logs associated)?

Using the AWS CLI (1.17.0) and ecs-cli (1.21.0), I have gotten decently close with the following two commands:

aws ecs run-task --cluster "mycluster" --task-definition testhelloworldjob --launch-type FARGATE --network-configuration etc.etc.etc.
        
ecs-cli logs --task-id {TASK_ID_HERE_FROM_OUTPUT_OF_PREVIOUS_COMMAND} --follow 

I am currently have two issues with the above approach:

  1. There is a race condition being that the logs are not available when the task is in a pre "running" state. Instead of ecs-cli logs waiting for the logs to exist, there is an error immediately thrown.
  2. Even after waiting for the task to be in a running state, and issuing the ecs-cli logs the command refuses to detach even AFTER the task is finished and in a Post Running status.

For the first issue I could poll until there is a post activating/pending status, prior to calling logs. For the second issue I could draft some type of threaded call that would poll to stop the following of a log after the container in question is no longer running.... But there has to be an easier way?

To clarify I am coming from numerous other container orchestration tools/technologies that seemingly supported this very seamlessly. Here are some examples of tools and their associated commands that would yield me my intended results:

Docker CLI:

docker run hello-world

Docker-Compose Yaml:

docker-compose up

K8 Kubectl Yaml:

kubectl apply -f ./hello-k8.yaml && kubectl logs --follow hello-world
like image 559
Copy and Paste Avatar asked Mar 23 '26 15:03

Copy and Paste


1 Answers

I don't know of an easy way, I also wanted to do this and ended up writing some bash magic to do it. It is a bit long, but I wrap it in a function that you can just call with a task ID which works for my purposes. The general idea to solve the above issues is:

  1. use aws ecs wait tasks-running to block until the log group is created
  2. Poll for new log messages in a loop with --since until the task is stopped
# Prints logs like 'tail -f' for an ecs task
function tail_task_logs {
  local TASKID=$1
  local CLUSTER
  local TASK_DEFINITION
  local LGROUP
  CLUSTER=$(echo "$TASKID" | cut -d/ -f1,2 | sed 's/task/cluster/')

  # Lookup the log group name
  TASK_DEFINITION=$(aws ecs describe-tasks \
      --cluster "$CLUSTER" \
      --tasks "$TASKID" \
      --query 'tasks[0].taskDefinitionArn' \
      --output text)
  LGROUP=$(aws ecs describe-task-definition \
      --task-definition "$TASK_DEFINITION" \
      --query 'taskDefinition.containerDefinitions[0].logConfiguration.options."awslogs-group"' \
      --output text)

  # Start tailing once container is running
  SINCE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  echo "Waiting for task to start.."
  aws ecs wait tasks-running \
      --cluster "$CLUSTER" \
      --tasks "$TASKID"

  STATUS="None"
  while [[ $STATUS == "None" ]]; do
    # print new messages
    NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    aws logs tail "$LGROUP" --since "$SINCE"
    SINCE="$NOW"
    sleep 2

    # Check if container is still running
    STATUS=$(aws ecs describe-tasks \
        --cluster "$CLUSTER" \
        --tasks "$TASKID" \
        --query 'tasks[0].stopCode' \
        --output text)
  done

  # Print final messages
  aws logs tail "$LGROUP" --since "$SINCE"
  echo "Container exited: $STATUS"
}

I tried to make it easy to call, so it does some work to figure the log group which you could remove if you already know it. You can call it like this

tail_task_logs "some-task-id"

You might be able to simplify using ecs-cli but I wanted a version with no extra dependencies.

like image 121
Ryan Widmaier Avatar answered Mar 26 '26 08:03

Ryan Widmaier



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!