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

Что это делает

Это широко распространенный способ проверки интерактивности оболочки. Помните, что он работает только в bash, он не работает с другими оболочками. Так что ладно (если глупо )для .bashrc, но это не сработает в.profile(который читает sh, а bash это только одна из возможных реализаций sh, и не самая распространенная ).

Почему это работает (только в bash!)

Интерактивная оболочка устанавливает переменную оболочкиPS1в строку приглашения по умолчанию. Таким образом, если интерактивная оболочка, PS1устанавливается (, если пользователь .bashrcне удалил ее, чего еще не могло произойти в верхней части .bashrc, и вы могли бы подумать, что это глупо все равно делать ).

Обратное верно для bash :не -интерактивных экземпляров bash unset PS1при их запуске. Обратите внимание, что такое поведение характерно для bash и, возможно, является ошибкой (. Почему bash -c '… do stuff with $var…'не работает, если varравно PS1? ). Но все версии bash до 4.4 (включительно, последняя версия, которую я пишу ), делают это.

Многие системы экспортируют PS1в среду. Это плохая идея, потому что многие разные оболочки используют PS1, но с другим синтаксисом (, например. экранирование приглашения bash полностью отличается от экранирования приглашения zsh). Но это настолько широко распространено, что на практике установка PS1не является надежным показателем того, что оболочка интерактивна. Оболочка могла унаследовать PS1от среды.

Почему здесь используется (mis )

.bashrc— это файл, который bash читает при запуске, когда он интерактивен.Менее известный -факт заключается в том, что bash также читает .bashrcкак оболочку входа в систему, и эвристика bash заключает, что это удаленный сеанс (bash проверяет, является ли его родителем rshdилиsshd). Во втором случае маловероятно, что PS1будет установлен в среде, потому что еще не запущен ни один точечный файл.

Однако то, как код использует эту информацию, приводит к обратным результатам.

  • Если оболочка является интерактивной, то .bash_profileвыполняется в этой оболочке. Но .bash_profile— это сценарий времени входа -. Он может запускать некоторые программы, предназначенные для запуска только один раз за сеанс. Это может переопределить некоторые переменные среды, для которых пользователь преднамеренно установил другое значение перед запуском этой оболочки. Запуск .bash_profileв оболочке входа без -нарушает работу.
  • Если оболочка не является -интерактивной оболочкой удаленного входа в систему, она не будет загружаться .bash_profile. Но это тот случай, когда загрузка .bash_profileможет быть полезной, потому что интерактивная оболочка входа без -не загружает автоматически /etc/profileи ~/.profile.

Я думаю, люди делают это по той причине, что пользователи, которые входят в систему через графический интерфейс (, что является очень распространенным случаем )и которые устанавливают свои настройки переменных среды в .bash_profile, а не .profile. Большинство механизмов входа в систему с графическим интерфейсом вызывают .profile, но не .bash_profile(, чтение .bash_profileпотребует запуска bash как части запуска сеанса вместо sh ). В этой конфигурации, когда пользователь открывает терминал, он получает свои переменные среды. Однако пользователь не получит свои переменные среды в приложениях с графическим интерфейсом, что является очень распространенным источником путаницы. Решение здесь состоит в том, чтобы использовать .profileвместо .bash_profileдля установки переменных среды. Добавление моста между .bashrcи .bash_profileсоздает больше проблем, чем решает.

Что делать вместо этого

Есть прямой,портативный способ проверить, является ли текущая оболочка интерактивной :проверить, включена ли опция -i.

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This shell is not interactive";;
esac

Это полезно в .bashrcдля чтения .profileтолько в том случае, если оболочка не -интерактивная — т. е. противоположное тому, что делает код! Прочтите .profile, если bash является (не -интерактивной )оболочкой входа в систему, и не читайте ее, если это интерактивная оболочка.

if [[ $- != *i* && -r ~/.profile ]]; then. ~/.profile; fi
0
23.06.2021, 14:12
1 ответ

Боюсь, у вас неверный синтаксис. Я думаю, вы ищете что-то вроде этого:

if [ "$line" = "Information wrong try again!" ]; then
  echo "Try again"
else
    echo "All's well"
fi

Конечно, детали будут зависеть от того, как вы запустите сценарий. Если вы хотите, чтобы это был бесконечный цикл, и повторно -запускайте команду echo "information" | ncat "IP" "PORT", пока она не сработает, вам нужно что-то вроде этого:

line=$(echo "information" | ncat "IP" "PORT")
while [ "$line" = "Information wrong try again!" ]; do
    line=$(echo "information" | ncat "IP" "PORT")
    sleep 1 ## wait one second between launches to avoid spamming the CPU
done

## At this point, we have gotten a value of `$line` that is not `Information wrong try again!`, so we can continue. 
echo "Worked!"

Или аналогично:

while [ $(echo "information" | ncat "IP" "PORT") = "Information wrong try again!" ]; do
    sleep 1 ## wait one second between launches to avoid spamming the CPU
done

## rest of the script goes here
echo "Worked!"
0
28.07.2021, 11:22

Теги

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