Shell脚本如何查看容器进程列表

wen 实用脚本 1

Shell脚本高效查看容器进程列表:实战指南与深度解析

目录导读


为什么需要查看容器进程列表?

容器本质上是宿主机上的隔离进程,当容器运行异常(如内存泄漏、僵尸进程、死锁)时,直接查看容器内的进程列表比进入容器执行 ps aux 更高效,通过 Shell 脚本结合 docker top 或 docker inspect,你能在秒级获取关键进程信息,而无需逐一登录容器。

Shell脚本如何查看容器进程列表

典型场景:

  • 排查容器内 CPU/内存占用最高的进程
  • 监控容器是否启动了额外守护进程(如意外运行的 sshd
  • 批量检查停机前容器进程是否残留

核心命令:docker top 的深度用法

基础语法解析

docker top <容器名或ID> [ps 选项]
  • docker top 直接输出容器内进程列表,等同于在容器内执行 ps -ef
  • 支持附加 ps 参数,docker top my-container -o pid,cmd,%mem 显示自定义字段

实用示例

# 显示所有容器内进程(含PID、PPID、CMD)
docker top my-nginx
# 显示CPU和内存占用排序(需容器内ps支持)
docker top my-nginx aux | sort -k3 -r | head -5
# 过滤特定进程名
docker top my-nginx | grep "python"

无 ps 命令的容器(如 Alpine)怎么办?

Alpine 默认只有 ps 但无 topdocker top 依然有效——因为它读取的是宿主机 cgroup 数据,而非容器内命令。
测试证明:即使容器内无 ps 程序,docker top 仍能输出 PID 列表(仅无 CMD 列)。


进阶技巧:Shell脚本批量管理容器进程

场景:需要查看所有运行容器的进程摘要

#!/bin/bash
# file: container_ps_summary.sh
# 用途:扫描所有运行容器,输出进程数量与TOP进程
echo "=== 容器进程监控报告 ==="
docker ps --format "{{.ID}}|{{.Names}}|{{.Image}}" | while IFS='|' read id name image; do
    proc_count=$(docker top "$id" 2>/dev/null | tail -n +2 | wc -l)
    # 获取CPU占用最高的进程
    top_cmd=$(docker top "$id" aux 2>/dev/null | awk 'NR>1 {print $11, $3}' | sort -k2 -r | head -1)
    echo "容器: $name ($image) | 进程数: $proc_count | 最耗CPU: $top_cmd"
done

场景:检查容器是否运行了非法进程(如挖矿程序)

#!/bin/bash
# 黑名单进程列表(小写)
blocklist=("xmrig" "minerd" "cryptonight")
docker ps -q | while read cid; do
    cname=$(docker inspect --format '{{.Name}}' "$cid" | cut -d'/' -f2)
    # 获取所有进程命令并转为小写
    all_cmds=$(docker top "$cid" -o cmd 2>/dev/null | tail -n +2 | tr '[:upper:]' '[:lower:]')
    for proc in "${blocklist[@]}"; do
        if echo "$all_cmds" | grep -q "$proc"; then
            echo "[警告] 容器 $cname 疑似运行黑名单进程: $proc"
            # 可追加 kill 操作(谨慎使用)
            # docker exec "$cid" pkill -9 "$proc" 2>/dev/null
        fi
    done
done

场景:通过容器 PID 反向查找宿主机进程(故障定位)

# 获取容器内PID对应的宿主机PID
container_pid=$(docker top my-container | grep "target_process" | awk '{print $1}')
# 查找宿主机上的对应PID(直接使用容器PID即可,因为容器进程命名空间映射到宿主机)
# 验证
ps -p $container_pid -o pid,comm,time

问题与解答(FAQ)

Q1:docker top 和 docker exec ps 有什么区别?

A:

  • docker top 直接读取宿主机 /proc 下容器的 cgroup 数据,速度快(毫秒级),且不依赖容器内工具。
  • docker exec ps 需在容器内创建进程,会改变容器状态(例如某些严格的安全性容器禁用 exec),且 Alpine 等精简镜像无 ps 命令。
    建议:优先使用 docker top,仅当需要复杂排序时(如 ps aux --sort=%cpu)才用 exec。

Q2:为什么我的 docker top 输出是空的?

可能原因:

  1. 容器已停止(docker ps -a 会显示停止容器,但 top 只对运行中容器有效)
  2. 容器 PID 命名空间与宿主机隔离(极少见,一般 Docker 默认共享)
  3. 权限不足(如非 root 用户无 /proc 访问权)
    解决: 检查容器状态,用 docker inspect <id> --format '{{.State.Status}}' 验证,并尝试 sudo docker top

Q3:如何监控容器进程并记录日志?

A: 结合 cron 或 systemd timer 执行以下脚本,输出到文件:

#!/bin/bash
logfile="/var/log/container_proc_$(date +%Y%m%d).log"
echo "=== $(date) ===" >> $logfile
docker ps | awk '{print $NF}' | tail -n +2 | while read name; do
  echo "容器: $name" >> $logfile
  docker top "$name" aux >> $logfile
done

Q4:容器内进程 PID 和宿主机 PID 一致吗?

A: 默认 Docker 容器与宿主机共享 PID 命名空间(非 --pid=host 情况下),容器内 PID 1 对应宿主机某个大于 1 的 PID,可通过 docker inspect -f '{{.State.Pid}}' <id> 获取容器 init 进程在宿主机的 PID。


性能与安全注意事项

  1. 避免频繁执行 docker top
    每执行一次 docker top,Docker 守护进程会加锁访问 /proc,若容器数量 > 100,建议用 docker stats --no-stream 或直接解析 cgroup 文件(/sys/fs/cgroup/pids/docker/<cid>/pids.current)替代。

  2. 严格限制黑名单脚本的 kill 操作
    上面的黑名单检测脚本若自动执行 kill,可能导致容器服务中断。始终先输出警告,手动确认后操作

  3. 嵌套容器场景(Docker in Docker)
    docker top 无法穿透内层容器,需进入外层容器后再次执行 docker top


总结与最佳实践

场景 推荐命令/脚本
查看单个容器进程数 docker top <id> \| wc -l
找出容器内 CPU 最高进程 docker top <id> aux \| sort -k3 -r \| head -1
批量检查所有容器 使用上述 container_ps_summary.sh 脚本
持续监控(1分钟频率) 结合 watch -n 60 '脚本名称'
从宿主机追踪容器进程 ls -la /proc/$(docker inspect -f '{{.State.Pid}}' <id>)/root 直接进入容器文件系统

核心观点: Shell 脚本的本质是组合 Docker 命令与标准 Unix 工具(awk、sort、grep),通过 docker top 这一轻量级接口,你可以在不进入容器的情况下,高效构建容器进程监控体系,无论是日常巡检还是应急排错,都能做到“一键执行,结果可视”。


提示: 若需在管理面板(如 Portainer、Kubernetes)中实现类似功能,建议将上述脚本封装为 Docker 镜像,作为独立监控容器运行。

上一篇Shell脚本如何查看容器网络连接

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!