Как вы можете запускать команду в bash снова и снова до достижения успеха?

#linux #bash #google-cloud-platform #error-handling

#bash #команда #цикл while

Вопрос:

У меня есть скрипт, и я хочу запросить у пользователя некоторую информацию, но скрипт не может продолжаться, пока пользователь не заполнит эту информацию. Ниже приведена моя попытка поместить команду в цикл для достижения этой цели, но по какой-то причине она не работает:

 echo "Please change password"
while passwd
do
    echo "Try again"
done
 

Я перепробовал много вариантов цикла while:

 while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more
 

Но, похоже, я не могу заставить ее работать.

Ответ №1:

 until passwd
do
  echo "Try again"
done
 

или

 while ! passwd
do
  echo "Try again"
done
 

Комментарии:

1. oneliner: until passwd; do echo "Try again"; done

2. Трудно Ctrl-C из этого.

3. Легко использовать Ctr-C из этого: until passwd; do echo "Try again"; sleep 2; done — все, что вам нужно сделать, это нажать Ctr-C сразу после (в течение двух заданных секунд) echo выполнения задания.

4. Ctrl-Z, за которым следует, kill %1 работает здесь, когда Ctrl-C не будет

5. @azmeuk: попробуйте что-то вроде until passwd || (( count >= 5 )); do echo "foo"; done (только для bash, обязательно установите значение count равным 0, если это значение существует) Если вам это нужно для простого sh, увеличьте счетчик в теле и используйте [ ]

Ответ №2:

Чтобы уточнить ответ @Marc B.,

 $ passwd
$ while [ $? -ne 0 ]; do !!; done
 

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

Комментарии:

1. К сожалению, у меня не работает (я получаю ‘!!’ команда не найдена). Как это должно работать?

2. Это трюк bash для запуска предыдущей команды. Например, если вы забыли написать sudo перед командой, вы можете просто выполнить sudo !! предыдущую команду с правами root.

3. Как спать между запусками?

4.^^ while [ $? -ne 0 ]; do !!; sleep 1; done

Ответ №3:

Вместо этого вам нужно протестировать $? , что является статусом завершения предыдущей команды. passwd завершается с 0, если все работает нормально, и ненулевым, если не удалось изменить passwd (неправильный пароль, несоответствие пароля и т. Д.)

 passwd
while [ $? -ne 0 ]; do
    passwd
done
 

С вашей версией возврата вы сравниваете выходные данные passwd, которые могут быть такими, как Enter password и confirm password и тому подобное.

Комментарии:

1. Мне это нравится, потому что ясно, как адаптировать ее к противоположной ситуации. например, запустите программу с недетерминированной ошибкой, пока она не завершится неудачей

2. Когда успех обозначается ненулевым кодом выхода, это то, что вам нужно.

3. Я думаю, что это можно немного улучшить, изменив первое passwd на /bin/false , если у вас есть какая-то длинная и сложная команда, для которой вы не хотите сохранять две версии.

4. Должен быть принятый ответ имхо. Это должно работать в большинстве оболочек (протестировано в bash, mksh и ash) и легко адаптируется к ситуации.

5. Сбой проверки оболочки с выводом: проверьте код выхода напрямую, например, с помощью ‘if mycmd;’, а не косвенно с помощью $ ?. [SC2181]

Ответ №4:

Если кто-нибудь хочет иметь ограничение на повторные попытки:

 max_retry=5
counter=0
until $command
do
   sleep 1
   [[ counter -eq $max_retry ]] amp;amp; echo "Failed!" amp;amp; exit 1
   echo "Trying again. Try #$counter"
   ((counter  ))
done
 

Комментарии:

1. $command не является отличным заполнителем — см. BashFAQ # 50 о том, почему использование строк для хранения команд изначально ненадежно.

Ответ №5:

Для достижения этой цели вы можете использовать бесконечный цикл:

 while true
do
  read -p "Enter password" passwd
  case "$passwd" in
    <some good condition> ) break;;
  esac
done
 

Комментарии:

1. Это единственный ответ, который не требовал ввода моей многострочной команды в функцию. Я сделал amp;amp; break это после моей команды проверки, хотя вместо выбора регистра.

Ответ №6:

 while [ -n $(passwd) ]; do
        echo "Try again";
done;
 

Комментарии:

1. Это не способ сделать это … вы отрицаете стандартный вывод psswd, а затем выполняете для него унарный тест. @duckworthdхорошо.

2. Более того, поскольку нет кавычек, тест будет вести себя неправильно, когда есть вывод, но это более одного слова, или это глобальное выражение, которое соответствует файлам в текущем каталоге, или так далее.