Как я пишу логику повторной попытки в сценарии, чтобы продолжать повторять для выполнения его до 5 раз?

unbuffer udevadm monitor --environment Использование unbuffer является дополнительным, но когда вывод передачи по каналу к grep сохраняет Вас головная боль. Выводом по умолчанию буферизуется в 4k блоках, ничто не будет распечатано, пока тот буфер не будет полон.

Вы не забыли перезагружать правила? sudo udevadm control --reload

120
11.07.2013, 11:04
14 ответов

Этот сценарий использует счетчик n ограничить попытки команды к пять. Если команда успешна, $? будет содержать нуль, и выполнение повредится от цикла.

n=0
until [ $n -ge 5 ]
do
   command && break  # substitute your command here
   n=$[$n+1]
   sleep 15
done
99
27.01.2020, 19:29
  • 1
    сбоя необходимо добавить break если успехи команды затем, это повредит цикл –  Rahul Patil 11.07.2013, 10:39
  • 2
    На самом деле надлежащий способ записать это if command; then break; fi или более кратко просто command && break –  tripleee 11.07.2013, 11:05
  • 3
    "команда" является просто названием команды, из которой Вы хотите проверить состояние. –  suspectus 11.07.2013, 16:00
  • 4
    Стоящий замечания, что можно протестировать, если n равняется пять в конце, чтобы знать если команда, за которой следуют или нет. –  mattdm 23.12.2015, 16:20
  • 5
    Хорошее решение - но в случае n отказы, это напрасно спит одно дополнительное время перед выходом. –  ron rothman 11.03.2016, 21:17
for i in 1 2 3 4 5; do command && break || sleep 15; done

Замена "команда" с Вашей командой. Это предполагает, что "состояние code=FAIL" означает любой ненулевой код возврата.


Изменения:

Используя {..} синтаксис. Работы в большинстве оболочек, но не BusyBox sh:

for i in {1..5}; do command && break || sleep 15; done

Используя seq и проведение кода выхода неудавшейся команды:

for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)

То же как выше, но пропуск sleep 15 после заключительного сбоя. Так как лучше только определить максимальное количество циклов однажды, это достигается путем сна в начале цикла если i > 1:

for i in $(seq 1 5); do [ $i -gt 1 ] && sleep 15; command && s=0 && break || s=$?; done; (exit $s)
129
27.01.2020, 19:29
  • 1
    +1 — сжатый и ясный. Одно предложение: Я заменил бы for i in 1 2 3 4 5 с for i in {1..5} потому что легче поддержать. –  Paddy Landau 11.07.2013, 16:03
  • 2
    Просто примечание, это работает потому что && оценен перед || из-за приоритета –  gene_wood 04.09.2015, 22:50
  • 3
    Другое примечание, это возвратит код даже если command сбои. –  Henrique Zambon 26.05.2017, 18:34
  • 4
    @HenriqueZambon Добавил версию, которая также обрабатывает это. –  Alexander 10.07.2017, 16:14
  • 5
    Разве это не спит после заключительного отказа? Походит ожидают, ненужные 15. Я думаю, что можно поместить проверку на [[ i -eq 5]] как ИЛИ условие передо сном для предотвращения этого. –  Dave Lugg 15.01.2018, 20:46

Вот функция для повторной попытки

function retry()
{
        local n=0
        local try=$1
        local cmd="${@: 2}"
        [[ $# -le 1 ]] && {
        echo "Usage $0 <retry_number> <Command>"; }

        until [[ $n -ge $try ]]
        do
                $cmd && break || {
                        echo "Command Fail.."
                        ((n++))
                        echo "retry $n ::"
                        sleep 1;
                        }

        done
}

retry $*

Вывод:

[test@Nagios ~]$ ./retry.sh 3 ping -c1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.207 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.207/0.207/0.207/0.000 ms

[test@Nagios ~]$ ./retry.sh 3 ping -c1 localhostlasjflasd
ping: unknown host localhostlasjflasd
Command Fail..
retry 1 ::
ping: unknown host localhostlasjflasd
Command Fail..
retry 2 ::
ping: unknown host localhostlasjflasd
Command Fail..
retry 3 ::
11
27.01.2020, 19:29
  • 1
    , который я копирую, вставил Ваш код в новом файле, названном retry.sh, и добавил строку #!/bin/bash наверху. При выполнении с данными командами в объяснении я не вижу, что что-либо просто запросить прибывает снова. –  java_enthu 19.08.2013, 13:54
  • 2
    имеет Вас попробованный bash retry.sh 3 ping -c1 localhost –  Rahul Patil 19.08.2013, 14:26
  • 3
    Да Rahul я действительно пробовал. –  java_enthu 19.08.2013, 14:29
  • 4
    Извините, я был bizy.., я протестировал снова, это работает, проверьте выходной paste.ubuntu.com/6002711 –  Rahul Patil 19.08.2013, 15:35

Посмотрите ниже примера:

n=0
while :
do
        nc -vzw1 localhost 3859
        [[ $? = 0 ]] && break || ((n++))
        (( n >= 5 )) && break

done

Я пытаюсь соединить порт 3389 на localhost, он повторит до сбоя 5 раз, если успех затем он повредит цикл.

$? это, существуют состояние команды, если это обнуляет команду средств, успешно выполненную, если кроме нулевых средств управляют fai

Кажется немного сложным, может быть кто-то, делают это лучше, чем это.

1
27.01.2020, 19:29
  • 1
    Спасибо rahul.. будет это быть сохранить повторную попытку для запущения скрипта?? –  Sandeep Singh 11.07.2013, 10:28
  • 2
    Проверьте теперь, я обновил –  Rahul Patil 11.07.2013, 10:32
  • 3
    $? это, существуют состояние команды, если это обнуляет команду средств, успешно выполненную, если кроме нулевых средств управляют, –  Rahul Patil 11.07.2013, 10:34
  • 4
    , являются требуемым дать адрес узла и адрес порта. мы можем сделать это путем предоставления dir местоположения сценария только. замена –  Sandeep Singh 11.07.2013, 10:43
  • 5
    какой-либо командой, которые дают $ кода статуса выхода? –  Rahul Patil 11.07.2013, 10:44
function fail {
  echo $1 >&2
  exit 1
}

function retry {
  local n=1
  local max=5
  local delay=15
  while true; do
    "$@" && break || {
      if [[ $n -lt $max ]]; then
        ((n++))
        echo "Command failed. Attempt $n/$max:"
        sleep $delay;
      else
        fail "The command has failed after $n attempts."
      fi
    }
  done
}

Пример:

retry ping invalidserver

выдает этот вывод:

ping: unknown host invalidserver
Command failed. Attempt 2/5:
ping: unknown host invalidserver
Command failed. Attempt 3/5:
ping: unknown host invalidserver
Command failed. Attempt 4/5:
ping: unknown host invalidserver
Command failed. Attempt 5/5:
ping: unknown host invalidserver
The command 'ping invalidserver' failed after 5 attempts

Для реального примера работы со сложными командами см. этот сценарий .

33
27.01.2020, 19:29

Вот мой любимый однострочный псевдоним / сценарий

    alias retry='while [ $? -ne 0 ] ; do fc -s ; done'

Затем вы можете делать что-то вроде:

     $ ps -ef | grep "Next Process"
     $ retry

, и он будет продолжать выполнять предыдущую команду, пока не найдет «Следующий процесс»

6
27.01.2020, 19:29

Я использую этот скрипт, который делает повторные попытки данной команды, преимущество этого скрипта в том, что если все повторные попытки не удались, он сохраняет код выхода.

#!/usr/bin/env bash

if [ $# -ne 3 ]; then
    echo 'usage: retry <num retries> <wait retry secs> "<command>"'
    exit 1
fi

retries=$1
wait_retry=$2
command=$3

for i in `seq 1 $retries`; do
    echo "$command"
    $command
    ret_value=$?
    [ $ret_value -eq 0 ] && break
    echo "> failed with $ret_value, waiting to retry..."
    sleep $wait_retry
done

exit $ret_value

Возможно, это может стать проще

2
27.01.2020, 19:29

Aquí hay una función recursiva retrypara los puristas de la programación funcional:

retry() {
  cmd=$1
  try=${2:-15}       # 15 by default
  sleep_time=${3:-3} # 3 seconds by default

  # Show help if a command to retry is not specified.
  [ -z "$1" ] && echo 'Usage: retry cmd [try=15 sleep_time=3]' && return 1

  # The unsuccessful recursion termination condition (if no retries left)
  [ $try -lt 1 ] && echo 'All retries failed.' && return 1

  # The successful recursion termination condition (if the function succeeded)
  $cmd && return 0

  echo "Execution of '$cmd' failed."

  # Inform that all is not lost if at least one more retry is available.
  # $attempts include current try, so tries left is $attempts-1.
  if [ $((try-1)) -gt 0 ]; then
    echo "There are still $((try-1)) retrie(s) left."
    echo "Waiting for $sleep_time seconds..." && sleep $sleep_time
  fi

  # Recurse
  retry $cmd $((try-1)) $sleep_time
}

Pásele un comando (o un nombre de función )y, opcionalmente, un número de reintentos y una duración de sueño entre reintentos, así:

retry some_command_or_fn 5 15 # 5 tries, sleep 15 seconds between each
0
27.01.2020, 19:29

Вы можете использовать команду loop, доступную здесь , вот так:

$ loop './do_thing.sh' --every 15s --until-success --num 5 

Который будет выполнять вашу задачу каждые 15 секунд, пока не добьется успеха, максимум пять раз.

5
27.01.2020, 19:29

GNU Parallel имеет--retries:

parallel --retries 5 --delay 15s :::./do_thing.sh

Пример:

parallel -t --retries 5 --delay 0.1s 'echo {};exit {}' ::: {0..10}
20
27.01.2020, 19:29

Поскольку мне приходилось делать это несколько раз, скрипты выходили из-под контроля, поэтому я создал для этого специальный инструмент под названием retry.

retry --until=success --times=5 --delay=15 command...

Повторная попытка доступна здесь:https://github.com/minfrin/retry

4
27.01.2020, 19:29

Отвечая на этот вопрос, поскольку существующие ответы не позволяют,

  1. Код ошибки не выдается.
  2. Выполняя exit errCode, Bash не учитывает некоторые ловушки, такие какtrap somefunc ERR
COMMAND="SOMECOMMAND"
TOTAL_RETRIES=3

retrycount=0
until [ $retrycount -ge $((TOTAL_RETRIES-1)) ]
do
   $COMMAND && break
   retrycount=$((retrycount+1))
   sleep 1
done

if [ $retrycount -eq $((TOTAL_RETRIES-1)) ]
then
    $COMMAND
fi
0
27.01.2020, 19:29

Это старый вопрос, но я часто возвращаюсь к нему. Мой вариант использования заключался в том, чтобы иметь один вкладыш, который может повторять команду до nраз, который можно использовать с модулем kubernetes (, конечно, если он будет работать для скрипта bash ).

TRY=6; until [ $TRY -eq 0 ] || <your command over here> ; do echo $TRY; echo "<output message>"; TRY=$(expr $TRY - 1); sleep 15; done;

Один лайнер немного сложно уложить в голове, но он может оказаться очень полезным.

0
06.12.2020, 08:13

небольшие модификации для одного -лайнера , который имеет увеличивающуюся задержку в секундах для следующего выполнения

 DELAYS=(0 1 3 5); (for i in 1 2 3 4; do sleep ${DELAYS[$i]}; <COMMAND> && break || [ $i -lt 4 ] && echo "retry in ${DELAYS[$i+1]}s"; done)

пример (git push используется для устранения ошибки)

✗  DELAYS=(0 1 3 5); (for i in 1 2 3 4; do sleep ${DELAYS[$i]}; git pish && break || [ $i -lt 4 ] && echo "retry in ${DELAYS[$i+1]}s"; done)
git: 'pish' is not a git command. See 'git --help'.

The most similar command is
    push
retry in 1s
git: 'pish' is not a git command. See 'git --help'.

The most similar command is
    push
retry in 3s
git: 'pish' is not a git command. See 'git --help'.

The most similar command is
    push
retry in 5s
git: 'pish' is not a git command. See 'git --help'.

The most similar command is
    push

заменить git pishна правильныйgit push


✗  DELAYS=(0 1 3 5); (for i in 1 2 3 4; do sleep ${DELAYS[$i]}; git push && break || [ $i -lt 4 ] && echo "retry in ${DELAYS[$i+1]}s"; done)
Everything up-to-date
0
21.10.2021, 20:04

Теги

Похожие вопросы