I have a Python/Flask web app on a Raspberry Pi that calls the following bash script (connect_to_wifi) to connect to WiFi:
sudo killall wpa_supplicant
sudo wpa_supplicant -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf
sudo dhclient wlan0
Basically, a user enters their WiFi credentials, which are saved in wpa_supplicant.conf
, and then this script is run. It works great...however, if they mistype their credentials, dhclient hangs forever before failing.
What I want to do is detect if the credentials are correct before proceeding with dhclient. I know that I can check the output of the wpa_supplicant
command for a 4-Way Handshake failure if creds are wrong, but when I call this script from my Python app via:
p = Popen(['connect_to_wifi'], stdout=PIPE, bufsize=1)
with p.stdout:
for line in iter(p.stdout.readline, b''):
print line,
p.wait()
None of the output from the sudo wpa_supplicant -i...
line is being captured. All I want to do is end immediately if I detect a handshake failure, but I'm having trouble capturing the output in Python.
John Bullard's answer was really clean and solid, but I was having trouble getting it to work consistently because of the comment I made on it:
There is a brief period where iw wlan0 link says it is connected even if invalid credentials are entered in wpa_supplicant.conf. I'm assuming it connects, then verifies creds, and if they're wrong, disconnects. So this script doesn't actually work, at least not every time.
What I ended up doing, with help from that answer, is using the -f flag for wpa_supplicant
and writing the output of wpa_supplicant to a file. The while loop then greps for the connected status, in which case it will call dhclient
. If it doesn't connect, it will either time out or result in a 4-way handshake failed (if the latter, the script will end earlier).
#!/bin/bash
sudo ip addr flush dev wlan0
sudo killall wpa_supplicant
sudo truncate -s 0 wifi_connection_status.txt
sudo wpa_supplicant -B -i wlan0 -f wifi_connection_status.txt -c /etc/wpa_supplicant/wpa_supplicant.conf
declare -i i=0
declare -i timeout=15
while [ $i -le $timeout ]; do
if grep -iq 'CTRL-EVENT-CONNECTED' wifi_connection_status.txt; then
sudo dhclient wlan0
exit 2
elif grep -iq '4-Way Handshake failed' wifi_connection_status.txt; then
exit 2
fi
(( i++ ))
sleep 1
done