#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. Более того, поскольку нет кавычек, тест будет вести себя неправильно, когда есть вывод, но это более одного слова, или это глобальное выражение, которое соответствует файлам в текущем каталоге, или так далее.