断网?不存在的——利用Linux脚本智能重启虚拟机环境下的软路由
追加修改(2021-03-18 14:22:30):
Proxmox VE的公钥配对文件authorized_keys在/etc/pve/priv下
Proxmox VE无须Linux远程SSH登录,直接在PVE的Shell里就可以运行定时任务,以下是脚本
#!/bin/bash
var=$(ping -c 3 114.114.114.114 | grep "ttl=")
if [[ $var =~ "ttl=" ]]
then
date -R >> ~/time.txt
echo '吴彦祖你好,网络正常' >> ~/time.txt
else
date -R >> ~/time.txt
echo '老子重启过~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' >> ~/time.txt
qm stop 400
qm stop 200
qm stop 100
reboot
fi
追加修改(2020-04-18 13:41:55):
Proxmox VE的公钥配对文件authorized_keys在/etc/pve/priv下
你是不是也和我一样,出门在外时总有一种强烈的不安?害怕家里突然断网,然后各种智能设备集体瘫痪。特别是像我这种养猫人士,每天都要通过智能摄像头看一下家里的情况,生怕主子把家拆了……年关将近,不在家的时候越来越频繁,这种不安也是随之增加。
断网分2个种情况,一种是外部因素,比如家里停电了、电信的设备抽风了、海底光缆又挖断了等等,这属于不可抗力,无解。另一种是内部因素,绝大部分都是路由器抽风了,这种情况通常手动重启一下路由器就能解决。
那么,有没有一个不需要人为干预的办法,自动修复断网的问题呢?首先我考虑过智能插座,但是很快就否决了,因为如果家里断网了,智能插座也会停止工作,更不可能远程控制插座。机械式的定时插座看起来是个不错的选择,可以设定好时间,强制断电后再恢复供电,实现重启无线路由器或者软路由的目的。但是这种方案的问题在于,突然断电对硬盘极为不利,有可能造成数据丢失,对NAS用户无疑是一剂毒药。更何况,不管是否断网,定时插座都会在设定好的时间强行断电,日复一日。
后来我想到一个终极方案,用树莓派做一个小机器人,当检测到家里断网的时候,让机器人去捅机箱上的电源键,捅两次,一次关机,一次开机。但是理想很丰满,现实却过于硬核,不仅成本高,而且还只能自娱自乐,不能将这种方案推而广之。
最后选择了退而求其次的方案,利用Linux的Shell脚本,检测网络是否通畅,如果不通,重启路由器或者软路由主机。硬件都重启了,应该能解除绝大部分故障了。俗话说,有问题,先重启嘛。没人帮忙执行这个操作,就让脚本来代劳。
大佬们看到这里应该可以就此打住了,如果这个方案能给你启发,我想你能用到更高级的办法,写出更漂亮的脚本。但还有很多像我这种完全没有编程经验,Linux仅入门水平的战五渣,对于我们这个群体来说,一切都是从头开始。
废话有点多,下面进入正题,详细记录一下实践过程,同时把我遇到的坑一一列举,如果你也是战五渣,这些坑你也会遇到。
一、改造设备,用虚拟机搭建软路由
其实Shell脚本在智能路由器上也能运行,但是路由器的工作也挺繁重的,比如广告过滤、酸酸乳、DDNS等,因为各种玄学问题,脚本经常无法自动运行起来。当然,败家之眼这类高端路由器应该能稳定运行,我没用过,不作讨论。TP-LINK这类非智能路由器也不作讨论了,因为运行不了Shell。
在稳定压倒一切的大前提下,用虚拟机上软路由才是王道。硬件采购就不细说了,上闲鱼挑一件趁手的兵器吧,成品软路由或者“低功耗板U套装+多口网卡”都行,CPU支持VT-x是底线,能支持VT-d和AES更好。
软件方面,先说底层虚拟机S,比较主流的OS是有ESXI、PVE和Unraid。我个人选择的是ESXI,毕竟是企业级的商业软件(某些问题不用担心,你懂的),非常稳定,易用性也比较高。相比之下,开源的PVE在稳定性方面就弱一些。Unraid我也试过,易用性比ESXI差远了,而且在我的那套硬件上,网卡直通太难搞了,要么全通,要么全不通。(当然,网卡直通关乎软路由的网络性能,与稳定性无关)
系统方面,主路由我选择的是爱快,国产老牌,更新频繁,稳定高效,论坛活跃,且官方技术人员回复及时。旁路由我选择的是Koolshare的LEDE,别问我为什么不用L大的LEDE,我特么注册不了恩山帐号。花钱注册?别开玩笑了,白嫖是我的信仰!为了稳定运行脚本,我又装了大名鼎鼎的CentOS,这个不用我多说,稳定性在Linux里数一数二。
软路由系统的搭建我就不写了吧,因为写这个又是长篇大论了,更何况本站已经有很多大佬发表了相关文章。去爬一下大佬的贴子,先让软路由能正常工作吧。这里我想提示一下,双软路由不是必须的,单独装一个爱快,或者一个LEDE,都是可以的。双软路由只是为了提供更多可玩性,与Shell脚本运行稳定与否无关。在脚本运行的过程中,脚本只与底层OS通讯,与主路由和旁路由都没有关系。所以,需要给底层OS配置好固定IP地址。如果你需要做直通,请务必留一个网口不直通,并且在后面的调试脚本过程中,将你的笔记本插到这个网口上。因为在调试过程中,需要频繁重启软路由,在重启的过程中,直通网口是不工作的。
如果你的软路由正常工作了,那么,再开一个虚拟器(分配512M内存就够了)安装CentOS也是易如反掌的,基本没什么难度。安装时选最小化安装就行,不需要GUI界面。安装好以后,需要简单配置一下。
CentOS 8镜像下载地址:http://isoredirect.centos.org/centos/8/isos/x86_64/CentOS-8-x86_64-1905-dvd1.iso
二、配置CentOS的IP地址
用root帐号登录进系统后
进入目录
cd /etc/sysconfig/network-scripts
浏览文件名
ls
编辑找到的文件,只有一个文件,ifcfg-xxx
vim ifcfg-xxxx
修改BOOTPROTO和ONBOOT参数
BOOTPROTO=static
ONBOOT=yes
增加下列语句
IPADDR=192.168.2.5 (这个IP地址根据你自己的实际情况来)
NETMASK=255.255.255.0
GATEWAY=192.168.2.2 (网关指向旁路由,如果没有旁路由,指向主路由)
DNS1=114.114.114.114
保存后退出vim,输入init 6回车,重启CentOS,让网络配置生效。
对于Windows用户来说,第一次使用vim(或者vi)的体验,令人抓狂,把电脑砸了的心都有。深呼吸,跟着我,左手右手几个简单的慢动作……首先,进入vi以后,在没按任何键之前,这个时候vi处于待机状态。按一下键盘上的i,进入插入状态,这时候可以对文件内容进行修改,用方向键移动光标。修改完以后,按Esc键回到待机状态。这时,在键盘上输入:wq后回车,可保存文件并退出vi。如果不想保存文件直接退出,输入:q!后回车。总之,我们只需要用到这几个最基本的动作,即 i键,Esc键,:wq,:q!
三、调整时区和对时
百度上相关文档太多了,大部分都不起作用。我分析可能是不同的Linux版本造成的,坑我都踩过了,附上在CentOS 8下能对时成功的链接,照做就行了。
CentOS系统设置北京时间:https://jingyan.baidu.com/article/597a0643a082a9712a52435a.html
四、让CentOS能远程SSH登上底层OS
如果你的底层OS不是ESXI,那么简单了(ESXI用户可略过此部分)
先输入yum install expect,安装一下这个自动交互的小插件。然后
进入/opt目录,为什么进这里?因为这里面是空的,看着干净
cd /opt
创建一个执行文件,文件名随意,我这里就是a.sh
vim a.sh
按i键切换到插入状态,把下面语句粘贴进去,然后:wq保存。粘贴后请删掉括号里的字,以及多余的空格。后面的操作也是如此。(windwos有个软件叫putty,建议用这个,先SSH登录到CentOS,再进入vim进行复制或粘贴的操作。复制功能是鼠标左键圈选,选好了以后就自动复制了。粘贴是按一下鼠标右键。)
#!/usr/bin/expect -f
#!/bin/bash
set user root
set timeout 2
spawn ssh -o StrictHostKeyChecking=no $user@192.168.2.200 uname -a
(这里输入你底层OS的IP地址)
expect "*password"
(当expect匹配到password这个提示后,执行下一句。此项不用改)
send "xxxxxxx/r"
(把xxxxxx替换为底层OS的root密码,并且保留/r)
expect EOF
赋予a.sh执行权限
chmod 777 /opt/a.sh
测试一下这个脚本
/opt/a.sh
如果有问题,百度一下相关代码,我这里不便列举。
如果没问题,会显示出你的底层OS的版本号。这时再进vim编辑一下这个脚本,把uname -a替换成init 6,然后保存退出。该文件备用,暂时不用调试。
如果你是ESXI用户,expect交互对ESXI不起作用,需要制作公钥并配对,配对成功后,可以免去上面那个脚本。
a.ESXI默认是不开启SSH功能的,需要手动开启。把软路由主机的显示器和键盘接上,在ESXI的待机界面按F2,输入密码以后,按下图操作
b.把ESXI的密码锁解除掉,因为ESXI在输错5次登录密码后,会强制锁定900秒,如果继续输错,会累加900秒。另外,锁了以后也不提示一下,我曾经试密码试到怀疑人生,甚至还重装了一次ESXI。
c.用putty的SSH协议登录进CentOS,然后输入
ssh-keygen -t rsa
然后一路潇洒地回车,然后在/root/.ssh目录下会产生2个文件,我们显示出其中1个文件的内容
cat /root/.ssh/id_rsa.pub
d.用putty的SSH协议登录进ESXI,然后输入
vi /etc/ssh/keys-root/authorized_keys
进去以后是空的,按i键进行插入模式,把刚才复制的那串代码粘贴进来,按:wq走人。
这样两个系统之间的公钥配对就完成了。
e.回到CentOS,试一下效果,输入
ssh 192.168.2.200 (这里的IP是你的ESXI的IP)
如果不报错,就说明成功了,可以用uname -a确认。(第一次登录,可能会让你按yes,以后就不会了)
如果报错,那有点悲剧,得根据情况慢慢百度了。实际上,解决CentOS和ESXI免密码登录的问题,我用了2天,遇到各种坑,各种报错。翻了无数贴子都不行,最后我找到一篇贴子,根据这篇贴子弄好的。报错了好好看看这个吧。
SSH免登陆ESXI让操作更便捷安全:https://blog.51cto.com/jdonghong/1946604
五、编写重启脚本
以下是我自己拍脑袋想出来的,可能不是最佳方案,让大佬们见笑了。
在CentOS输入
vim /opt/reboot.sh
粘贴如下代码(建议粘贴,不要照着敲,粘完了删掉括号、说明文字,以及多余的空调)
#!/bin/bash
var=$(ping -c 3 114.114.114.114 | grep "bytes")
(ping这个DNS 3次,取值,并且将取到的值赋予变量var)
if [[ $var =~ "bytes" ]]
(如果取到了bytes这个词)
then
(那么)
date >> /opt/time.txt
(记录下当前时间,并追加到这个文档里)
echo '吴彦祖你好,网络正常' >> /opt/time.txt
(记录一下当前网络状态)
else
(如果没取到)
date >> /opt/time.txt
(记录下当前时间,并追加到这个文档里)
echo '老子重启过' >> /opt/time.txt
(重启电脑之前写一条记录)
ssh 192.168.2.200 reboot
(免密登录到ESXI,并且重启ESXI)
fi
(完事了)
以上脚本的思路是,如果网络是通的,那ping 114.114.114.114必然会返回大量信息,其中有一个词是“bytes”。如果网不通,ping了以后只有一行信息提示网络不通,并且不会出现"bytes"。所以,根据ping的结果反馈,就能得知当前网络的状况,并且做出下一步行动。
赋予a.sh执行权限
chmod 777 /opt/reboot.sh
下面测试一下这个脚本的运行情况,输入
/opt/reboot.sh
如果报错了,检查一下代码吧,一个标点、一个空格都不能错。
如果上面的代码是粘贴的,运行了以后,这里不会报错,也不会有任何显示。
查看一下运行情况
cat /opt/time.txt
断掉外网后再测试一下。断网有多种方式,可以拔掉光猫的电源,也可以拔掉主路由或者旁路由对应直通网口的网线,也可以重启或关闭主路由或旁路由。前面说过,你调试用的这台笔记本的网线,要插在没有直通过的那个网口上。只有这样,在软路由关机断网的情况下,你的笔记本才能和CentOS通讯,你才能在断网以后,继续运行脚本。嫌麻烦的直接去拔光猫电源吧,那绝对不会造成你家内网断掉。
外网断掉后,运行/opt/reboot.sh,就会触发重启,这是硬件重启,电脑会重新自检,重新加载进入EXSI。加载过程中,内外网全断,请保持淡定。重启好以后,你的内网和外网应该会自动恢复,如果没能自动恢复,说明你架的软路由有问题,请检查设置。比较典型的错误是,忘了把软路由的虚拟机设为自动开机。
重新登录进CentOS,看看刚才的运行情况
cat /opt/time.txt
六、胜利在望了,最后一步,让脚本自动运行
这里又是一个大坑,各种报错,各种不报错却不运行。为了减少故障率,用root帐号登录进CentOS,先把相关软件包都装好。
yum install vixie-cron (cron的主程序,可以理解为Windows的计划任务)
yum install crontabs (安装、卸装、或列举用来驱动cron守护进程的表格的程序)
yum install ntsysv (这个是一个图形化的插件,方便查看、修改开机自启动项,cron必须随CentOS开机自启动,不然一切无从谈起)
以上软件包都安装好以后,输入crontab -e,编辑定时脚本,这里和vi的操作方式一样
以下是我的脚本,可以复制粘贴后根据自己情况修改
SHELL = /bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
55 0 * * * /opt/reboot.sh
55 3 * * * /opt/reboot.sh
55 5 * * * /opt/reboot.sh
55 7 * * * /opt/reboot.sh
55 8 * * * /opt/reboot.sh
55 9 * * * /opt/reboot.sh
55 10 * * * /opt/reboot.sh
55 11 * * * /opt/reboot.sh
55 12 * * * /opt/reboot.sh
55 13 * * * /opt/reboot.sh
55 14 * * * /opt/reboot.sh
55 15 * * * /opt/reboot.sh
55 16 * * * /opt/reboot.sh
55 17 * * * /opt/reboot.sh
55 18 * * * /opt/reboot.sh
55 19 * * * /opt/reboot.sh
55 20 * * * /opt/reboot.sh
55 21 * * * /opt/reboot.sh
55 22 * * * /opt/reboot.sh
意思就是每个小时的第55分钟,运行一次脚本。网络正常就按兵不动,网络不正常就重启EXSI。
运行情况可以用cat /opt/time.txt来确认,文件里如果没有信息,说明脚本自动执行不成功。
还记得前面提到的那个a.sh吗,那个是为非ESXI环境准备的,只需要用reboot.sh调用一下就行
vim /opt/reboot.sh
按i键切换到插入模式,把
ssh 192.168.2.200 reboot
替换成
/opt/a.sh
输入:wq回车
刚才说过,cron是个大坑,调试过程中会有各种状况,很难在这里一一列举。下面提供CentOS 8一些命令,便于排查问题。
启动cron服务 /bin/systemctl start crond.service
停止cron服务 /bin/systemctl stop crond.service
重启cron服务 /bin/systemctl restart crond.service
查看cron的运行状态 service crond status
查看cron的配置 crontab -l
修改cron的配置 crontab -e
查看定时任务的执行情况 cat /var/log/cron
图形化界面,用于查看和修改开机启动项 ntsysv
以上命令,可以根据反馈结果,上百度找到对应解决方案,保持耐心,一定能解决。
写到这里差不多该收工了,作为了一只大佬,您看到这里,让您见笑了。如果你是一只小白,我想我写得够细致,应该能避掉大部分的坑。希望此文能起到抛砖引玉的效果,让更多的大佬来帮助我完善这个脚本,使我们的家庭网络能够更智能的工作。
ClegeA
校验提示文案
飞机撞星星
校验提示文案
狂风速想
校验提示文案
steffee
校验提示文案
mige
校验提示文案
值个大头鬼
55 * * * * /opt/reboot.sh
校验提示文案
未成年面包机
校验提示文案
o果果
校验提示文案
荒野驰骋
校验提示文案
[已注销]
校验提示文案
值友2780456292
校验提示文案
诺尼的背包
校验提示文案
米尼克斯
#!/bin/sh
server="去看看"
log=/opt/time.txt
#判断输出日志文件是否存在
if [ ! -f $log ]
then
touch $log
fi
clear
while true
do
ping -c 5 -w 5 $server
if [ $? != 0 ]
then
echo "`date` |网络掉渣了,老子重启过,请检查一下!!" >> $log
echo "Network is Failed!"
ssh 192.168.2.2 reboot
break
else
echo "`date` |网络一切正常,可以开心遨游!" >> $log
echo "Network is OK!"
break
fi
done
校验提示文案
未成年面包机
校验提示文案
米尼克斯
#!/bin/sh
server="去看看"
log=/opt/time.txt
#判断输出日志文件是否存在
if [ ! -f $log ]
then
touch $log
fi
clear
while true
do
ping -c 5 -w 5 $server
if [ $? != 0 ]
then
echo "`date` |网络掉渣了,老子重启过,请检查一下!!" >> $log
echo "Network is Failed!"
ssh 192.168.2.2 reboot
break
else
echo "`date` |网络一切正常,可以开心遨游!" >> $log
echo "Network is OK!"
break
fi
done
校验提示文案
值个大头鬼
55 * * * * /opt/reboot.sh
校验提示文案
mige
校验提示文案
o果果
校验提示文案
steffee
校验提示文案
狂风速想
校验提示文案
诺尼的背包
校验提示文案
值友2780456292
校验提示文案
[已注销]
校验提示文案
荒野驰骋
校验提示文案
飞机撞星星
校验提示文案
ClegeA
校验提示文案