【原创】修改WIFI保持连接脚本
项目中用到wifi,由于无线网络的不稳定性,可能会造成wifi的掉线,这就需要在程序中判断网络的是否联通,并且能在断线后继续搜寻无线网络并重新连接。
并且因为wifi连接有许多现成的工具,所以在这里就利用shell脚本来实现此功能。
本篇博客主要是记录我修改此脚本到当前项目的记录,包含shell脚本的一些用法和wifi连接工具的用法:
一、初始化函数init_var
init_var() { #until [ -d $SYSFS ] ; do sleep 1; done #find the first useable wifi card local wifi_dev #定义局部变量wifi_dev wifi_dev=$(iwconfig 2>&1 | grep -v "no wireless" ) #查看当前设备有的无线设备,grep -v 指的是去除no wireless这一行 while true; do #无限循环 if [ -z "$wifi_dev" ]; then #判断wifi_dev字符串是否为空 是空则执行下面的命令 sleep 3 wifi_dev=$(iwconfig 2>&1 | grep -v "no wireless" ) else #不为空 获取当前wifi设备名 IFACE=$(iwconfig 2>&1 | grep -v -n "no wireless" | awk '{print $1}' | awk -F: '{print $2}' | grep 0) break fi done # support only pc run dhclient which dhclient #判断 dhclient工具是否存在 if [ $? -ne 0 ]; then RUN_PC=0 else RUN_PC=1 fi if [ "$RUN_PC" = "0" ] ; then DHCP_CLIENT=udhcpc DHCP_CLIENT_OPT=" -i " PING_KEYWORD=round-trip DHCP_WAIT_TIMES=5 else DHCP_CLIENT=dhclient PING_KEYWORD=rtt DHCP_WAIT_TIMES=5 rm -f /var/lib/dhclient/dhclient.leases fi tmpfsloc=$(mount | grep tmpfs | awk '{print $3}' | head -n 1) loc=${tmpfsloc:-/dev} WPA_CONFIGFILE=$loc/wpa_supplicant.conf echo dhcp client app is $DHCP_CLIENT #打印相关信息 echo ping key words is $PING_KEYWORD echo ESSID is $CONF_ESSID echo interface is $IFACE echo run mode is $RUN_MODE }
二、主循环程序如下
while [ -d $SYSFS ] ; do network_connect if [ $? -ne 0 ]; then echo --INFO--:network is disconnected? try to reconnect ifconfig $IFACE 0.0.0.0 setup_wifi fi sleep $CHECK_PERIOD done
network_connect是一个函数,其主要功能是判断网络是否联通,然后是一个判断语句,如过network_connect不成功(返回的不是0),
则执行setup_wifi函数,此函数的主要功能重新设置并连接wifi。如果网络联通则睡眠CHECK_PERIOD秒后再重新判断连接是否正常。
三、判断网络是否连接函数network_connect
network_connect() { #get ip first ifconfig $IFACE | grep -q "inet addr" #判断当前是否有IP地址 if [ $? -ne 0 ]; then echo can\'t find IP return 1 fi #get default gateway route | grep -q default | awk '{print $2}' #获取当前连接路由的网关地址 if [ $? -ne 0 ]; then echo can\'t get default gatway return 1 else SERVER_IP=$(route | grep default | awk '{print $2}') fi if [ -z $SERVER_IP ]; then echo did not get server ip by route, server_ip=$SERVER_IP return 1 fi if ! ping -c $PING_RETRY_COUNT -q $SERVER_IP | grep -q $PING_KEYWORD; then #利用ping命令查看网络是否联通 echo ping $SERVER_IP failed return 1 fi }
四、加入路由函数setup_wifi
setup_wifi() { ifconfig $IFACE down ifconfig $IFACE up #将无线网卡重启 echo start wireless scanning local count=0 until [ $count -ge 3 ] ; do get_auth_mode #获取AP加密方式等信息,如果未找到指定AP,将会返回1 if [ $? -ne 0 ]; then echo "AP $CONF_ESSID not found, sleeping..."; sleep 5; let 'count=count+1'; else break #找到后返回 fi done #scan ok if [ $count -lt 3 ] ; then if [ "$RUN_MODE" = "debug" ] ; then set_wifi_mode return 0 fi fi local index if [ $count -lt 3 ] ; then echo APs list: ${mac_ary[*]} #打印获取后的同名AP列表 echo signal list: ${siglevel_ary[*]} echo sort index: ${sort_ary[*]} for(( i = 1; i <= $AP_COUNT; i++)) #下面的功能是找到最大信号的那个AP 并加入到其中,如果加入不成功,依次加次强的那个 do index=${sort_ary[i]} #the first is most signal bssid=${mac_ary[index]} echo try AP: ${ssid_name_ary[index]} $bssid set_wifi_mode #该函数是设置wifi模式,并调用WPA_CONFIGFILE工具,连接AP if [ $? -ne 0 ]; then echo association with $bssid failed else echo association with $bssid OK break fi done fi }
五、搜寻指定AP,并获得AP加密方式函数get_auth_mode
get_auth_mode() { local grep_expr found local ad_hoc_grep iwlist_log=$(iwlist $IFACE scanning) #扫描所有AP信息 grep_expr="ESSID:\"$CONF_ESSID\"" ad_hoc_grep="Mode:$ADHOC_MODE" local start_line start_line=$(printf "%s \n" "$iwlist_log" | grep -n $grep_expr | awk -F: '{print $1}')#找到符合指定AP名的行 AP_COUNT=$(echo $start_line | wc -w) #判断有几行 echo total ap number is $AP_COUNT #有几行就说明有几个同名AP # if AP_COUNT > 0 if [ $AP_COUNT -gt 0 ]; then #如果大于0就说明找到指定AP found=true else return 1 fi start_line=$(printf "%s \n" "$iwlist_log" | grep $grep_expr -B 2 | grep Cell | awk '{print $2}') #获得全部指定AP名的Cell local i cell for((i = 1; i <= $AP_COUNT; i++ )) #将每个同名AP分离出来 并存到数组内 do cell=$(echo $start_line | awk '{print $('$i')}') get_ssid_str $cell $i #根据Cell编号,获取每个同名AP的加密信息 done #suppose all APs used the same encryption settings, for supporting roaming ssid_str=${ssid_str_ary[1]} #数组内第一个AP就是同名AP中信号最强的 Encryption=$(printf "%s \n" "$ssid_str" | grep Encryption | awk -F: '{print $2}')#下面是获取其加密类型 Auth_Suite=$(printf "%s \n" "$ssid_str" | grep "Authentication Suites" | awk '{print $5}') Group_cipher=$(printf "%s \n" "$ssid_str" | grep "Group Cipher" | head -n 1 | awk '{print $4}') echo --INFO--:Group_cipher=$Group_cipher #Pair_ciper=$(printf "%s \n" "$ssid_str" | grep "Pairwise Ciphers" | awk '{print $5}') if [ "$Auth_Suite" = "802.1X" ]; then #转化为wpa_supplicant对应的加密类型 #Auth_Suite is PSK or 802.1X echo didn\'t support WPA Enterprise, Authentication Suites is $Auth_Suite return 1 fi if [ "$Group_cipher" = "CCMP" -o "$Group_cipher" = "TKIP" ]; then EncrypType=$Group_cipher fi AuthMode=WEP if [ "$Encryption" = "off" ]; then AuthMode= return 0 fi if echo $ssid_str | grep -q "802.11i/WPA2" ; then AuthMode=WPA2 return 0 fi if echo $ssid_str | grep -q "WPA Version" ; then AuthMode=WPA return 0 fi return 0 }
六、加入AP函数set_wifi_mode
set_wifi_mode() { echo auth mode is $AuthMode if [ "$RUN_MODE" = "debug" ] ; then killall $DHCP_CLIENT killall wpa_supplicant sleep 5 ifconfig $IFACE up sleep 2 #iwconfig $IFACE key off iwconfig $IFACE mode $ADHOC_MODE sleep 2 iwconfig $IFACE essid "$DEBUG_CONF_ESSID" ifconfig $IFACE $DEBUG_FIX_IP return fi if [ "$AuthMode" = "WEP" ] ; then #判断加密类型 生成wpa_supplicant所需的.conf文件 local pref if [ "$WEP_KEY_TYPE" = "char" ] ; then pref="s:" fi iwconfig $IFACE key open $pref$PASSWORD [$WEP_KEYINDEX] iwconfig $IFACE essid "$CONF_ESSID" echo try "open" Authentication mode sleep 5 name=$(iwconfig $IFACE | head -1 | awk -F\" '{print $2}') if [ "$name" != "$CONF_ESSID" ];then echo "open" Authentication mode failed, try shard mode iwconfig $IFACE key restricted $pref$PASSWORD [$WEP_KEYINDEX] iwconfig $IFACE essid "$CONF_ESSID" fi elif [ "$AuthMode" = "WPA2" -o "$AuthMode" = "WPA" ] ; then killall wpa_supplicant write_wpa_config #此函数生产.conf文件 sleep 2 ifconfig $IFACE up sleep 2 wpa_supplicant -i $IFACE -B -c $WPA_CONFIGFILE #利用wpa_supplicant工具加AP #wait wpa config, associ sleep 10 else iwconfig $IFACE key off iwconfig $IFACE essid "$CONF_ESSID" fi if [ "$AuthMode" != "WPA2" -a "$AuthMode" != "WPA" ]; then if [ "$SET_MODE" = "yes" ] ; then if [ "$RUN_MODE" = "debug" ] ; then killall $DHCP_CLIENT killall wpa_supplicant sleep 2 ifconfig $IFACE up sleep 2 fi iwconfig $IFACE mode $ADHOC_MODE else iwconfig $IFACE mode $DEFAULT_MODE fi fi #check if successed #判断是否加入成功 ssidname=$(iwconfig $IFACE | grep $IFACE | awk -F: '{print $2}' | awk '{print $1}') cur_bssid=$(iwconfig $IFACE | grep "Access Point:" | awk '{print $6}') cur_mode=$(iwconfig $IFACE | grep Mode | awk -F: '{print $2}' | awk '{print $1}') echo $ssidname $cur_bssid $cur_mode if [ "$ssidname" != "\"$CONF_ESSID\"" -o "$bssid" != "$cur_bssid" \ -o "$cur_mode" != "$DEFAULT_MODE" ]; then #fail return 1 fi if [ -z $FIX_IP ] ; then dhcp_pc dhcp_ok=$(ifconfig $IFACE | grep "inet addr" | awk '{print $1}') if [ -z $dhcp_ok ]; then return 1 fi else ifconfig $IFACE $FIX_IP fi if [ "$RUN_MODE" != "debug" ] ; then route add default gateway $SERVER_IP $IFACE fi return 0 }
七、生产wpa_supplicant所需.conf文件函数
write_wpa_config() { #init wpa_supplicant.conf file if [ -f $WPA_CONFIGFILE ]; then rm -f $WPA_CONFIGFILE fi cat >$WPA_CONFIGFILE<<-EOF ctrl_interface=/var/run/wpa_supplicant network={ ssid="$CONF_ESSID" bssid=$bssid scan_ssid=1 key_mgmt=WPA-PSK proto=$AuthMode pairwise=$EncrypType group=$EncrypType psk="$PASSWORD" } EOF }
至此,此脚本全部结束,这个脚本的最好处在于支持wifi信号的漫游。