如何从运行 Fargate ECS 任务中查看 Python 打印语句?
Posted
技术标签:
【中文标题】如何从运行 Fargate ECS 任务中查看 Python 打印语句?【英文标题】:How to see Python print statements from running Fargate ECS task? 【发布时间】:2021-01-17 09:12:12 【问题描述】:我有一个 Fargate ECS 容器,用于通过 ECS 中的任务运行 Docker 容器。任务启动时,会调用一个sh脚本,runner.sh
,
#!/bin/sh
echo "this line will get logged to ECS..."
python3 src/my_python_script.py # however print statements from this Python script are not logged to ECS
这又会启动一个长时间运行的 Python 脚本 my_python_script.py
。我知道 Python 脚本运行良好,因为它完成了它需要做的事情,但我看不到 Python 脚本的输出。
在my_python_script.py
内部有几个print()
语句。在我的 ECS Fargate 任务的 CloudWatch 日志中,我看到了 sh 脚本 ("this line will get logged to ECS..."
) 的输出,但没有看到 Python 脚本中的 print()
语句的输出。
这是我的任务定义中的日志配置:
"ipcMode": null,
"executionRoleArn": "myecsTaskExecutionRolearn",
"containerDefinitions": [
"dnsSearchDomains": null,
"environmentFiles": null,
"logConfiguration":
"logDriver": "awslogs",
"secretOptions": null,
"options":
"awslogs-group": "/ecs/mylogsgroup",
"awslogs-region": "eu-west-1",
"awslogs-stream-prefix": "ecs"
,
"entryPoint": null,
"portMappings": [],
"command": null,
"linuxParameters": null,
"cpu": 0,
"environment": [],
"resourceRequirements": null,
"ulimits": null,
"dnsServers": null,
"mountPoints": [],
"workingDirectory": null,
"secrets": null,
"dockerSecurityOptions": null,
"memory": null,
"memoryReservation": null,
"volumesFrom": [],
"stopTimeout": null,
"image": "1234567.dck.aws.com/mydockerimage",
"startTimeout": null,
"firelensConfiguration": null,
"dependsOn": null,
"disableNetworking": null,
"interactive": null,
"healthCheck": null,
"essential": true,
"links": null,
"hostname": null,
"extraHosts": null,
"pseudoTerminal": null,
"user": null,
"readonlyRootFilesystem": null,
"dockerLabels": null,
"systemControls": null,
"privileged": null,
"name": "my-task-definition-name"
],
"memory": "4096",
"taskRoleArn": "myecsTaskRolearn",
"family": "my-task-definition-name",
"pidMode": null,
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "2048",
"inferenceAccelerators": [],
"proxyConfiguration": null,
"volumes": [],
"tags": []
Dockerfile:
FROM rocker/verse:3.6.0
ENV DEBIAN_FRONTEND noninteractive
RUN install2.r --error \
jsonlite
RUN echo "deb http://ftp.de.debian.org/debian testing main" >> /etc/apt/sources.list
RUN echo 'APT::Default-Release "stable";' | tee -a /etc/apt/apt.conf.d/00local
RUN apt-get update && apt-get -t testing install -y --force-yes python3.6
RUN apt-get update && apt-get -t testing install -y libmagick++-dev python3-pip python-setuptools
RUN mkdir /app
WORKDIR /app
COPY ./src /app/src
RUN pip3 install --trusted-host pypi.python.org -r /app/requirements.txt
CMD /app/runner.sh
我想我正在遵循 https://docs.aws.amazon.com/AmazonECS/latest/userguide/using_awslogs.html 的 awslogs 说明,但也许不是?我是否需要做一些明显的事情来确保 Python 脚本中的 print()
语句被捕获到我的 ECS 任务的 CloudWatch 日志中?
【问题讨论】:
你能发布剩下的任务定义和构建镜像的 Dockerfile 吗? @alexandre-juma 我已经编辑了我的问题以添加我的任务定义和 Dockerfile。谢谢 您可以尝试将 DockerfileCMD
语句更改为 exec 格式 CMD ["/app/runner.sh"]
并添加更改您的帮助脚本,例如 exec python3 src/my_python_script.py
吗?在此之后,请以交互方式登录到容器并检查 PID 1 是否被您的 python 脚本持有以确保。
这是一个长镜头,但也许日志驱动程序吓坏了,因为您的 PID 1 是一个包装外壳(您没有在 exec 模式下运行 CMD),然后调用另一个外壳脚本 /app/runner .sh 然后调用python解释器和脚本。
【参考方案1】:
在我看来,您可以在这里处理几件事情。
第一个是 Python 的默认缓冲行为,它可以阻止输出显示。你需要阻止它。
您可以通过在 CMD 之前插入以下内容来正确设置 PYTHONUNBUFFERED env var:
ENV PYTHONUNBUFFERED=1
其次,引用您链接的 Using the awslogs driver 文档:
任务中容器记录的信息类型主要取决于它们的 ENTRYPOINT 命令。默认情况下,如果您在本地运行容器,捕获的日志会显示您通常会在交互式终端中看到的命令输出,即 STDOUT 和 STDERR I/O 流。 awslogs 日志驱动程序只是将这些日志从 Docker 传递到 CloudWatch Logs。有关如何处理 Docker 日志的更多信息,包括捕获不同文件数据或流的替代方法,请参阅 Docker 文档中的查看容器或服务的日志。
因此,按照the Exec form of ENTRYPOINT,我将用以下内容替换 CMD 行:
ENTRYPOINT ["/app/runner.sh"]
这应该用于连接您的 shell 脚本的 STDOUT 和 STDERR I/O 流,并希望您的 Python 脚本连接到容器日志记录。
【讨论】:
以上是关于如何从运行 Fargate ECS 任务中查看 Python 打印语句?的主要内容,如果未能解决你的问题,请参考以下文章
Auto-Scaling 移除 ECS 服务中正在运行的任务 (FARGATE)