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

Bash脚本中nmcli命令的DNS变量包裹转义问题求助

问题:Bash脚本调用nmcli时的参数解析错误

我编写了一个Bash脚本用于随机修改网络DNS服务器,逻辑如下:

  1. 统计public-dns.txt文件中可用DNS服务器的数量;
  2. 随机选择3个DNS服务器IP;
  3. 将IP拼接为空格分隔的字符串;
  4. 去掉字符串末尾的空格并包裹双引号;
  5. 将变量传入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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 01:22:20