大量残留 network namespace 的 ip netns delete 批量脚本

2次阅读

ip netns delete 失败的根本原因是 Namespace 仍被进程、veth 设备、iptables 规则或 systemd 会话引用;必须解除所有引用才能删除。

大量残留 network namespace 的 ip netns delete 批量脚本

为什么 ip netns delete 会失败或残留?

根本原因不是命令本身不支持批量,而是每个 namespace 必须处于“未被任何进程或网络设备引用”的状态才能删除。常见卡点包括:
• 进程仍持有该 netns 的文件描述符(比如容器未彻底退出、nsenter 残留 shell)
• veth 对端仍挂在 host 或其他 netns 中(ip link 显示 netns XXX 但 XXX 已删)
• 有绑定到该 netns 的 iptables/nftables 规则(尤其使用 -t nat 或自定义链时)
• systemd 用户 session 持有 netns 引用(systemd-run --scope --scope-netns 启动的服务未 clean up)

安全批量清理残留 netns 的 bash 脚本

以下脚本先做软清理(尝试优雅删除),再强制解除引用,最后硬删目录。关键点是绕过 /var/run/netns/ 符号链接校验,直接操作底层 bind mount:

#!/bin/bash for ns in $(ip netns list | awk '{print $1}'); do     echo "处理 netns: $ns"     # 尝试正常删除     if ip netns delete "$ns" 2>/dev/null; then         continue     fi     # 若失败,检查是否有进程在用     pid=$(ls -la /proc/[0-9]*/ns/net 2>/dev/null | grep "$ns" | head -n1 | cut -d' ' -f3 | cut -d'/' -f3)     if [ -n "$pid" ]; then         echo "  PID $pid 正在使用,发送 SIGTERM"         kill "$pid" 2>/dev/null         sleep 0.5         kill -9 "$pid" 2>/dev/null     fi     # 解除 veth 引用(host 端口若名含 ns 名,移除)     ip link show | grep -E "^[0-9]+:" | cut -d':' -f1 | xargs -I{} sh -c 'ip link show {} | grep -q "netns.*'"$ns"'" && ip link delete {} 2>/dev/NULL'     # 最终强制删目录(注意:仅当确认无进程引用后才执行)     rm -f "/var/run/netns/$ns" done

ip netns delete 失败时的快速诊断命令

别急着删,先定位卡在哪:

  • 查哪些进程在用:find /proc/[0-9]*/ns/net -lname "*$NS_NAME*" 2>/dev/null
  • 查 veth 是否挂载:ip -all link show | grep -A5 "$NS_NAME"
  • 查 netns 目录是否真是 bind mount:stat /var/run/netns/$NS_NAME | grep -i "bind|mount"
  • 查是否有 network device 绑定:ip link show | grep -B1 -A1 "netns $NS_NAME"

避免下次再积的实操习惯

预防比清理重要。日常开发中建议:

  • ip netns exec $NS cmd 代替 nsenter,前者自动 cleanup 更可靠
  • 写测试脚本时,统一用 trap 'ip netns delete mytest 2>/dev/null' EXIT 保证退出必删
  • 不要手动 ln -s 创建 /var/run/netns/ 下的链接 —— 必须用 ip netns add,否则 delete 无法识别
  • docker/podman 用户注意:docker run --network=none 不创建 netns,但 --network=container:xxx 会复用,容易误判残留来源

真正麻烦的不是删不掉,而是删掉后某个 veth 还挂在 host 上却没报错 —— 建议每次批量删完,跑一遍 ip link show | grep "state DOWN" | grep -v "lo|docker|cni" 手动扫一眼异常接口

text=ZqhQzanResources