Shell 脚本列出所有 IP 地址:2026 年企业级实践指南

IP 地址可以看作是我们日常生活中的家庭住址。正如每个房子都有唯一的家庭住址一样,网络上的每个独特设备也有一个唯一的 IP 地址IP 地址用于在网络协议网络中唯一标识一个设备。

IP 地址示例:

192.0.2.1/24

在这里,192.0.2.1 被称为网络 ID,而 24 是主机 ID。我们可以把网络 ID 想象成街道名称,而主机 ID 则是唯一的门牌号。

编写 Shell 脚本列出所有 IP 地址

随着我们步入 2026 年,虽然基础设施变得更加复杂,容器化(Docker/K8s)和云原生架构普及,但获取本机 IP 这一基础操作依然至关重要。在自动化部署、服务发现和监控告警中,准确、高效地列出 IP 是第一步。

方法 1:使用 hostname 命令(适合快速诊断)

hostname 是一个用于在 Linux 中显示主机名详细信息的命令,主机名是分配给计算机的唯一域名。我们可以在终端中输入 hostname 命令来查看设备的主机名。
命令:

hostname -I

这里,“-I”用于列出所有 IP 地址。

输出:

!Shell Script to List All IPip addresses

让我们编写一个脚本来列出所有 IP。

在早期的脚本编写中,我们可能会直接输出结果。但为了更好的可读性和后续的自动化处理(比如将 IP 传入配置文件),我们会按照以下方式进行格式化。获取所有 IP 后,我们按空格分割这些地址,然后逐行显示。

脚本:

#! /bin/bash

# 保存所有 ip 地址
# 注意:hostname -I 会将所有 IP 放在一行,用空格分隔
ip_addresses=$(hostname -I)

# 按空格分割,将其转换为数组
// 这种字符串替换方式在 Bash 中处理空格非常有效
ip_addresses=(${ip_addresses//" "/ })

# 逐行打印每个 ip 地址,增加表头便于阅读
echo "LIST OF IP ADDRESSES"
for ip in "${ip_addresses[@]}";
do
  printf "$ip
"
done

输出:

!Shell Script to List All IPList of ip addresses

> 注意:hostname -I 将不会显示链路本地 ip6 地址,因为它是为每个支持 IPv6 的接口自动配置的。在现代高可用网络中,这一点尤为重要,因为我们通常关注的是可路由的全球单播地址。

方法 2:使用 awk 命令(企业级推荐)

awk 是一种图灵完备的模式匹配编程语言,广泛与其他 Linux 命令 结合使用,用于模式匹配和数据提取。在我们的实际生产环境中,INLINECODEf2cb5394 配合 INLINECODEd87ace56 命令是更稳健的选择,因为它提供了更细致的控制权。
脚本:

#! /bin/bash

# 提取匹配以下模式的行
# 我们使用 ip address 获取原始数据
# awk 过滤出包含 ‘inet‘ 的行并打印第二列(地址/掩码)
# grep -v 用于排除我们不需要的回环地址 (::1 和 127.x.x.x)
ip=$(ip address| awk ‘/inet/ {print $2}‘ | grep -v ^::1 | grep -v ^127)

# 显示 ip 地址
echo "LIST OF IP ADDRESSES"
echo "$ip"

这里,ip address 将列出有关网络及其 ip 地址的信息,使用 awk ‘/inet/ {printf $2}‘ 我们是在查找以 inet 开头的模式并打印地址。而 grep -v ^::1 将反向匹配包含“::1”的内容,同样我们不希望将本地主机列为 ip 地址,所以我们使用 grep -v ^127 将其省略。

输出:

!Shell Script to List All IPList of ip addresses

进阶实战:2026 年视角下的 IP 地址管理

现在我们已经掌握了基础方法,但在 2026 年的开发环境中,仅仅打印出 IP 是不够的。作为开发者,我们面对的是容器化环境、多网卡服务器以及复杂的微服务架构。让我们深入探讨一些更高级的场景和解决方案。

1. 处理复杂网络环境与 JSON 输出

在现代 DevOps 工作流中,特别是与 Kubernetes 或 Terraform 交互时,文本格式的输出往往难以解析。我们更倾向于结构化数据(如 JSON)。让我们看看如何利用 jq 这样的现代工具来增强我们的脚本。

场景: 假设我们需要将当前服务器的 IP 列表以 JSON 格式发送给监控系统的 API。
高级脚本示例:

#!/bin/bash

# 定义一个函数来获取 IP,体现模块化编程思维
get_network_info() {
    # 我们使用 ip -j (JSON) 直接获取 JSON 格式的输出,这是较新发行版的特性
    # 如果没有 -j 支持,则回退到 awk
    if ip -j addr &>/dev/null; then
        ip -j addr | jq -r ‘.[] | select(.addr_info != null) | .addr_info[] | select(.family == "inet" or .family == "inet6") | ".local": "\(.local)", "prefixlen": \(.prefixlen)‘
    else
        # 兼容模式:使用 awk 提取并手动构建 JSON 字符串
        echo "Legacy fallback mode"
        ip addr show | awk ‘/inet / {print $2}‘ | sed ‘s/\//"prefixlen": "/‘ | sed ‘s/^/"ip": "/‘ | paste -sd,
    fi
}

echo "{
  "hostname": "$(hostname)",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "interfaces": [
    $(
        # 这里演示了如何在 shell 中进行简单的循环构建 JSON 数组
        ip addr show | grep -E "^[0-9]+:" | cut -d":" -f2 | tr -d ‘ ‘ | while read iface; do
            # 获取该接口的 IPv4 地址
            ips=$(ip addr show "$iface" | awk ‘/inet / {print $2}‘ | cut -d/ -f1)
            if [ -n "$ips" ]; then
                echo "  {\"interface\": \"$iface\", \"ips\": [$(echo "$ips" | sed ‘s/.*/"&"/‘ | tr ‘
‘ ‘,‘ | sed ‘s/,$//‘)]}",
            fi
        done
    )
  ]
}" | sed ‘s/,
[ ]*\]/
  ]/‘ # 清除最后一个多余的逗号

解析:

在这个脚本中,我们不仅仅是在打印 IP,而是在构建一个数据对象。我们首先检测 ip 命令是否支持 JSON 输出(这是 Linux 工具生态现代化的一个趋势),如果不支持,则回退到传统的文本处理。这种“降级兼容”思维在编写跨发行版脚本时非常关键。

2. AI 辅助与 Vibe Coding:我们如何写脚本

在 2026 年,我们的编码方式发生了显著变化。Vibe Coding(氛围编程)——即通过自然语言描述意图,由 AI 生成具体实现——已经成为常态。当我们需要编写一个脚本来“监听 IP 变化并触发回调”时,我们不再需要死记硬背 Bash 的语法细节。

Prompt 示例:

> “写一个 Shell 脚本,监听 eth0 网卡的 IP 变化。如果 IP 改变,调用 webhook 并在 /var/log/ip_change.log 中记录。包含错误处理和重试逻辑。”

AI 生成的生产级代码片段:

#!/bin/bash

# 这是一段由 AI 辅助生成的代码示例
# 展示了现代脚本如何处理长运行任务和错误容灾

INTERFACE="eth0"
WEBHOOK_URL="https://api.internal.example.com/hooks/ip-update"
LOG_FILE="/var/log/ip_change.log"

# 日志函数:包含时间戳和日志级别
log() {
    local level="$1"
    shift
    echo "[$(date ‘+%Y-%m-%d %H:%M:%S‘)] [$level] $*" | tee -a "$LOG_FILE"
}

# 发送通知的函数,包含指数退避重试机制
send_notification() {
    local new_ip="$1"
    local payload="{\"hostname\": \"$(hostname)\", \"ip\": \"$new_ip\"}"
    local retries=3
    local wait_time=5

    while [ $retries -gt 0 ]; do
        if curl -s -X POST -H "Content-Type: application/json" -d "$payload" "$WEBHOOK_URL"; then
            log "INFO" "Successfully notified API of IP change: $new_ip"
            return 0
        else
            log "ERROR" "Failed to notify API. Retries left: $retries"
            retries=$((retries - 1))
            sleep $wait_time
            wait_time=$((wait_time * 2)) # 指数退避
        fi
    done
    log "ERROR" "All retries failed."
    return 1
}

# 主循环:使用 trap 捕获退出信号,确保优雅退出
cleanup() {
    log "INFO" "Stopping IP monitor."
    exit 0
}
trap cleanup SIGINT SIGTERM

log "INFO" "Starting IP monitor on interface $INTERFACE..."

# 缓存当前的 IP
CURRENT_IP=$(ip -4 addr show dev "$INTERFACE" | awk ‘/inet / {print $2}‘ | cut -d/ -f1)
log "INFO" "Initial IP: $CURRENT_IP"

while true; do
    # 使用 ip monitor 命令异步监听网络事件(比轮询更高效)
    # 注意:这是一个简化的演示,生产环境可能需要处理更复杂的输出解析
    ip monitor addr dev "$INTERFACE" | while read -r line; do
        if echo "$line" | grep -q "inet"; then
            NEW_IP=$(echo "$line" | awk ‘{print $4}‘ | cut -d/ -f1)
            if [ "$NEW_IP" != "$CURRENT_IP" ]; then
                log "INFO" "IP changed from $CURRENT_IP to $NEW_IP"
                send_notification "$NEW_IP"
                CURRENT_IP="$NEW_IP"
            fi
        fi
    done
    # 如果 ip monitor 退出(例如网卡重启),稍作等待后重新启动监控
    log "WARN" "Monitor exited, restarting in 5s..."
    sleep 5
done

代码解析:

  • 异常处理与重试: 你可以看到我们并没有直接执行 curl,而是封装了一层重试逻辑。在网络不稳定的环境(如边缘计算节点)中,这是必须的。
  • 日志规范: 所有输出都带有了时间戳和级别,这对于后续使用 ELK(Elasticsearch, Logstash, Kibana)栈进行日志分析至关重要。
  • 资源效率: 使用 INLINECODE6163ff0c 替代 INLINECODE30369ada 轮询,显著降低了 CPU 占用率。

3. 性能优化与常见陷阱

在我们的经验中,很多初学者写的脚本在处理大规模数据或老旧硬件时会出现性能瓶颈。以下是一些我们在项目中总结的优化建议:

  • 避免外部命令调用循环: 这是一个经典的陷阱。

* 错误做法: cat file.txt | while read line; do grep $line large_file.txt; done

* 正确做法: 尽量使用 INLINECODE61e8a758 或 INLINECODE6534494b 在内部处理循环,或者利用 xargs -P 进行并行处理。在上面的 IP 监控脚本中,我们利用了 Shell 内置的管道特性,而不是频繁启动新进程。

  • 引号的使用:

在 2026 年,IPv6 的普及率已经非常高。IPv6 地址包含多个冒号(:),如果在 Shell 脚本中不加双引号引用变量,会被 Shell 解析为分隔符,导致脚本崩溃。

* 错误: echo $ip_addr

* 正确: echo "$ip_addr" —— 永远记得给变量加引号。

  • 子进程的陷阱:

管道 | 会创建子 Shell。这意味着在管道循环中修改的变量,在循环外部是丢失的。这也是为什么上面的高级脚本中,我们使用了临时文件或进程替换来传递数据。

替代方案与技术选型

虽然 Bash 脚本因其“到处都有”而仍然是首选,但在某些 2026 年的场景下,我们会考虑其他方案:

  • Python 3 + PyPy: 如果涉及复杂的 API 交互或加密逻辑,Python 的库支持更好。虽然性能不如 C,但开发效率极高(配合 AI 辅助)。
  • Go (Golang): 如果我们需要构建一个跨平台的二进制工具(例如在 Docker 镜像中使用),Go 是最佳选择。它编译出的二进制文件不依赖 Shell 环境,非常适合构建云原生应用。
  • PowerShell (Core): 在混合操作系统环境中,PowerShell 的对象模型处理网络配置比 Bash 的文本流处理更直观。

结论

Bash 脚本是 Shell 脚本的一种特定类型,旨在 Bash shell 中执行——Bash shell 是当今 Linux 中使用最广泛的 shell。Shell 脚本是一个更通用的术语,可以为任何 shell 编写脚本,例如 BashZsh 或 Dash。虽然所有 Bash 脚本都是 Shell 脚本,但并非所有 Shell 脚本都是 Bash 脚本。

如果我们从事 Linux 自动化、服务器管理或命令行脚本工作,Bash 和 Shell 脚本 技能将允许我们编写更便携、优化且兼容的脚本。

随着我们进入 2026 年,Shell 脚本并没有消失,而是进化了。通过结合 AI 辅助编程、现代化的 JSON 处理工具以及对云原生环境的深刻理解,我们依然能编写出高效、健壮且易于维护的系统级工具。无论你是传统的运维工程师,还是正在构建边缘计算应用的开发者,掌握这些核心原理都将是你技术栈中不可或缺的一部分。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/45347.html
点赞
0.00 平均评分 (0% 分数) - 0