#!/usr/bin/env bash
# ==============================================================================
# 脚本名称: container_debug.sh
# 功能描述: 自动获取容器 PID 并穿透执行宿主机网络排查命令 (纯只读)
# 使用方式: ./container_debug.sh <容器名称或ID> [要执行的命令, 默认 ss -antp]
# ==============================================================================
set -o pipefail
CONTAINER_NAME=$1
COMMAND_TO_RUN=${2:-"ss -antp"}
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PLAIN='\033[0m'
if [ -z "$CONTAINER_NAME" ]; then
echo -e "${RED}用法: $0 <容器名称或ID> [要执行的网络命令, 如 'tcpdump -i eth0']${PLAIN}"
exit 1
fi
echo -e "${BLUE}================================================================${PLAIN}"
echo -e "${BLUE} 极简容器底层 Namespace 穿透诊断脚本 ${PLAIN}"
echo -e "${BLUE}================================================================${PLAIN}"
# 1. 自动判断底层运行时并获取 PID
echo -e "${YELLOW}[1/3] 正在探测目标容器的宿主机物理 PID...${PLAIN}"
TARGET_PID=""
if command -v docker &>/dev/null && docker ps -q --filter "name=$CONTAINER_NAME" --filter "id=$CONTAINER_NAME" | grep -q .; then
TARGET_PID=$(docker inspect --format '{{.State.Pid}}' "$CONTAINER_NAME" 2>/dev/null)
echo -e " -> 匹配到 Docker 容器, PID: ${GREEN}${TARGET_PID}${PLAIN}"
elif command -v crictl &>/dev/null && crictl ps -q | xargs -I {} crictl inspect {} | grep -q "$CONTAINER_NAME"; then
# 模糊匹配 crictl 容器并提取 pid
CID=$(crictl ps | grep "$CONTAINER_NAME" | awk '{print $1}')
TARGET_PID=$(crictl inspect "$CID" | grep -i 'pid' | head -n 1 | awk -F':' '{print $2}' | tr -d ' ,')
echo -e " -> 匹配到 Containerd 容器, PID: ${GREEN}${TARGET_PID}${PLAIN}"
fi
# 修复了这里的乱码 \vert{}\vert{} 为 ||
if [ -z "$TARGET_PID" ] || [ "$TARGET_PID" == "0" ]; then
echo -e "${RED}[ERROR] 未找到容器或获取 PID 失败。请确认容器名称准确且处于运行状态。${PLAIN}"
exit 1
fi
# 2. 检查 nsenter 工具
if ! command -v nsenter &>/dev/null; then
echo -e "${RED}[ERROR] 宿主机缺少 nsenter 命令 (属于 util-linux 包),无法执行穿透。${PLAIN}"
exit 1
fi
# 3. 实施穿透执行
echo -e "\n${YELLOW}[2/3] 正在进入容器网络命名空间执行命令...${PLAIN}"
echo -e " -> 目标命令: nsenter -t ${TARGET_PID} -n ${COMMAND_TO_RUN}\n"
echo -e "${BLUE}---------------------- [ 执行结果输出 ] ------------------------${PLAIN}"
# 穿透执行
nsenter -t "$TARGET_PID" -n $COMMAND_TO_RUN
EXIT_CODE=$?
echo -e "${BLUE}----------------------------------------------------------------${PLAIN}"
if [ $EXIT_CODE -eq 0 ]; then
echo -e "\n${GREEN}[OK] 穿透执行完成。${PLAIN}"
else
echo -e "\n${RED}[WARN] 命令执行返回非零状态码 ($EXIT_CODE),请确认宿主机已安装所调用的命令工具。${PLAIN}"
fi
echo -e "${BLUE}================================================================${PLAIN}"