Как включить таймер в сценарии Bash?

Добрый день! Есть ли способ включить таймер (отметку времени?или какой бы то ни было термин) в скрипте, использующем Баш? Например, каждые 60 секунд определенная функция проверяет, отключен ли интернет, если он есть, то он подключается к устройству wifi вместо этого и наоборот. Короче говоря, программа Время от времени проверяет подключение к интернету.

любые предложения / ответы будут высоко оценены. =)

6 ответов


тупые версии

while sleep 60; do
  if ! check_internet; then
    if is_wifi; then
       set_wired
    else
       set_wifi
    fi
  fi
done

использование самого сна в качестве условия цикла позволяет вырваться из цикла, убив сон (т. е. если это процесс переднего плана, ctrl-c будет делать).

Если мы говорим о минутах или часах интервалов, cron, вероятно, сделает лучшую работу, как отметил Монтекристо.


вы можете сделать человек cron.

или если вам просто нужно придерживаться bash, просто поместите вызов функции внутри цикла и спать 60 внутри итерации.


пожалуйста, найдите здесь скрипт, который вы можете использовать, сначала добавьте запись в задание cron следующим образом:

$ sudo crontab-e * * * * * * / path/to/your / switcher

Это простой метод, который находится на pinging живой сервер непрерывно каждую минуту, если сервер не доступен, он переключится на второй маршрутизатор, определенный ниже.

конечно, есть лучший способ, чтобы использовать эту проблему.

$ cat > switcher

#!/bin/sh

route=`which route`
ip=`which ip`

# define your email here
mail="user@domain.tld"

# 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

Мне понравился ответ Уильяма, потому что он не нужен опрос. Поэтому я реализовал следующий сценарий, основанный на его идее. Он работает вокруг проблемы, что элемент управления должен вернуться в оболочку.

#!/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)"

вы можете сделать что-то вроде следующего, но это не надежно:

#!/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

одна из проблем с этой техникой заключается в том, что ловушка не вступит в силу, пока текущая задача не вернется в оболочку (например, замените sleep 1 на sleep 10). Если оболочка находится под контролем большую часть времени (например, если все команды, которые она вызывает, быстро завершатся), это может работать. Один из вариантов, конечно, это запустить все в фоновом режиме.


создайте сценарий bash, который проверяет, отключено ли подключение к интернету, и добавьте сценарий в задачу crontab, которая выполняется каждые 60 секунд.