最可靠方式是利用networksetup配合“网络位置”机制:先创建多个预设dns的位置,再用networksetup -switchlocation命令切换,dns随位置自动生效,切换后需执行sudo dscacheutil -flushcache && sudo killall -hup mdnsresponder刷新缓存。
macos 通过脚本自动切换 dns,最可靠、原生支持的方式是利用 networksetup 工具配合“网络位置”(location)机制——它不依赖第三方工具,配置永久生效,且能随位置切换自动应用整套网络参数(dns、ip、代理等)。
用 networksetup 切换位置实现 DNS 自动切换
这是推荐的主力方案:每个“网络位置”可预设专属 DNS,脚本只需切换位置,DNS 就同步更新。
- 先在系统设置中创建多个位置,例如:“家庭-公共DNS”(配 1.1.1.1 和 223.5.5.5)、“公司-内网DNS”(配 192.168.10.2 和 114.114.114.114)
- 终端执行命令即可一键切换:
sudo networksetup -switchlocation "公司-内网DNS" - 切换后建议刷新 DNS 缓存,避免旧解析残留:
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder - 验证是否生效:
scutil --dns | grep nameserver或networksetup -getdnsservers Wi-Fi(服务名需匹配当前活跃接口)
直接为指定服务设置 DNS 的脚本化方式
适用于无需完整位置切换、仅需快速更新某接口 DNS 的场景(如临时调试)。
- 先查出当前活跃的服务名:
networksetup -listallnetworkservices | grep -v "\*" | tail -n +2 - 获取真实启用的服务(更稳妥):
route -n get default 2>/dev/null | awk '/interface:/ {print $2}' | xargs -I{} networksetup -listnetworkserviceorder | grep -A1 "{}" | grep "Hardware Port" | cut -d: -f2 | sed 's/^ *//' - 设置 DNS(以 Wi-Fi 为例):
sudo networksetup -setdnsservers "Wi-Fi" 8.8.8.8 1.1.1.1 - 恢复 DHCP 自动获取 DNS:
sudo networksetup -setdnsservers "Wi-Fi" empty
增强脚本健壮性的关键细节
避免硬编码服务名或失败静默,提升多语言/多设备兼容性:
- 脚本开头加
export LANG=C,确保networksetup输出稳定(不受系统语言影响) - 用
networksetup -listlocations动态检查目标位置是否存在,再执行切换 - 判断当前连接类型(Wi-Fi / Ethernet / USB 网络共享),再决定操作哪个服务,而非固定写死 “Wi-Fi”
- 添加简单错误提示,比如:
if [ $? -ne 0 ]; then echo "切换失败,请检查位置名称是否正确"; exit 1; fi
不需要安装额外工具,系统自带命令就能完成。关键是把 DNS 当作“位置的一部分”来管理,而不是孤立修改——这样才真正符合 macOS 的设计逻辑,也最稳定。











