买了nas,买了ups,突然想起这个ups不能和nas通信,那岂不是无法自动关机,ups不是白买了,本着物尽其用的原则,网上搜了下方案,发现主要思路是nas跑脚本ping路由器或者某个没断电可以正常网络联通的设备,如果断电,这个设备必然ping不通,超过一定次数,可判定为断电,调用脚本关机。
不过看了几个脚本,要么太简单如:https://www.chiphell.com/thread-708216-1-1.html,要么太复杂如:https://post.smzdm.com/p/621381/
且都没提供参数配置,比如:ups预估运行时间,nas关闭预估时间,ping间隔,失败几次关机,ping检测本身预估耗时,buffer时间等
关机脚本
所幸自行写一版,主要流程改为,ping指定ip,不通后间隔s秒,继续ping N次,失败后调用关机指令/sbin/poweroff 关设备,另外增加各类可配置参数,命令尽量不使用平台相关,方便适应不同机器和环境
优化后版本如下
#!/bin/bash
# @author JasonLiu
# @since 2019/12/25
# @description ping the router,if power shutdown,router will shutdown,ping will fail,if ping fail>N,shutdown NAS
# idea first come from http://koolshare.cn/thread-120821-1-1.html
# */1 * * * * /share/Project/shell/powerchk.v5.sh >> /share/Project/shell/log/power.log
# crontab /etc/config/crontab && /etc/init.d/crond.sh restartfunction usage()
{
echo "$ARG0 usage:$ARG0 -c check parameter$ARG0 -h help$ARG0 -d drill,not really shutdown"
}
# write qnap log
log=true
# UPS live minute
live_min=10
# nas shutdown cost minute
shutdown_min=5
# buffer minute
buffer_min=3
# ping check count
check_cnt=5
# ping check interval seconds
interval_sec=3
# ping fail shutdown count
fail_shutdown_cnt=2
# ping ip,default can set router
ip=192.168.50.1
# script crontab iterval
task_interval_sec=60
# shutdown cost second= shutdown cost + buffer time
shutdown_buffer_cost_min=`expr $shutdown_min + $buffer_min`
#echo "shutdown_buffer_cost_min = $shutdown_buffer_cost_min"
shutdown_buffer_cost_sec=`expr $shutdown_buffer_cost_min \* 60`
#echo "shutdown_buffer_cost_sec = $shutdown_buffer_cost_sec"
# check cost = check interval * check_count
check_cost_max_sec=`expr $interval_sec \* $check_cnt`
#echo "check_cost_max_sec = $check_cost_max_sec"# check can use seconds = live_min - shutdown_cost - one_crontab_interval
check_can_use_sec=`expr $live_min \* 60 - $shutdown_buffer_cost_sec - $check_cost_max_sec - $task_interval_sec`
#echo "check_can_use_sec = $check_can_use_sec"
DRILL=false
while getopts "dhc" opts
docase $opts inc)echo "shutdown cost(s) = $shutdown_buffer_cost_sec s"echo "ping check cost(s) = $check_cost_max_sec s"echo "ping check can use(s) = $check_can_use_sec s"if [ $check_cost_max_sec -gt $check_can_use_sec ]; thenecho "alert:ping check cost time < ping can use time !!! may got not enought time to shutdown"elseecho "parameter all OK!!!"fiexit;;;h)usage; exit;;;d)DRILL=trueesac
donenow=`date "+%Y-%m-%d %H:%M:%S"`
# ping fail counter
fail_cnt=1
while [ $fail_cnt -le $check_cnt ]; doif ping -c 1 $ip > /dev/null; thenecho "$now $ip ping success"if [ $log = true ]; thenwrite_log "[powercheck] ping succ" 4fibreakelseecho "$ip ping fail,count $fail_cnt"let fail_cnt++if [ $fail_cnt -ge $fail_shutdown_cnt ]; thenecho "$now $ip ping fail,fail count $fail_cnt great than $fail_shutdown_cnt,start to shutdown NAS"if [ $log = true ]; thenwrite_log "ping fail, shut down NAS" 2fiif [ $DRILL = true ]; thenecho "drill end ,$ip check fail"exit;else/sbin/powerofffibreakfisleep $interval_secfi
done
- -h 可以查看帮助
- -d 演习模式,不会实际执行关机指令,可以测试下脚本是否跑通
- -c 会根据配置参数计算出是否有足够实际来做ping检测和关机操作,具体为:
检测可用时间 = ups断电支持时间 - NAS关机时间 - 机动时间 - crontab时间间隔
检测时间 = 检测间隔 * 一次ping时间
如果 检测可用时间<检测时间,会提示,此时需要调整参数,保证NAS有足够时间关机
qnap写脚本有个坑,不支持bc,导致计算相关代码全部用expr重写了一遍,expr不支持括号,所以又有括号的乘法也需要拆开。
需要配置参数有
# 是否输出qnap日志,默认开
log=true
# 断电后,UPS预估关机耗时,单位分钟
live_min=10
# NAS关机预估耗时,单位分钟
shutdown_min=5
# 预留机动时间,单位分钟
buffer_min=3
# ping检查失败最大次数
check_cnt=5
# ping检查间隔
interval_sec=3
# ping检测失败次数,超过此次数关机
fail_shutdown_cnt=2
# ping的IP,一般为路由器
ip=192.168.50.1
# 脚本在crontab内,调用间隔,单位秒,根据crontab配置调整
task_interval_sec=60
crontab配置
crontab 配置,在qnap里也有坑,详细可以参考
现放正确的配置,具体命令可根据脚本所在目录自行修改,如果写了文件日志可以把qnap日志关闭,另外脚本所在在硬盘无法休眠,脚本最好放到存放软件的盘上,不把数据盘唤醒
*/1 * * * * /share/Project/shell/powerchk.v5.sh >> /share/Project/shell/log/power.log
坑1
crontab不能直接使用-e编辑,编辑后不会写入/etc/config/crontab文件,qnap重启,或者crontab服务重启后,配置会丢失,因此需要直接编辑/etc/config/crontab,之后再调用以下脚本重启crontab才能生效
crontab /etc/config/crontab && /etc/init.d/crond.sh restart
坑2
是由于要设定一分钟跑一次,先使用的参数如下
0/1 * * * *
使用这个 在线工具,检查也ok,如下图
但是qnap的crontab容错性比较差,这样配置后,只能一小时执行一次,需要改为更正规的
*/1 * * * * /share/Project/shell/powerchk.v5.sh >> /share/Project/shell/log/power.log
crontab配置参考
* * * * * command
分 时 日 月 周 命令
第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令