如何在 Bash 脚本中包含计时器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1226094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to include a timer in Bash Scripting?
提问by Suezy
Good day! Is there any way to include a timer (timestamp?or whatever term it is) in a script using bash? Like for instance; every 60 seconds, a specific function checks if the internet is down, if it is, then it connects to the wifi device instead and vice versa. In short, the program checks the internet connection from time to time.
再会!有什么方法可以使用bash在脚本中包含计时器(时间戳?或任何术语)?比如说;每 60 秒,一个特定的功能检查互联网是否关闭,如果是,则连接到 wifi 设备,反之亦然。简而言之,该程序会不时检查互联网连接。
Any suggestions/answers will be much appreciated. =)
任何建议/答案将不胜感激。=)
回答by falstro
Blunt version
钝版
while sleep 60; do
if ! check_internet; then
if is_wifi; then
set_wired
else
set_wifi
fi
fi
done
Using the sleep itself as loop condition allows you to break out of the loop by killing the sleep (i.e. if it's a foreground process, ctrl-c will do).
使用 sleep 本身作为循环条件允许您通过终止 sleep 来打破循环(即,如果它是一个前台进程,则 ctrl-c 可以)。
If we're talking minutes or hours intervals, cron will probably do a better job, as Montecristo pointed out.
如果我们谈论的是几分钟或几小时的间隔,cron 可能会做得更好,正如 Montecristo 指出的那样。
回答by Alberto Zaccagni
You may want to do a man cron.
你可能想做一个man cron。
Or if you just have to stick to bash just put the function call inside a loop and sleep 60inside the iteration.
或者,如果您只需要坚持使用 bash,只需将函数调用放在循环中并在迭代中休眠 60。
回答by Ali Mezgani
Please find here a script that you can use, first add an entry to your cron job like this:
请在此处找到您可以使用的脚本,首先在您的 cron 作业中添加一个条目,如下所示:
$ sudo crontab -e * * * * * /path/to/your/switcher
$ sudo crontab -e * * * * * /path/to/your/switcher
This is simple method that reside on pinging an alive server continuously every minute, if the server is not reachable, it will switch to the second router defined bellow.
这是一种简单的方法,驻留在每分钟连续 ping 一个活动服务器上,如果服务器不可访问,它将切换到下面定义的第二个路由器。
surely there are better way, to exploit this issue.
肯定有更好的方法来利用这个问题。
$ cat > switcher
$猫>切换台
#!/bin/sh
route=`which route`
ip=`which ip`
# define your email here
mail="[email protected]"
# We define our pingable target like 'yahoo' or whatever, note that the host have to be
# reachable every time
target="www.yahoo.com"
# log file
file="/var/log/updown.log"
# your routers here
router1="192.168.0.1"
router2="192.168.0.254"
# default router
default=$($ip route | awk '/default/ { print }')
# ping command
ping -c 2 ${target}
if [ $? -eq 0 ]; then
echo "`date +%Y%m%d-%H:%M:%S`: up" >> ${file}
else
echo "`date +%Y%m%d-%H:%M:%S`: down" >> ${file}
if [ ${default}==${router1} ]; then
${route} del default gw ${router1}
${route} add default gw ${router2}
elif [ ${default}==${router2} ]; then
${route} del default gw ${router2}
${route} add default gw ${router1}
fi
# sending a notification by mail or may be by sms
echo "Connection problem" |mail -s "Changing Routing table" ${mail}
fi
回答by drizzd
I liked William's answer, because it does not need polling. So I implemented the following script based on his idea. It works around the problem that control has to return to the shell.
我喜欢威廉的回答,因为它不需要投票。所以我根据他的想法实现了以下脚本。它解决了控制权必须返回给 shell 的问题。
#!/bin/sh
someproc()
{
sleep
return
}
run_or_timeout()
{
timeout=
shift
{
trap 'exit 0' 15
"$@"
} &
proc=$!
trap "kill $proc" ALRM
{
trap 'exit 0' 15
sleep $timeout
kill -ALRM $$
} &
alarm=$!
wait $proc
ret=$?
# cleanup
kill $alarm
trap - ALRM
return $ret
}
run_or_timeout 0 someproc 1 0
echo "exit: $? (expected: 142)"
run_or_timeout 1 someproc 0 0
echo "exit: $? (expected: 0)"
run_or_timeout 1 someproc 0 1
echo "exit: $? (expected: 1)"
回答by William Pursell
You can do something like the following, but it is not reliable:
您可以执行以下操作,但它不可靠:
#!/bin/sh trap handle_timer USR1 set_timer() { (sleep 2; kill -USR1 $$)& } handle_timer() { printf "%s:%s\n" "timer expired" "$(date)"; set_timer } set_timer while true; do sleep 1; date; done
One problem with this technique is that the trap will not take effect until the current task returns to the shell (eg, replace the sleep 1 with sleep 10). If the shell is in control most of the time (eg if all the commands it calls will terminate quickly), this can work. One option of course, is to run everything in the background.
这种技术的一个问题是陷阱在当前任务返回到外壳之前不会生效(例如,用 sleep 10 替换 sleep 1)。如果 shell 大部分时间都在控制之下(例如,如果它调用的所有命令都将快速终止),这可以工作。当然,一种选择是在后台运行所有内容。
回答by David Aleu
Create a bash script that checks once if internet connection is down and add the script in a crontab task that runs every 60 seconds.
创建一个 bash 脚本,检查一次 Internet 连接是否关闭,并将脚本添加到每 60 秒运行一次的 crontab 任务中。