Назад | Перейти на главную страницу

добавление строки и переменной к другой переменной в сценарии bash

Я попытался создать сценарий bash, чтобы показать все доступные локальные IP-адреса. Поскольку обычный параметр ping не может работать быстрее 1 секунды на IP-адрес, а fping показывает слишком много вывода при выполнении в цикле for, я попытался сделать это следующим образом:

read -p "Enter Gateway IP Address: " gateway
for ip in $(seq 1 254);
    allips = $allips ${gateway::-1} $ip
done
fping -c1 -t500 -a $allips > /dev/null

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

local.sh: line 2:  : command not found
local.sh: line 4: syntax error near unexpected token `allips'
local.sh: line 4: ` allips = $allips ${gateway::-1} $ip'

В вашем скрипте есть ряд синтаксических ошибок; Я пройдусь по ним в конце. Но сначала кажется, что есть более простой способ сканировать подсеть / 24: fpingс -g (генератор) вариант. У меня нет fping установлен для тестирования, но из документация, это должно работать:

#!/bin/bash
read -p "Enter Gateway IP Address: " gateway
fping -c1 -t500 -a -g "${gateway%.*}.0/24" > /dev/null

В ${gateway%.*} часть берет введенный IP-адрес шлюза и обрезает, начиная с последнего "." (т.е. последний октет). Итак, если шлюз - «192.168.0.254», это «192.168.0». Затем сценарий добавляет к нему «.0 / 24», чтобы получить «192.168.0.0/24» в качестве строки подсети.

Проблемы в исходном скрипте:

  • Начните свои сценарии с соответствующей строки shebang. Обычно это будет #!/bin/bash или #!/usr/bin/env bash. Вы также увидите #!/bin/sh, но это может вызвать проблемы, если вы используете в своем скрипте какие-либо расширения синтаксиса bash. Если вы не знаете тонкостей синтаксиса bash vs plain sh, придерживайтесь bash shebang.

  • Ваш for в заявлении отсутствует do. Так должно быть for ip in $(seq 1 254); do.

  • bash v3 не допускает отрицательных строковых индексов (например, ${gateway::-1}). Если у вас версия bash 4, это сработает; если у вас v3, вам нужно вычесть единицу из длины строки: ${gateway::${#gateway}-1}. Или вы можете использовать оператор обрезки от конца, %, как я сделал в моем коде выше. Если вы используете ${gateway%.*}, это удалит последний "." а также номер, поэтому вам нужно добавить его обратно. Другое преимущество заключается в том, что это также будет работать, если последний октет состоит более чем из одной цифры (например, некоторые люди по какой-то причине ставят свои маршрутизаторы на 0,254).

  • Вы должны почти всегда заключать ссылки на переменные в двойные кавычки, чтобы избежать различных форм неправильного анализа пробелов, подстановочных знаков и т. Д. В этом случае это, вероятно, безопасно, но я бы все равно этого избегал. Но в вашем скрипте вы рассчитываете на разделение слов, чтобы каждый адрес передавался как отдельный аргумент в fping. Лучший способ сделать это в сценарии оболочки - использовать массив, а не простую переменную, причем каждый аргумент является отдельным элементом массива. Синтаксис для этого немного запутан, но основные операции следующие:

    args=(arg1 arg2 "arg with spaces")    # The parentheses tell bash this is an array
    for x in list of things; do
        args+=(additionalarg)    # Add elements to array. Both + and () are REQUIRED
    done
    somecommand "${args[@]}"    # Yes, all those parentheses, brackets, etc are needed
    
  • Вы не можете использовать пробелы в назначении (если вы не заключаете их в кавычки или экранируете, и в этом случае они являются частью присвоенной строки). Когда вы используете var = something, оболочка рассматривает это как выполнение команды var, с участием = и something как аргументы. Итак, ваше задание должно выглядеть примерно так:

    allips="$allips ${gateway::-1}$ip"
    

    ... за исключением того, что, как я сказал выше, вы должны использовать массив. Поэтому установите его на пустой перед циклом (allips=()), а затем используйте:

    allips+=("${gateway%.*}.$ip")
    

    А затем после цикла используйте его так:

    fping -c1 -t500 -a "${allips[@]}" > /dev/null