Васильев Андрей
2020
Всего можно выделить 2 типа исполняемых файла:
Для запуска первых приложений достаточно только ОС, для работы вторых нужен установленный интерпретатор или соответствующая исполнительная машина
Типичный способ запуска таких приложений выглядит следующим образом:
интерпретатор файл-приложения
python app.py
ruby app.rb
bash script.sh
Приложение, реализованное на языке Python, обычно знает какой интерпретатор ему нужен, а вот его пользователь может не знать
В UNIX-мире есть механизм, позволяющий указать интерпретатор для запуска файла
Строка для выбора интерпретатора называется Shebang:
#!интерпретатор [аргументы]
В случае, если в начале файла указана данная строка, то при его запуске загрузчик постарается найти интерпретатор и запустит интерпретатор с указанным файлом
#!/bin/sh
— запуск интерпретатора Bourne Shell или совместимого с ним.#!/bin/bash
— запуск файла с помощью интерпретатора Bash.#!/usr/bin/python3
— запуск файла с помощью системного интерпретатора Python 3#!/usr/bin/env ruby
— запуск файла с помощью интерпретатора Ruby, поиск которого надо выполнять в PATH пользователя, вызывающего приложение#!/bin/false
— запретить выполнение файла через запуск, нужно например для файлов, предназначеных только для подключения к другим исполняемым скриптамПуть к интерпретатору должен быть абсолютным, т.к. данный механизм по умолчанию не использует подсистему поиска по PATH. Если необходима функциональность по поиску интерпретатора, тогда следует использовать /usr/bin/env
Рассмотрим простейшее приложение на языке Bash:
Запишем его в файл /home/user/script.sh
и дадим права на исполнение
$ cd /home/user
$ chmod +x script.sh
$ ./script.sh
Для запуска скрипта необходимо:
Исполняемые скрипты для выполнения административных задач в Linux можно писать на множестве языков: Python, Ruby, Perl, Bash и так далее
При выборе языка программирования необходимо учитывать множество факторов:
Если задача требует сложных вычислений и её необходимо поддерживать достаточно долго, то рекомендуется использовать более продвинутые языки программирования
С базовым синтаксисом Bash мы уже знакомы
Bash выполняет каждую строку как отдельную команду, которую вводили в терминале
Наиболее полная книжка по Bash называется Advanced Bash Scripting Guide
*
, ?
, [[:upper:]]
{abc, def}
$((5 + 10))
${VAR}
$(ls)
Все эти элементы можно и нужно использовать при написании скриптов
Для объявления переменной используется синтаксис:
Для получения доступа к значению переменной используйте $name
alias
, declare
, typeset
, export
, readonly
, local
unset name
#!/bin/bash
info='Some data goes here'
echo "Значение info: $info" # Просмотр переменной
files=$(ls) # Сохранение результата вызова ls
echo "$files"
$ ls
abc test.sh
$ ./test.sh
Some data goes here
abc
test.sh
Со знака #
начинаются комментарии
Для обхода набора значений удобно воспользоваться циклами
Циклы можно использовать для обработки вывода из приложения
if
Благодаря наличию данного оператора можно говорить, что Bash является языком программирования. Важно понимать, что этот язык — узкоспециализированный, ориентированный на обработку строк и запуск внешних задач, поэтому разрабатывать на нём сложные приложения не стоит
Синтаксис:
if list; then list;
[ elif list; then list; ] ...
[ else list; ]
fi
Если последняя команда из списка в условии вернёт 0, тогда будут выполнены команды в then
-списке, в противном случае будет протестированы команды из elif
Стандартное определение функции main
на языке Си:
int argc
— количество аргументовchar* argv[]
— массив с аргументамиchar** envp
— массив с переменными окружения в формате КЛЮЧ=ЗНАЧЕНИЕ
int main
, метод возвращает целое значение, обозначающее результат выполнения
В BASH переменная ?
позволяет узнать статус выполнения последней команды
test
Приложение позволяет проверить некоторые выражения и вернуть 1 или 0
test ВЫРАЖЕНИЕ
[ ВЫРАЖЕНИЕ ]
Написанное выражение подвергается обработке со стороны BASH как обычная строка, а после передаётся для выполнения в приложение test
Данное приложение предназначено для использования в if-выражении:
[[
Данная команда является расширением приложения test
и исправляет ряд его ограничений. Рекомендуется к использованию вместо приложения test
[[ ]]
не происходит расширения строк&&
, ||
внутри выражения(...)
Команду [[
следует использовать для сравнения строк и проверки файлов
test
Несколько проверок можно объединить с помощью &&
, ||
на уровне Bash:
Операторы &&
и ||
работают на уровне результатов работы приложения
test
и [[
Строковые проверки отличаются
[[ |
test | Пример |
---|---|---|
> |
\> |
[[ a > b ]] ложь, a идёт раньше b |
< |
\< |
[[ az < za ]] правда, a идёт раньше z |
= , == |
= |
[[ a = a ]] правда, a равно a |
!= |
!= |
[[ a != b ]] правда, a не равно b |
= , == |
нет | [[ name = n* ]] правда, name начинается с n |
=~ |
нет | [[ home =~ ^h+ ]] правда, home соответствует выражению |
-z |
-z |
[[ -z $info ]] правда, если строка в $info нулевой длины |
-n |
-n |
[[ -n $data ]] правда, если строка в $data ненулевой длины |
test
и [[
Числовые проверки между test
и [[
не отличаются
Проверка | Пример |
---|---|
-gt |
[[ 5 -gt 10 ]] ложь, 5 меньше 10 |
-lt |
[[ 8 -lt 9 ]] правда, 8 меньше 9 |
-eq |
[[ 5 -eq 3 ]] ложь, 5 не равно 3 |
-ne |
[[ 5 -ne 3 ]] правда, 5 не равно 3 |
-ge |
[[ 3 -ge 3 ]] правда, 3 больше или равно 3 |
-le |
[[ 3 -le 8]] правда, 3 меньше или равно 8 |
test
и [[
Проверка | Пример |
---|---|
-a |
[[ -a /tmp/data ]] правда, если файл существует |
-d |
[[ -d /var/log ]] правда, если директория существует |
-e |
[[ -e /run/info.pid ]] правда, если файл существует |
-f |
[[ -f /tmp/test ]] правда, если существует и является файлом |
-r |
[[ -r ~/info ]] правда, если файл доступен на чтение |
-w |
[[ -w ~/result ]] правда, если файл доступен на запись |
-x |
[[ -x ~/bin/run ]] правда, если файл можно выполнять |
while
и until
Помимо итеративного for в Bash также есть бесконечные циклы while и utlit:
while list-1; do list-2; done
until list-1; do list-2; done
while
будет выполнять свои действия пока условия в list-1
верныuntil
будет выполнять свои действия пока условия в list-1
неверныВыйти из цикла можно с помощью break [n]
Если передать число, тогда выход будет произведён из такого количества циклов
Для перехода к следующей итерации можно воспользоваться continue [n]
Если передать число, то продолжение будет на соответствующем уровне вложенности
while
Bash поддерживает следующие типы переменных:
Для декларирования переменной окружения используется команда export
:
export [name=[word]] ...
В переменные $0
, $1
, $2
записываются аргументы скрипта
$0
содержит название скрипта$1
содержит первый аргумент и т.д.${10}
$*
и $@
позволяют обратиться сразу ко всем переменным$#
позволяет получить количество переданных аргументовMINPARAMS=10
if [ $# -lt "$MINPARAMS" ]; then
echo
echo "This script needs at least $MINPARAMS arguments!"
fi
if [ -n "$1" ] # Tested variable is quoted.
then
echo "Parameter #1 is $1" # Need quotes to escape #
fi
if [ -n "${10}" ] # Parameters > $9 must be enclosed
then
echo "Parameter #10 is ${10}"
fi
Команда shift
производит “сдвиг” позиционных аргументов влево
$1 <--- $2, $2 <--- $3, $3 <--- $4, ...
Значение переменной $0 не изменяется
С помощью этой команды можно обойти все аргументы:
shift может сдвигать сразу на несколько позиций
Язык Bash имеет множество отличий в семантике работы от привычных языков программирования, поэтому надо быть осторожным с переносом своих привычек на язык Bash
Для проверки Bash-кода на наличие проблем рекомендуется использовать статический анализатор кода ShellCheck
Для установки его в GNU/Debian необходимо от имени сперпользователя
apt install shellcheck
$ shellcheck test.sh
In test.sh line 3:
until [ -z $1 ] # Until all parameters used up . . .
^-- SC2086: Double quote to prevent globbing and word splitting.
Did you mean:
until [ -z "$1" ] # Until all parameters used up . . .
For more information:
https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...