Bash: различия между версиями

Материал из sysadm
Перейти к навигации Перейти к поиску
 
(не показаны 3 промежуточные версии этого же участника)
Строка 29: Строка 29:
 
   <command>
 
   <command>
 
fi
 
fi
 +
</pre>
 +
 +
'''команда '[ ' или test'''
 +
<pre>
 +
В большинстве реализаций bash элемент '[ ' и 'test' обрабатывается как внутренняя команда и не запускает исполняемые файлы /bin/[ или /bin/test
 +
 +
# проверить можно так
 +
type [
 +
[ is a shell builtin
 +
 +
type test
 +
test is a shell builtin
 +
 +
type /bin/[
 +
/bin/[ is /bin/[
 +
 +
Обе команды и утилиты имеют идентичный набор параметров.
 +
Важно, что при использовании [ последним аргументом всегда должна быть закрывающая квадратная скобка ].
 +
 +
Основные категории параметров (выражений для проверки):
 +
1. Проверка файлов (File operators)
 +
 +
    [ -a ФАЙЛ ] - Истинно, если файл существует.
 +
    [ -b ФАЙЛ ] - Истинно, если файл существует и является блочным специальным файлом.
 +
    [ -c ФАЙЛ ] - Истинно, если файл существует и является символьным специальным файлом.
 +
    [ -d ФАЙЛ ] - Истинно, если файл существует и является каталогом.
 +
    [ -e ФАЙЛ ] - Истинно, если файл существует (любого типа).
 +
    [ -f ФАЙЛ ] - Истинно, если файл существует и является обычным файлом.
 +
    [ -g ФАЙЛ ] - Истинно, если файл существует и имеет установлен бит SGID.
 +
    [ -h ФАЙЛ ] или [ -L ФАЙЛ ] - Истинно, если файл существует и является символической ссылкой.
 +
    [ -k ФАЙЛ ] - Истинно, если файл существует и имеет установлен бит "sticky".
 +
    [ -p ФАЙЛ ] - Истинно, если файл существует и является именованным каналом (pipe) или FIFO.
 +
    [ -r ФАЙЛ ] - Истинно, если файл существует и доступен для чтения (текущим пользователем).
 +
    [ -s ФАЙЛ ] - Истинно, если файл существует и его размер больше нуля.
 +
    [ -t FD ] - Истинно, если файловый дескриптор FD открыт на терминале.
 +
    [ -u ФАЙЛ ] - Истинно, если файл существует и имеет установлен бит SUID.
 +
    [ -w ФАЙЛ ] - Истинно, если файл существует и доступен для записи.
 +
    [ -x ФАЙЛ ] - Истинно, если файл существует и доступен для выполнения (или поиска, если это каталог).
 +
 +
2. Сравнение строк (String operators)
 +
 +
    [ СТРОКА ] - Истинно, если строка не пустая.
 +
    [ СТРОКА1 = СТРОКА2 ] - Истинно, если строки равны.
 +
    [ СТРОКА1 != СТРОКА2 ] - Истинно, если строки не равны.
 +
    [ СТРОКА1 < СТРОКА2 ] - Истинно, если СТРОКА1 лексикографически меньше СТРОКА2.
 +
    [ СТРОКА1 > СТРОКА2 ] - Истинно, если СТРОКА1 лексикографически больше СТРОКА2.
 +
    [ -z СТРОКА ] - Истинно, если длина строки нулевая (пустая строка).
 +
    [ -n СТРОКА ] - Истинно, если длина строки ненулевая (не пустая строка).
 +
 +
3. Сравнение чисел (Integer operators)
 +
 +
    [ ЧИСЛО1 -eq ЧИСЛО2 ] - Истинно, если числа равны.
 +
    [ ЧИСЛО1 -ne ЧИСЛО2 ] - Истинно, если числа не равны.
 +
    [ ЧИСЛО1 -gt ЧИСЛО2 ] - Истинно, если ЧИСЛО1 больше, чем ЧИСЛО2.
 +
    [ ЧИСЛО1 -ge ЧИСЛО2 ] - Истинно, если ЧИСЛО1 больше или равно ЧИСЛО2.
 +
    [ ЧИСЛО1 -lt ЧИСЛО2 ] - Истинно, если ЧИСЛО1 меньше, чем ЧИСЛО2.
 +
    [ ЧИСЛО1 -le ЧИСЛО2 ] - Истинно, если ЧИСЛО1 меньше или равно ЧИСЛО2.
 +
 +
4. Логические операторы (Logical operators)
 +
 +
    [ ! ВЫРАЖЕНИЕ ] - Истинно, если ВЫРАЖЕНИЕ ложно (логическое отрицание).
 +
    [ ВЫРАЖЕНИЕ1 -a ВЫРАЖЕНИЕ2 ] - Истинно, если оба выражения истинны (логическое И).
 +
    [ ВЫРАЖЕНИЕ1 -o ВЫРАЖЕНИЕ2 ] - Истинно, если хотя бы одно выражение истинно (логическое ИЛИ).
 +
 +
**Ключевой момент:** При использовании `[` как отдельной утилиты (или встроенной команды), пробелы вокруг скобок и операторов обязательны.
 +
</pre>
  
# пример, если ошибка, то
+
'''ПРИМЕРЫ'''
# ! - команда отрицания
+
<pre>
# [ - команда проверки условия (пробелы важны)
+
# если ошибка, то
if ! [ $? -eq 0 ]
+
if [ $? -ne 0 ]; then
then
 
 
   echo ERROR
 
   echo ERROR
 
fi
 
fi
Строка 45: Строка 110:
 
fi
 
fi
  
 +
# если параметр 1 определен, то
 
if [ -n "$1" ]; then
 
if [ -n "$1" ]; then
     echo "Параметр 1 существует и не пуст: $1"
+
     echo "передан параметр $1"
 
else
 
else
     echo "Параметр 1 либо отсутствует, либо пуст."
+
     echo "параметр не передан"
 
fi
 
fi
  
 
if [ -z "$1" ]; then
 
if [ -z "$1" ]; then
     echo "Параметр 1 либо отсутствует, либо пуст."
+
     echo "параметр не передан"
 
else
 
else
     echo "Параметр 1 существует и не пуст: $1"
+
     echo "передан параметр $1"
 
fi
 
fi
 
</pre>
 
 
'''опции команды ['''
 
<pre>
 
 
-n <операнд>              # истина, если строка операнда имеет не нулевую длину
 
-z <операнд>              # истина, если строка операнда имеет нулевую длинну
 
<операнд1> -eq <операнд2>  # истина, если <операнд1> равен <операнд2>, оба операнда должны иметь числовой тип
 
 
 
</pre>
 
</pre>
  

Текущая версия на 16:31, 26 ноября 2025

Обзор

bash - это наиболее популярный но не единственный командный интерпретатор в среде Linux.

Исполняемый файл обычно расположен здесь /bin/bash.

Код скрипта должен начинаться строкой

#!/bin/bash

Варианты запуска скрипта

# текущий командный интерпретатор запустит интерпретатор bash как дочерний процесс, который выполнит скрипт
/bin/bash /home/myuser/myscript.sh

# текущий интерпретатор выполнит скрипт в рамках своего процесса,
# если в строке #! не задан другой тип интерпретатора 
. /home/myuser/myscript.sh

Условия

if <command>
then
  <command>
else
  <command>
fi

команда '[ ' или test

В большинстве реализаций bash элемент '[ ' и 'test' обрабатывается как внутренняя команда и не запускает исполняемые файлы /bin/[ или /bin/test

# проверить можно так
type [
[ is a shell builtin

type test
test is a shell builtin

type /bin/[
/bin/[ is /bin/[

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

Основные категории параметров (выражений для проверки):
1. Проверка файлов (File operators)

    [ -a ФАЙЛ ] - Истинно, если файл существует.
    [ -b ФАЙЛ ] - Истинно, если файл существует и является блочным специальным файлом.
    [ -c ФАЙЛ ] - Истинно, если файл существует и является символьным специальным файлом.
    [ -d ФАЙЛ ] - Истинно, если файл существует и является каталогом.
    [ -e ФАЙЛ ] - Истинно, если файл существует (любого типа).
    [ -f ФАЙЛ ] - Истинно, если файл существует и является обычным файлом.
    [ -g ФАЙЛ ] - Истинно, если файл существует и имеет установлен бит SGID.
    [ -h ФАЙЛ ] или [ -L ФАЙЛ ] - Истинно, если файл существует и является символической ссылкой.
    [ -k ФАЙЛ ] - Истинно, если файл существует и имеет установлен бит "sticky".
    [ -p ФАЙЛ ] - Истинно, если файл существует и является именованным каналом (pipe) или FIFO.
    [ -r ФАЙЛ ] - Истинно, если файл существует и доступен для чтения (текущим пользователем).
    [ -s ФАЙЛ ] - Истинно, если файл существует и его размер больше нуля.
    [ -t FD ] - Истинно, если файловый дескриптор FD открыт на терминале.
    [ -u ФАЙЛ ] - Истинно, если файл существует и имеет установлен бит SUID.
    [ -w ФАЙЛ ] - Истинно, если файл существует и доступен для записи.
    [ -x ФАЙЛ ] - Истинно, если файл существует и доступен для выполнения (или поиска, если это каталог). 

2. Сравнение строк (String operators)

    [ СТРОКА ] - Истинно, если строка не пустая.
    [ СТРОКА1 = СТРОКА2 ] - Истинно, если строки равны.
    [ СТРОКА1 != СТРОКА2 ] - Истинно, если строки не равны.
    [ СТРОКА1 < СТРОКА2 ] - Истинно, если СТРОКА1 лексикографически меньше СТРОКА2.
    [ СТРОКА1 > СТРОКА2 ] - Истинно, если СТРОКА1 лексикографически больше СТРОКА2.
    [ -z СТРОКА ] - Истинно, если длина строки нулевая (пустая строка).
    [ -n СТРОКА ] - Истинно, если длина строки ненулевая (не пустая строка).

3. Сравнение чисел (Integer operators)

    [ ЧИСЛО1 -eq ЧИСЛО2 ] - Истинно, если числа равны.
    [ ЧИСЛО1 -ne ЧИСЛО2 ] - Истинно, если числа не равны.
    [ ЧИСЛО1 -gt ЧИСЛО2 ] - Истинно, если ЧИСЛО1 больше, чем ЧИСЛО2.
    [ ЧИСЛО1 -ge ЧИСЛО2 ] - Истинно, если ЧИСЛО1 больше или равно ЧИСЛО2.
    [ ЧИСЛО1 -lt ЧИСЛО2 ] - Истинно, если ЧИСЛО1 меньше, чем ЧИСЛО2.
    [ ЧИСЛО1 -le ЧИСЛО2 ] - Истинно, если ЧИСЛО1 меньше или равно ЧИСЛО2.

4. Логические операторы (Logical operators)

    [ ! ВЫРАЖЕНИЕ ] - Истинно, если ВЫРАЖЕНИЕ ложно (логическое отрицание).
    [ ВЫРАЖЕНИЕ1 -a ВЫРАЖЕНИЕ2 ] - Истинно, если оба выражения истинны (логическое И).
    [ ВЫРАЖЕНИЕ1 -o ВЫРАЖЕНИЕ2 ] - Истинно, если хотя бы одно выражение истинно (логическое ИЛИ).

**Ключевой момент:** При использовании `[` как отдельной утилиты (или встроенной команды), пробелы вокруг скобок и операторов обязательны.

ПРИМЕРЫ

# если ошибка, то
if [ $? -ne 0 ]; then
  echo ERROR
fi

# проверка на существование файла
if [ -f /path/to/file ]; then
    echo 'File exists.'
else
    echo 'File does not exist.'
fi

# если параметр 1 определен, то
if [ -n "$1" ]; then
    echo "передан параметр $1"
else
    echo "параметр не передан"
fi

if [ -z "$1" ]; then
    echo "параметр не передан"
else
    echo "передан параметр $1"
fi

Циклы

for

По списку

for <var> in <list>
do
  команды
done

<list> := если путь к каталогу, то перечисляется содержимое каталога
<list> := если текст, то перечисляются фрагменты текста, разделитель определяется переменной $IFS. По умолчанию, IFS=' '.

# пример перечисления строк файла
IFS=$'\n'
for a in $(cat /etc/password)
do 
  echo $a
done

# пример перечисления массива
myArr[0]='item1'
myArr[1]='item2'
myArr[2]='item3'

for i in "${!myArr[@]}"
do
  echo ${myArr[$i]}
done


В стиле С

for (( i=0; i<10; i++ ))
do
  команды
done

команды управления циклом

# прервать текущую итерацию и перейти к следующей
continue

# прервать цикл
break

Перенаправление вывода


 >  Syntax: file_descriptor >  file_name
 >& Syntax: file_descriptor >& file_descriptor
 &> Syntax: &> file_name

# примеры
 ls > file.txt    # перенаправление stdout в файл
 ls 1 > file.txt  # перенаправление stdout в файл

 ls 2 > file.err  # перенаправление stderr в файл
 ls 2>&1          # перенаправление stderr в stdout

 ls 1 > file.txt 2 > file.txt  # перенаправление stdout и stderr в file.txt, файл будет открыт один раз
 ls &> file.txt                # перенаправление stdout и stderr в file.txt, файл будет открыт один раз

Cкобки (brackets)

Ссылки по теме:

( ... ) - блок команд, выполняется в рамках отдельного дочернего процесса

a=2
(
  a=3
  echo $a
)
echo $a

#вывод будет таким
3
2

{ ... } - блок команд, выполняются в рамках текущего процесса

a=2
{
  a=3
  echo $a
}
echo $a

#вывод будет таким
3
3

<( ... ) - блок команд, вывод которых передается в динамически создаваемую область памяти, при этом сам блок возвращает путь к этой области в виде /dev/fd/63. Также необходимо учитывать, что данные области памяти удаляются сразу после выполнения первого дочернего процесса запущенного скриптом.

echo <(echo test1; echo test2) <(echo test3)

#вывод
/dev/fd/63 /dev/fd/62

cat <(echo test1; echo test2) <(echo test3)

#вывод
test1
test2
test3

Ввод пароля

echo password:
read -s pass
mysql -u root -p $pass

Функции

function MyFunc {
  echo Параметр 1 [$1]
  echo Параметр 2 [$2]
  return 0
}

MyFunc vol1 vol2

запуск фоновых процессов

command &       # запускает процесс и не ожидая его завершения возвращает управление родительскому процессу
                # вывод процесса направляется в stdout родительского процесса
                # закрытие родительского процесса приводит к закрытию процесса

# при закрытии родительского процесса всем дочерним процессам направляется сигнал HUP (hang up), что приводит к закрытию всех дочерних процессов
# команда nohup (no hang up) запускает дочерний процесс с запретом принимать сигнал HUP, поэтому данный дочерний процесс не закрывается при закрытии родительского 

# при запуске через nohup, stdout и stderr дочернего процесса направляется в файл nohup.out, который создается в текущем каталоге
# чтобы файл nohup.out не создавался, необходимо перенаправить stdout и stderr в файл или в /dev/null

nohup command &> /dev/null &       # процесс запускается, вывод направляется в /dev/null, управление возвращается в консоль
                                   # при закрытии консоли, процесс не закрывается

Обработка ошибок

Прерывание

set -e
# некоторый критический блок кода, где ошибка недопустима
# выполнение скрипта прервется, если какая-либо команда вернет не 0
# но это не будет работать для промежуточных команд в серии пайпов
true | false | true
echo "Это будет напечатано"
set +e

set -o pipefail -e
# код будет прерван, даже если ошибка возникла внутри серии пайпов
true | false | true
echo "Это не будет напечатано"
set +e

Ловушки

#!/bin/bash

trap 'echo trap SIGINT' SIGINT
trap 'echo trap SIGTERM' SIGTERM
trap 'echo trap SIGHUP' SIGHUP
trap 'echo trap SIGQUIT' SIGQUIT
trap 'echo trap EXIT' EXIT
trap 'echo trap ERR' ERR

echo 'start'
sleep 1m
echo 'end'

# удаление ловушки
trap - ERR

# ловушка ERR не срабатывает на команде, если используется конструкция
command && echo OK || echo ERROR

# устанавливает наследование trap (DEBUG, RETURN) в функциях и subshell процессах
set -T
# устанавливает наследование trap (ERR) в функциях и subshell процессах
set -E