如何在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:23:12  来源:igfitidea点击:

How to include a timer in Bash Scripting?

bashtimestamp

提问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 任务中。