![为什么 bash 脚本不使用导入的文本文件数据来运行整个代码?](https://linux22.com/image/208366/%E4%B8%BA%E4%BB%80%E4%B9%88%20bash%20%E8%84%9A%E6%9C%AC%E4%B8%8D%E4%BD%BF%E7%94%A8%E5%AF%BC%E5%85%A5%E7%9A%84%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E6%95%B0%E6%8D%AE%E6%9D%A5%E8%BF%90%E8%A1%8C%E6%95%B4%E4%B8%AA%E4%BB%A3%E7%A0%81%EF%BC%9F.png)
我想将 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
前面的。curl
ip.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 - <<EOJSON
和JSON )
- 可能会让人困惑,但注释行可以帮助解决这个问题。在我看来,当下一个使用脚本的编码人员更容易理解 JSON 时,这是值得的。或者您可以将 JSON 全部放在一长行中。这里的文档仍然会减少您需要使用单引号和双引号字符玩的游戏。
我将此处的文档用于其他复杂的字符串,这些字符串希望在从 shell 变量构建的某些元素周围使用引号。jq
我想到的是JMESPath 查询和 MySQL 命令。
我倾向于不在脚本中缩进此处的文档。在大多数 shell 中,缩进结束行(EOJSON
在本例中)需要使用制表符,这些制表符很容易被重写为空格,从而破坏此处的文档。缩进 JSON 行但不缩进结束行可能比没有缩进任何行时更令人困惑,并用注释进行解释。这也只是我个人的看法。