Как передать аргументы в скрипт Bash?

В этой статье мы создадим простой Bash-скрипт и покажем, как передавать ему аргументы с помощью командной строки Linux.

Как передать аргументы в скрипт Bash?

Аргументы, передаваемые в скрипт Bash, следуют за именем скрипта в командной строке и отделяются друг от друга пробелом. На каждый аргумент в скрипте можно ссылаться с помощью позиционных параметров, определенных по умолчанию в Bash ($1, $2, $3 и т. д.).

Имея домен, мы хотим узнать сопоставленный ему IP-адрес.

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

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

Передача аргументов в скрипт Bash позволяет использовать тот же скрипт более универсальным способом, вместо того чтобы делать его зависимым от конкретных значений, жестко запрограммированных в скрипте.

Давайте начнем!

Первая версия «Сценария без аргументов»

В первой версии нашего скрипта мы просто используем команду dig для вывода IP-адреса для google.com. В нашем скрипте мы выполним следующую команду:

dig +short google.com

Итак, давайте создадим наш базовый скрипт Bash, назовем его dns_resolver.sh. Где .sh — это стандартное расширение для скриптов Shell.

Для редактирования скрипта можно использовать редактор vim:

vim dns_resolver.sh

Ниже вы можете увидеть содержание скрипта:

#!/bin/bash

dig +short google.com 

Что означает #!/bin/bash?

Это называется Shebang, но это на другой раз, а пока вы можете использовать его таким, какой он есть, и помнить, что он всегда будет первой строкой в ​​ваших скриптах Bash.

Выполнение вашего сценария

Для выполнения скрипта используйте следующую команду:

./dns_resolver.sh

Что происходит?

./dns_resolver.sh
-bash:./dns_resolver.sh: Permission denied 

Почему возникает ошибка «Отказано в доступе»?

ls -al dns_resolver.sh
-rw-r--r--  1 ec2-user  ec2-user  35 16 Feb 13:23 dns_resolver.sh

Потому что для скрипта не установлены права на исполнение, что подтверждается командой ls выше.

Итак, что мы можем сделать сейчас? Как нам установить права на исполняемый файл?

Мы можем использовать команду chmod для установки прав на исполнение нашего скрипта:

chmod +x dns_resolver.sh 
ls -al dns_resolver.sh 
-rwxr-xr-x  1 ec2-user  ec2-user  35 16 Feb 13:23 dns_resolver.sh

Команда chmod +x назначает права на исполнение нашего скрипта пользователю-владельцу, владельцу группы и другим.

Вы можете увидеть выделенные жирным шрифтом разрешения на исполнение, назначенные скрипту (обозначенные буквой x).

И теперь попробуем выполнить скрипт еще раз:

./dns_resolver.sh
172.217.169.78 

Бинго!! Теперь скрипт работает как надо и возвращает IP-адрес для google.com.

Разница между аргументами и параметрами в Bash

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

Аргументы — это те, которые вы передаете в командной строке рядом с именем скрипта:

./dns_resolver.sh arg1 arg2 arg3

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

Параметры относятся к переменным, которым назначаются аргументы.

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

Имена позиционных параметров по умолчанию в Bash:

$0, $1, $2, $3, etc...

В следующей таблице показано значение позиционных параметров Bash:

Имя параметраЦенить
$0Название сценария
$1Значение первого аргумента
$1Значение второго аргумента
$nЗначение n-го аргумента

Таким образом, параметры называются позиционными, поскольку значение первого аргумента присваивается параметру $1, значение второго аргумента — параметру $2 и т. д.

Используете $1 в нашем Bash-скрипте?

Хорошо, теперь вы знаете, как ведут себя позиционные параметры.

Теперь, когда у нас есть работающий скрипт, мы хотим иметь возможность передавать значение google.com через командную строку.

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

Итак, мы хотим выполнить скрипт следующим образом:

./dns_resolver.sh google.com

Затем скрипт должен прочитать аргумент google.com и передать его команде dig.

Для этого мы воспользуемся параметром $1, который, как мы уже говорили, в Bash имеет значение первого аргумента, переданного скрипту.

Итак, наш сценарий становится таким:

#!/bin/bash

dig +short $1 

Давайте выполним это и посмотрим, что произойдет:

./dns_resolver.sh google.com
172.217.169.14 

Круто, работает! А что насчет другого домена?

./dns_resolver.sh codefather.tech
176.58.107.26

Он тоже работает!! Итак, теперь у нас есть скрипт, который намного мощнее первой версии.

И таким же образом мы используем $1 для чтения первого аргумента, переданного скрипту через командную строку, мы можем использовать $2, $3, $4 и т. д. для второго, третьего и четвертого аргумента… и так далее.

Для ясности давайте выведем значения $2 и $3 при выполнении нашего скрипта с помощью команды echo:

#!/bin/bash

dig +short $1

echo "The value of the second argument is: $2"
echo "The value of the third argument is: $3"

Если я запущу скрипт так же, как и раньше, то получу:

./dig.sh codefather.tech
176.58.107.26
The value of the second argument is:
The value of the third argument is:

Второй и третий аргументы пустые, поскольку я не указал их в командной строке.

Давайте передадим некоторые фиктивные значения в качестве второго и третьего аргументов:

./dig.sh codefather.tech domain2 domain3
176.58.107.26
The value of the second argument is: domain2
The value of the third argument is: domain3

На этот раз значения $2 и $3 выводятся в терминал, и если я захочу, я могу использовать их в логике моего скрипта.

Что такое $@ в Bash?

Bash предоставляет специальную переменную $@ — массив, содержащий все позиционные параметры.

Давайте используем цикл for для чтения всех значений в $@ при выполнении нашего скрипта:

#!/bin/bash

for ITEM in "$@"
do
    echo $ITEM
done

И вот что получается:

$./dig.sh codefather.tech domain2 domain3
codefather.tech
domain2
domain3

Имеет ли это смысл?

Как проверить количество аргументов, переданных в скрипт Bash

Еще одна вещь, которая может быть очень полезна при написании скрипта, — это проверка количества аргументов, переданных скрипту.

Эту проверку можно использовать, чтобы убедиться, что пользователь передает правильное количество аргументов.

Это поможет вам предотвратить ошибки во время выполнения скрипта, вызванные отсутствием аргументов.

Количество аргументов, переданных скрипту Bash, хранится в переменной $#.

Давайте обновим наш предыдущий скрипт, чтобы он также выводил количество переданных аргументов:

#!/bin/bash

echo "The number of arguments passed to the script is: $#"

for ITEM in "$@"
do
    echo $ITEM
done

И вот что получается:

(base) Jeter:bash claudiosabato$./dig.sh codefather.tech domain2 domain3
The number of arguments passed to the script is: 3
codefather.tech
domain2
domain3

Кроме того, для проверки значения $# можно использовать оператор if:

if [ $# -ne 3 ]; then
    echo "The number of arguments passed is incorrect"
    exit 1
fi

Если количество аргументов неверно, мы немедленно останавливаем выполнение скрипта, используя команду выхода.

Как проверить, являются ли аргументы Bash пустыми?

Другой способ проверки переданных аргументов — проверка пустых позиционных параметров.

Например, я могу использовать оператор if else, чтобы проверить, является ли параметр $2 пустым:

#!/bin/bash

echo "The number of arguments passed to the script is: $#"

if [ "$2" == "" ]; then
    echo "ERROR: The second argument is empty"
fi

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

$./dig.sh codefather.tech
The number of arguments passed to the script is: 1
ERROR: The second argument is empty

Заключение

В этой статье мы узнали, как создать новый Bash-скрипт с помощью vim, как его выполнить и как передавать аргументы через командную строку.

Я также объяснил:

  • Разница между аргументами и позиционными параметрами.
  • Как распечатать все параметры с помощью $@.
  • Значение переменной $#, содержащей количество аргументов, переданных скрипту.
  • Как проверить, является ли аргумент пустым.

Имеет ли это смысл?

Что еще можно сделать для улучшения созданного нами скрипта DNS-резолвера?