Bash脚本中nmcli命令的DNS变量包裹转义问题求助
问题:Bash脚本调用nmcli时的参数解析错误
我编写了一个Bash脚本用于随机修改网络DNS服务器,逻辑如下:
- 统计
public-dns.txt文件中可用DNS服务器的数量; - 随机选择3个DNS服务器IP;
- 将IP拼接为空格分隔的字符串;
- 去掉字符串末尾的空格并包裹双引号;
- 将变量传入nmcli命令执行。
脚本代码
servers=$(wc -l public-dns.txt) for i in `shuf -i 1-$servers -n 3`;do string+=$(sed -n "${i}p" public-dns.txt) string+=" " done string="\""${string::-1}\"" #也尝试过"\"""${string::-1}""\"" echo $string #仅用于检查变量是否正确转义和包裹 nmcli c mod tp ipv4.ignore-auto-dns yes systemctl restart NetworkManager
运行报错
user@debian:~/dns$ bash test "80.27.2.223 134.255.241.139 89.7.235.170" Error: invalid or not allowed setting '134': '134' not among [connection, 802-11-wireless (wifi), 802-11-wireless-security (wifi-sec), 802-1x, ethtool, match, ipv4, ipv6, hostname, tc, proxy].
手动执行nmcli c mod tp ipv4.dns "92.190.137.96 92.43.224.1 92.53.204.219"可以成功修改DNS,说明问题出在变量的转义/包裹方式上。
错误原因
你手动执行时的双引号是Shell语法层面的引号,作用是告诉Shell将引号内的内容当作单个参数传递给nmcli;但你在变量里直接添加了"字符,导致Shell解析后,nmcli实际收到的参数是拆分后的多个部分:"80.27.2.223作为第一个参数,134.255.241.139被当成了无效的设置项,因此触发报错。
同时原脚本还有一个隐藏bug:wc -l public-dns.txt会输出行数 文件名格式的内容(比如10 public-dns.txt),导致shuf -i 1-$servers无法正确生成随机范围。
正确解决方法
方法1:用数组处理更简洁可靠
# 读取所有DNS到数组中 mapfile -t dns_list < public-dns.txt # 随机选3个IP,拼接为空格分隔的字符串 selected_dns=$(printf "%s\n" "${dns_list[@]}" | shuf -n3 | tr '\n' ' ') # 去掉末尾多余的空格 selected_dns=${selected_dns% } # 调用nmcli时用双引号包裹变量,确保作为单个参数传递 nmcli c mod tp ipv4.dns "$selected_dns" nmcli c mod tp ipv4.ignore-auto-dns yes systemctl restart NetworkManager
方法2:修复原脚本的变量处理逻辑
# 修复wc -l的输出,只获取行数数字 servers=$(wc -l < public-dns.txt) string="" for i in $(shuf -i 1-$servers -n 3);do string+=$(sed -n "${i}p" public-dns.txt) string+=" " done # 去掉末尾空格,不要给变量添加引号字符 string=${string::-1} # 调用nmcli时用双引号包裹变量,让Shell将其作为单个参数传递 nmcli c mod tp ipv4.dns "$string" nmcli c mod tp ipv4.ignore-auto-dns yes systemctl restart NetworkManager
内容的提问来源于stack exchange,提问作者achille
相关产品推荐
相关产品推荐

