macOS 断开指定 Wi-Fi 时,自动恢复 IP

 

2019-11-17

上一篇写到当 macOS 连接到指定的 Wi-Fi 时,可以自动打开或退出应用。其实当完成这个功能的时候,冒出了令一个类似需求,虽然用到的机会不多,但需要用时还比较麻烦,于是顺便一起实现了。

设置静态 IP

其实大部分环境无线网络一般都不需要设置静态 IP,只是恰好办公网络便是其中例外之一,所以也就只能乖乖使用指定 IP 连接。

把 Hammerspoon API 从头到尾看了一遍(并没有),也没有找到能设定 IP 和 DNS 的 API,查看的倒是有。不过还好有 hs.execute, 可以运行 Shell 命令。

既然要用到 Shell,自然得先知道什么命令可以设定 IP 啦。说来也巧(惭愧),刚好在上周收集了在 macOS 中设置 IP 地址的方法,自然,macOS 不可能像 Linux 那么变态的需要你手动修改文件。

在 Shell 中的操作:

Terminal window
1
# 设置静态 IP
2
networksetup -setmanual "Wi-Fi" <IP> <掩码> <网关>
3
4
# 设定 DNS
5
networksetup -setdnsservers "Wi-Fi" <dns1> <dns2>
6
7
# 恢复 IP 为自动获取
8
networksetup -setdhcp "Wi-Fi"
9
10
# 恢复 DNS 为自动获取(将清除 所有DNS)
11
networksetup -setdnsservers "Wi-Fi" empty

是不是超简单,两行代码便完成了 IP 和 DNS 的设定,既然知道了如何在 Shell 中设置 IP,那么是时候祭出 Hammerspoon 了:

1
-- 设置静态 IP
2
hs.execute('networksetup -setmanual "Wi-Fi" 10.1.1.42 255.255.255.128 10.1.1.1')
3
4
-- 设置 DNS
5
hs.execute('networksetup -setdnsservers "Wi-Fi" 10.1.1.10 10.1.1.24)

同样超简单的,对不对,在上一篇的代码中再加个 elseif 判断即可。

另外需要说明的是,其中的 Wi-Fi 是指无线网卡的名称,macOS 下默认都是 Wi-Fi,后面的 IP 地址用空格隔开即可。多说一句,可以先在 Console 中执行试试是否正常,然后再写到实际代码中,其他代码也可以如此。

当断开 Wi-Fi 时

如果只是简单的在连接 Wi-Fi 后设置 IP,其实没必要再另写一篇,主要原因是 Hammerspoon 并没有能直接判断当前是连接 Wi-Fi 还是断开 Wi-Fi 的 API,仅有一个用于获取当前 Wi-Fi 的 currentNetwork

在没有 API 的情况下,判断是否从指定网络断开,需要两个数据,一个是断开前的 Wi-Fi 名称,另一个是需要知道已经断开 Wi-Fi。不过好在 Hammerspoon 留了余地,currentNetwork 除了获取连接时的 Wi-Fi 名称之外,当断开 Wi-Fi 时,会返回 nil,我们便可以以此判断是否为断开状态。

获取断开状态很简单,if not currentNetwork (与 if currentNetwork == nil 等同),最开始是困在了如何获取断开前 Wi-Fi 名称,其实只要保存断开前的一个 Wi-Fi 名称即可,明白后也很简单。另外,写代码时有一个重要失误是把代码放在在 watcher 外面,导致一直无法获取正确的 Wi-Fi 名称。

下面是用于获取断开前 Wi-Fi 名称和判断断开指定 Wi-Fi 时的操作:

1
local oaWifi = "OA"
2
3
-- 这样就可以保存断开前的 Wi-Fi 名称了
4
if hs.wifi.currentNetwork() then
5
prevWifi = hs.wifi.currentNetwork()
6
end
7
8
-- 断开 oaWifi 时,恢复 IP,并重新设定 DNS
9
elseif prevWifi == oaWifi and currWifi == nil then
10
hs.execute('networksetup -setdhcp "Wi-Fi"')
11
hs.execute('networksetup -setdnsservers "Wi-Fi" empty')
12
hs.execute('networksetup -setdnsservers "Wi-Fi" 8.8.8.8 114.114.114.114')

要注意的是如果先判断 currWifi 是否为 nil,这段代码永远都不会执行成功,测试时被这个坑惨,不知道是 BUG,还是语法特性。

另外,可以在代码中使用 hs.noify.showhs.alert.show 显示通知,我用的是前者,调用的是系统通知模块,显示在右上角(前提是别把 Hammerspoon 的通知关了)。

1
-- 在 hs.execute 后面加上这句即可,当然可以修改为其他文字
2
hs.notify.show("IP 设置成功", "", "")

最后

其实这两篇主要是讲当连接或断开特定 Wi-Fi 时,执行指定操作,打开 / 关闭应用和设置 IP 地址其实其中的两个例子,只要是想在连接特定 Wi-Fi 后,需要执行的任意功能均可。

另外,发现变唠叨了许多,以往一句话讲完的事情,现在非得扯上半天,也不知是好是坏。不过姑且这样,至少有变化是好事。

信息

版本

  • macOS:macOS Catalina 10.15.1
  • Hammerspoon:Version 0.9.76 (5104)

参考

hs.execute