Тариф успешно добавлен в корзину
В корзину
url image

Часть 4. Bash-скрипты. Управление заданиями, here-документы, конвейер

Перед чтением этой статьи рекомендуем ознакомиться с предыдущими из серии Основы написания bash-скриптов:

  1. Знакомство с bash
  2. Часть 1. Bash-скрипты. Основные команды и рекомендации
  3. Часть 2. Bash-скрипты. Переменные, комментарии, пользовательский ввод
  4. Часть 3. Bash-скрипты. Перенаправление ввода и вывода

В этой статье рассмотрим дополнительные способы управлять взаимодействием между командами bash и выполнением команд: 

Управление заданиями

В каждый конкретный момент на переднем плане (foreground) находится только один процесс Linux. С ним можно взаимодействовать при помощи клавиатуры, и он выводит на экран выходной поток (если stdout предусмотрен и выводится в терминал, а не перенаправляется).

Остальные запущенные процессы выполняются в фоне (background). Они не связаны с терминалом — не выводят на него данные и не получают их с клавиатуры.

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

Например, удобно переводить в фон длительные процессы — в том числе и команды, соединённые операторами перенаправления. Для этого в конце команды ставят амперсанд &

Следующая команда создаёт архив каталога /home/lite и перенаправляет его стандартный вывод в файл, а затем переводит процесс в фоновый режим:

tar -czf /backup/home-lite.tar.gz /home/lite > /backup/logs/tar-home-lite-backup.log 2>&1 &

1) Команда tar создаёт (ключ -c) при помощи программы gzip (-z) файл (-f/backup/home-lite.tar.gz — архив каталога /home/lite.

2) Оператор > перенаправляет вывод команды tar в файл лога.

3) Выражение 2>&1 перенаправляет сообщения об ошибках в поток stdout.

4) Оператор & в конце команды переводит выполнение в фоновый режим.

Выводимый результат:

[1] 77612

Здесь [1] ID задания77612 — ID процесса (PID).

ID задания (job ID) присваивает оболочка bash, когда оператор & переводит процесс в фоновый режим. PID — идентификатор процесса в операционной системе. 

Список всех запущенных процессов (включая их PID) всех пользователей и используемые ими системные ресурсы можно просмотреть этой командой:

ps -aux

Команды управления заданиями

Можно переводить в фоновый режим несколько команд последовательно — вторую, пока не выполнена первая, и так далее. Заданиями в списке можно управлять при помощи следующих команд:

1) jobs — вывести список фоновых заданий:

[1]+  Running              tar -czf /backup/home-lite.tar.gz /home/lite > backup/logs/tar-home-lite-backup.log 2>&1

 2) fg %1 — вывести задание с ID=1 из фонового режима.

Задание будет выведено на передний план и будет занимать терминал до завершения выполнения.

3) Ctrl+Z, затем bg %1 — приостановить выполнение задания и перевести его в фоновый режим.

4) kill %1 — завершить выполнение команды; 

  kill -9 %1 — принудительно завершить выполнение команды.

Here-документы

Here-документ (HereDoc) — это фрагмент кода или текста из нескольких строк, передаваемый на вход другим командам и программам. Оболочка bash работает с ним как с файлом.

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

Общий вид синтаксиса:

команда << ограничитель 
  строка 1
  строка 2
ограничитель

Here-документы работают с любыми командами, принимающими перенаправление.

Дефис после оператора перенаправления <<- позволяет игнорировать табуляцию в теле документа.

Ограничитель в первой строке — маркер начала here-документа. Чаще всего используют EOF или EOL, но подойдет любое слово (согласно определению в рамке ниже) длиной от одного символа, которое отсутствует в теле документа — например, цифра или спецсимвол. Ограничителем в начале here-документа может быть и экранированный метасимвол — тогда в конце документа этот метасимвол не требуется экранировать.

Слово (согласно Руководству GNU по оболочке bash) — последовательность символов, воспринимаемая оболочкой как единое целое. Слова не могут содержать метасимволов, не заключённых в кавычки.

Метасимволы (согласно тому же Руководству) — символы, которые разделяют слова, если используются без кавычек. К ним относятся: пробел, знак табуляции, перенос строки и следующие символы: |, &, ;, (, ), < и >. 

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

Тело here-документа содержит любое количество строк (завершающихся переносом строки) с командами, переменными, строковыми литералов и других входных данных.

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

В следующем скрипте here-документы используются при соединении с удалённым сервером по протоколу SSH для изменения пароля пользователя СУБД MySQL:

#!/bin/bash

remote_user="lite"
remote_host="somehost"
mysql_user="mylite"
new_password="betterpassword"

ssh $remote_user@$remote_host << EOF
mysql -u root -p'somesecurepassword' << EOL
ALTER USER '$mysql_user'@'localhost' IDENTIFIED BY '$new_password';
FLUSH PRIVILEGES;
EOL
EOF

Скрипт выполняет следующие действия:

1) Присваиваются значения переменным. 

  • remote_user означает пользователя на удалённом сервере,
  • remote_host — удалённый сервер, 
  • mysql_user — пользователя  СУБД MySQL на удалённом сервере, 
  • new_password — новый пароль.

2) Команда ssh запускает сеанс связи пользователя с удалённым сервером. Этой команде перенаправляется содержимое here-документа, который начинается с ограничителя EOF.

4) Тело here-документа — вход пользователя root в СУБД MySQL при помощи команды mysql. Ей, в свою очередь, перенаправляется содержимое следующего here-документа, который начинается с ограничителя EOL.

5) Внутри второго документа команда ALTER USER изменяет пароль пользователя с именем, которое содержится в переменной mysql_user, на значение переменной new_password.

6) Команда FLUSH PRIVILEGES обновляет таблицы привилегий (прав) пользователей MySQL.

7) Конец второго документа обозначается ограничителем EOL, конец первого — ограничителем EOF.

Here strings

Here strings (here-строки) — разновидность here-документов для передачи слов (последовательностей символов согласно определению в предыдущем разделе) на стандартный вход команд.

Это означает, что если в here-строке есть метасимволы, нужно заключить её в кавычки целиком или экранировать метасимволы.

Here strings не имеют ограничителей в начале и конце.

Синтаксис в общем виде выглядит так:

команда <опции> <<< слово

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

Следующая команда считает количество слов в передаваемой ей строке:

wc -w <<< "The word undergoes tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal."

Выводимый результат:

16

От команд echo или cat тоже можно быстро перенаправить строку какой-либо команде через конвейер

Любая из двух следующих команд:

  1. echo "ТЕКСТ, НАБРАННЫЙ ПРОПИСНЫМИ БУКВАМИ" | tr [A-Z] [a-z]

или

  1. tr [A-Z] [a-z] <<< "ТЕКСТ, НАБРАННЫЙ ПРОПИСНЫМИ БУКВАМИ"

выведет на экран такой результат:

текст, набранный прописными буквами

При этом here-строки проще читать человеку, так как в них нет дополнительных элементов помимо принимающей команды, оператора перенаправления и передаваемой строки. Поэтому в большинстве случаев для перенаправления команде короткой строки стоит выбирать here strings.

Конвейер

Конвейер (pipeline, пайп), обозначаемый символом вертикальной черты | — это механизм межпроцессного взаимодействия, который направляет стандартный вывод и иногда стандартную ошибку одного процесса на стандартный ввод другого. Таким образом команды можно соединять в последовательности и быстро выполнять многоступенчатую обработку данных из командной строки или в скриптах.

Согласно Руководству GNU по оболочке bash конвейер относится к управляющим операторам.

Общий вид синтаксиса:

команда 1 | команда 2

В разделе Перенаправление ввода с добавлением >> статьи Перенаправление ввода и вывода показан пример выгрузки массива данных из базы данных MySQL и его конвертации в формат .csv. 

Если потребовалось отобразить строки этого массива в другом порядке и в формате, который удобен для чтения, а не для машинной обработки, но в данный момент нельзя сделать повторную выгрузку этого массива, то можно получить нужное отображение при помощи bash: 

column -s, -t customers_100.csv | sort -k4 | less -S

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

1.Программа column читает содержимое файла customers_100.csv и отображает его в удобочитаемом для человека виде — разделяет столбцы пробелами в нужных количествах, а не запятыми.

2. Cодержимое по конвейеру | направляется команде sort, которая по ключу -k4 упорядочивает строки по содержимому четвёртого столбца, то есть по фамилиям — фамилии упорядочиваются от A к Z:

3. Упорядоченное содержимое по конвейеру передаётся команде less, чтобы на экране не отображались все столбцы сразу, а можно было прокручивать таблицу при помощи клавиш «влево» и «вправо».

Конвейер можно использовать в одной команде с перенаправлениями разных видов:

команда1 | команда2 | команда3 > файл_с_результатом

Например:

df -h | grep '/dev/sda1' | awk '{print $5}' > sda1_usage.txt

Смысл команды:

  1. Отобразить объём занятого дискового пространства по файловым системам.
  2. Найти строку с фрагментом '/dev/sda1'.
  3. Вырезать из неё пятый столбец — Use% (Занятое пространство в %).
  4. Записать содержимое столбца Use% в файл sda1_usage.txt.

Опция pipefail

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

Назначение следующей команды — найти в файле /var/log/nginx/error.log слово error и отобразить только 3 и 5 столбцы в найденных строках:

grep error /var/log/nginx/error.log | awk '{print $3, $5}' 

Выводимый результат:

grep: /var/log/nginx/error.log: No such file or directory

Команда grep выполнена с ошибкой — файл с указанным именем не найден (лог ошибок веб-сервера NGINX по умолчанию называется error_log). На выход этой команды и на вход awk передаётся пустая строка. 

Тем не менее, команда awk принимает эту строку как валидный ввод и возвращает код возврата 0:

echo $? # Показать код возврата команды
0

Опция pipefail, включённая перед запуском конвейера, изменяет это поведение:

set -o pipefail
grep error /var/log/nginx/error.log | awk '{print $3, $5}'

Тогда, если в цепочке с конвейерами завершится ошибкой не последняя команда — в данном случае grep — код возврата будет ненулевым:

echo $?
2

Код возврата 2 для команды grep означает, что файл отсутствует или нет прав на его чтение. (Ошибка 1 означает, что указанную последовательность символов не удалось найти.)

Опция pipefail особенно полезна в скриптах и длинных цепочках команд. Вместе с функцией set -e она позволяет прерывать выполнение скрипта сразу после возникновения ошибки в одной из команд конвейера.

Заключение

В этой статье мы рассмотрели дополнительные способы передавать данные между командами — конвейер и here-документы, а также узнали, как переключаться между заданиями в оболочке bash. Используя эти приёмы, вы можете упростить передачу и обработку входных и выходных данных между программами и ускорить выполнение задач.

Этот материал был полезен?

Скидка 25% новым клиентам!
Закажи сервер сегодня и получи скидку на первый месяц аренды!