You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本创建Docker缺失网络的字段提取问题及解决

问题:从.env文件创建缺失的Docker网络并匹配子网

我需要编写Shell脚本,从.env变量文件中创建尚未存在的Docker网络,同时为缺失的网络匹配对应的子网(子网信息也来自该文件)。

初始脚本

#!/bin/bash

# create tempfiles
TMPFILE=$(mktemp)
TMPFILE2=$(mktemp)
TMPFILE3=$(mktemp)

# search for networks in .env file with VARIABLE_NAME
< .env grep '_NET=' | grep -v '#' | sort | cut -d "=" -f2 > "${TMPFILE}" 2>&1

# search for subnetworks in .env file with VARIABLE_NAME
< .env grep '_NET_SUBNET=' | grep -v '#' | sort | sed 's/[^0-9]*//' > "${TMPFILE2}" 2>&1

# Merge
paste -d ' ' ${TMPFILE2} ${TMPFILE} >> ${TMPFILE3}

mapfile -t lines_array < "${TMPFILE3}"

for line in "${lines_array[@]}"; do
    #echo "$line" | awk '{print $2}'
    docker network ls | grep "$line"
    if [ "$(docker network ls | grep -c "$line" | awk '{print $2}' )" == 0 ]
    then
        echo "network $line not exist"
        echo "docker network create -d bridge --subnet=$line"
    else echo "network $line exists"
    fi

done

.env文件内容

# Network
## traefik proxy network
TF_PROXY_NET=traefik_proxy_net
## subnet network traefik extern
TF_PROXY_NET_SUBNET=172.30.0.0/16
## crowdsex network
CS_NET=crowdsec_net
## subnet network crowdsec
CS_NET_SUBNET=172.31.0.0/16
## docker-socket-proxy network
DSP_NET=dsp_net
##  subnet network docker-socket-proxy
DSP_NET_SUBNET=172.32.0.0/16

实现思路

  • 从.env文件提取网络变量,排序后存入临时文件TMPFILE
  • 从.env文件提取子网变量,排序后存入临时文件TMPFILE2
  • 将TMPFILE2与TMPFILE内容合并,存入TMPFILE3

TMPFILE3输出内容:

172.31.0.0/16 crowdsec_net
172.32.0.0/16 dsp_net
172.30.0.0/16 traefik_proxy_net

到这一步逻辑可行,只是稍显繁琐。

当前Docker网络列表

NETWORK ID     NAME                DRIVER    SCOPE
befbc543b385   bridge              bridge    local
34604e449c61   host                host      local
489eb654d1de   none                null      local
b0520be90b41   traefik_proxy_net   bridge    local
1709315fb264   wikijs_default      bridge    local

遇到的问题

我需要从line变量中提取第二个字段(例如line为172.31.0.0/16 crowdsec_net时,第二个字段是crowdsec_net),单独执行echo $line | awk '{print $2}'可以正常输出网络名称,但在判断语句if [ "$(docker network ls | grep -c "$line" | awk '{print $2}' )" == 0 ]中无法正常工作——因为$line会被当作完整字符串传入,导致无法匹配到对应的Docker网络。

临时解决方案

mapfile -t lines_array < "${TMPFILE3}"

for line in "${lines_array[@]}"; do

    docker network ls | grep "$line"
    if [ "$(docker network ls --format "{{.Name}}" | while read i; do echo $i $(docker network inspect $i | grep Subnet | tr -d '"' | sed -e 's/\<Subnet\>//g ' | tr -d ":" ); done | grep "$line" | wc -l )" == 0 ]
    then
        echo "network $line not exist"
        echo "docker network create -d bridge --subnet=$line"
    else echo "network $line exists"
    fi

该命令会查找Docker网络及其关联子网,匹配TMPFILE3中的格式,输出如下:

network crowdsec_net 172.31.0.0/16 not exist
docker network create -d bridge --subnet=crowdsec_net 172.31.0.0/16
network dsp_net 172.32.0.0/16 not exist
docker network create -d bridge --subnet=dsp_net 172.32.0.0/16
network traefik_proxy_net 172.30.0.0/16 exists

最终可用脚本

感谢@Gilles Quénot和@markp-fuso的帮助,最终脚本参考@markp-fuso的方案:

#!/bin/bash

while read -r status line
do
    printf "\n########## %s : %s\n" "${status}" "${line}"

    if [[ "${status}" = 'create' ]]
    then
        echo "network '${line} not exist"
        echo "docker network create -d bridge --subnet=${line}"
    else
        echo "network ${line} exists"
    fi
done < <( awk -f env.awk <(docker network ls) .env )

内容的提问来源于stack exchange,提问作者Andre Semek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 15:45:55