用Expect连接无线网络

垃圾的无线网卡驱动

我的无线网卡是 Broadcom BCM57780,这个东西,Linux下的无线驱动做得非常烂。以前我用Gentoo Portage中的net-wireless/broadcom-sta,后来听 microcai 的,直接在 menuconfig 里配置。这个驱动对应的模块名称是 brcmsmac,必须编译成模块(编译进内核的话,我没成功打开无线过)。它还需要 firmware,而且路径是定死的(使用其他名称是不行的,至少我没成功)。它在 dmesg 中的信息非常简略,如果你 firmware 的路径配置错的话,每次启动有一定机率 dmesg 会提示你正确的路径(这个……)。

这个驱动,偶尔会造成 kernel panic,掉线也挺频繁的,其实要连线都很困难……

以前我都是用wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf后在wpa_cli里输入select_network,然后间断性输入status希望出现一个rwpa_state CONNECTED,这样就连上了。如果十几秒还没连上的话,就不用指望再过几分钟它会连上。我一般是 kill 掉 wpa_supplicant 再来。有时如此几次还是不行,我就用modprobe重新加载brcmsmac.ko,如果再不行我就该重启了。

用 Expect 自动化连接过程

#+BEGIN_SRC tcl -n
#!/bin/sh
# -*- tcl -*- \            (ref:1)
exec tclsh "$0" "$@"       (ref:2)

package require Expect

for {set i 0} {$i < 5} {incr i} {
    catch {system wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf}
    catch {system wpa_cli select_network 0}

    for {set try 0} {$try < 12} {incr try} {
        spawn wpa_cli status
        expect {
            -re {wpa_state=(.*)\r} {
                if {$expect_out(1,string) eq "COMPLETED"} {
                    system dhcpcd wlan0
                    exit
                }
                sleep 0.7
            }
            -re .+ exp_continue
            default
        }
        wait
    }
    catch {system killall wpa_supplicant}
    catch {system modprobe -r brcmsmac}
    catch {system modprobe brcmsmac}
}

注意 (ref:1) (ref:2) 这两行,这里用了一个技巧,就是 sh 的 # 注释是不续行的,而 Tcl 的是续行的(Makefile 也续行)。如果用 sh 执行,就会执行行 (ref:2),用 tclsh 来解释这个脚本。tclsh 则会忽略行 (ref:2)。