ожидание сети в скрипте bash

9

Я запускаю сценарий, который зависит от сети и подключения к сети. Скрипт запускается при входе в систему (что происходит автоматически после загрузки). Проблема в том, что к моменту запуска скрипта у меня обычно еще нет IP-адреса (DHCP). Сейчас я просто сплю сценарий на 15 секунд, но мне этот подход не нравится, так как я хочу быть в состоянии сообщить пользователю, если что-то не так.

Мой план заключается в том, чтобы выполнить цикл, пока у меня еще нет IP-адреса, и продолжить, когда у меня есть. Важно отметить, что через какое-то время это должно произойти. Что я придумал, так это if [ ifconfig | grep "192.168.100" ];то, что происходит, когда grep потребляет ];и ему не нравится. Тогда bash также расстраивается, потому что не может найти, ];какой grep съел. А потом я даже не реализовал тайм-аут.

Кто-то предложил сохранить переменную и, скажем, спать в течение секунды в каждой итерации и увеличивать эту переменную каждый раз. Вот мой полный (не рабочий) скрипт (я довольно новичок в скриптах bash):

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
    echo "no nework"
    if "$x" -gt 200; then
        #Time out here
        exit 1
    x=$((x+1))
    sleep .1
    fi
done

#continue with rest of script...

Любые указатели в правильном направлении будут с благодарностью!

aguywithsocks
источник
1
Если ваша инициализация - systemd, напишите служебный файл, который ждет network-online.target...
jasonwryan
нет необходимости перенаправлять grepвывод на /dev/null. -qВместо этого используйте опцию. Кроме того, я не собираюсь гадать, если хорошая идея - ifconfig. Почему бы не использовать pingвместо этого?
Раш
pingможет произойти сбой в зависимости от рассматриваемой сети. Лучше просто проверить работающую конфигурацию системы.
Братчли

Ответы:

8

Синтаксис оболочки

Вы, кажется, смущены относительно условий в сценариях оболочки. Каждая команда оболочки имеет статус выхода, который является целым числом от 0 до 255, где 0 означает успех, а любое другое значение означает сбой. Такие операторы, как ifи whileпредполагающие, что булевы операнды проверяют состояние выхода команды и рассматривают 0 (успех) как истину, а любое другое значение (сбой) - как ложь.

Например, grepкоманда возвращает 0, если шаблон найден, и 1, если шаблон не найден. Так

while ifconfig | grep "192.168.100." > /dev/null; do 

повторяет цикл, пока шаблон 192.168.100.не найден в выходных данных ifconfig. Обратите внимание, что шаблон 192.168.100.соответствует строки, как 192x168 1007, потому что .в регулярном выражении соответствует любой символ; искать символьную строку, передать параметр -Fв grep. Чтобы инвертировать условие, поставьте !перед.

while ! ifconfig | grep -F "192.168.100." > /dev/null; do 

Далее в скрипте вы хотите сравнить значение переменной с числом. Вы используете -gtоператор, который является частью синтаксиса условных выражений, понятных testкоманде. Команда testвозвращает 0, если условное выражение истинно, и 1, если условное выражение ложно.

if test "$x" -gt 200; then

Принято использовать альтернативное имя [для testкоманды. Это имя предполагает, что команда заканчивается параметром ]. Два способа написания этой команды в точности эквивалентны.

if [ "$x" -gt 200 ]; then

Bash также предлагает третий способ написания этой команды со специальным синтаксисом [[ … ]]. Этот специальный синтаксис может поддерживать несколько больше операторов, чем [, потому что [это обычная команда, подчиненная обычным правилам синтаксического анализа, в то время как [[ … ]]является частью синтаксиса оболочки.

Опять же, имейте в виду, что [для условных выражений , которые являются синтаксисом с такими операторами, как -n, -gt[не означает «логическое значение»: любая команда имеет логическое значение (состояние выхода = 0?).

Обнаружение, что сеть работает

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

Вам действительно нужно запускать эти команды, когда кто-то входит в систему? Проще сделать команду запускаемой автоматически при включении сети. Способ сделать это зависит от вашего дистрибутива и от того, используете ли вы NetworkManager.

Если вам нужно выполнить эти команды как часть сценариев входа в систему, то проверьте ресурс, который вам действительно нужен, а не наличие IP-адреса. Например, если вы хотите проверить, /net/somenode/somedirсмонтирован ли он, используйте

while ! grep -q /net/somenode/somedir </proc/mounts; do
  sleep 1
done

Если у вас выскочка или системный ...

тогда вы можете использовать это. Например, с помощью Upstart пометьте свою работу как start on net-device-up eth0(замените eth0именем интерфейса, который обеспечивает желаемое сетевое подключение). С Systemd, см. Причины выполнения сценария после запуска сети?

Жиль "ТАК - перестань быть злым"
источник
Я думаю, /net/должно быть /proc/net?
Себикс
@sebix Нет, с чего бы это? Я не говорю о сетевой конфигурации Linux. Я привожу пример точки монтирования для удаленной файловой системы, /netэто общее расположение для таких точек монтирования.
Жиль "ТАК - перестань быть злым"
Итак, вам требуется подключенный сетевой диск. Существует ли более общее решение?
Себикс
@sebix Решение для чего? Требование подключенного сетевого диска было примером цели, а не примером решения.
Жиль "ТАК - перестань быть злым"
1

Просто посчитайте вывод, ip add showнапример:

root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
    inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
    inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2

Тогда вы можете просто перейти на номер строки, возвращаемой в зависимости от ситуации. Вы, вероятно, просто проверите, было ли это ноль, и если так, спите и повторите цикл.

Непроверенный код для иллюстрации:

while [ 1 ]; do

  if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
     break
  fi

  sleep 1

done
Bratchley
источник
1

Ping вернет ответ 0, если хотя бы одна попытка была успешной. Возможно, вы захотите пропинговать сервер, к которому вы подключаетесь, пока он не будет успешным.

brwtx
источник