为什么 bash 脚本不使用导入的文本文件数据来运行整个代码?

为什么 bash 脚本不使用导入的文本文件数据来运行整个代码?

我想将 Cloudflare WAF 中存储的 IP 地址列表的文本文件列入白名单。为此,我使用以下包含 bash 脚本的 Cloudflare API4 curl。

此 Cloudflare API 脚本无法使用导入的 IP 地址数据。当我调试时,它显示“无效 IP 地址”消息(来自 Cloudflare 端)。

我想从单独的文本文件加载此脚本的 IP 地址数据。

如何从文件导入数据?

我本地保存的文件包含以下格式的数据。

123.123.123.124 
123.123.123.57 
123.123.123.91

这是 Cloudflare IP 白名单脚本。

#!/bin/bash
    
input="/var/download/ip.txt"
while IFS= read -r line
do
  echo "$line"
done < "$input"
    
    for i in "${line[@]}"
    do
       : 
       # do whatever on $i
        echo $i
        curl -X POST "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules" \
             -H "X-Auth-Email: myemail" \
             -H "X-Auth-Key: globle API key" \
             -H "Content-Type: application/json" \
             --data '{"mode":"whitelist","configuration":{"target":"ip","value":"'$i'"},"notes":"Google Bot IP"}'

    done

答案1

以下是我实现此脚本的方式重击(根据原来的问题)。某些部分与您的示例不同,我将解释为什么我建议它们。

#!/bin/bash

# the IP addresses are in a file, one per line
ip_file='/var/download/ip.txt'

# get the IP addresses from the file into an array
while read -r ip_line
do
  ip_list[${#ip_list[@]}]="${ip_line}"
done < "${ip_file}"

# was the file empty?
[[ ${#ip_list[@]} -lt 1 ]] && {
  echo "$0: Error, no ip addresses in ${ip_file}" >&2
  exit 1
}

# parameterize the unchanging parts of the curl commands
url='https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules'
my_email='my-email@my-domain'
api_key='1234567890abcdef'

# loop through the list of IPs
for ip_addr in "${ip_list[@]}"
do
  # use a here document to put the IP into the json blob
  # (the here document is not indented)
  whitelist_json=$(cat - <<EOJSON
{
  "mode":"whitelist",
  "configuration": {
    "target": "ip",
    "value": "${ip_addr}"
  },
  "notes":"Google Bot IP"
}
EOJSON
)

  # tell my user what I'm doing
  echo "Submitting whitelist for IP ${ip_addr}"

  # the curl command to submit the address
  echo curl \
  -X POST "${url}" \
  -H "Content-Type: application/json" \
  -H "X-Auth-Email: ${my_email}" \
  -H "X-Auth-Key: ${api_key}" \
  --data "${whitelist_json}"
done

在对文件运行它并验证它生成正确的命令参数后,删除echo前面的。curlip.txt

如果你的文件有 Unix/Linux 行结尾,那么你可以用一行ip.txt替换循环的四行:while read ...

readarray -t ip_list < "${ip_file}"

readarray方法只有一行并且相当不言自明。另一方面,while read ...循环使您有机会在将${ip_line}值保存到数组之前更改该值。也许是为了去掉前导/尾随空白字符,或者测试该行是否为空等。

将值保存到数组中的语句是我push(array, value)在Bash中实现操作的方法,它没有push()。本质上,它获取数组的当前长度,并使用该数字作为下一个元素的索引来保存新值。

URL、电子邮件地址和 API 密钥被放入变量中,以保持curl参数的长度简短且易于理解,但这是我个人的偏好。

对于 JSON blob(数据结构),我发现用 shell 组装它要容易得多Here Document。单引号和双引号字符不会从字符串中删除,您可以使用多行缩进,使 JSON 可供可能需要更改它的人读取。使用此处文档的周围结构 -$(cat - <<EOJSONJSON )- 可能会让人困惑,但注释行可以帮助解决这个问题。在我看来,当下一个使用脚本的编码人员更容易理解 JSON 时,这是值得的。或者您可以将 JSON 全部放在一长行中。这里的文档仍然会减少您需要使用单引号和双引号字符玩的游戏。

我将此处的文档用于其他复杂的字符串,这些字符串希望在从 shell 变量构建的某些元素周围使用引号。jq我想到的是JMESPath 查询和 MySQL 命令。

我倾向于不在脚本中缩进此处的文档。在大多数 shell 中,缩进结束行(EOJSON在本例中)需要使用制表符,这些制表符很容易被重写为空格,从而破坏此处的文档。缩进 JSON 行但不缩进结束行可能比没有缩进任何行时更令人困惑,并用注释进行解释。这也只是我个人的看法。

相关内容