Поиск по сайту:

Как использовать «Здесь документы» в Bash в Linux


Документы со странным названием «здесь» позволяют использовать перенаправление ввода/вывода внутри сценариев Bash в Linux. Это отличный способ автоматизировать выполнение команд на удаленном компьютере.

Здесь Документы

Многие команды в Linux имеют двух- или трехбуквенные имена. Отчасти это порождает мнение, что Linux трудно освоить и что он полон загадочных команд. Но одно из самых странных имен в Linux вовсе не загадочно короткое. «Здесь документы» не являются документами, и не совсем понятно, к чему относится «здесь».

Это относительно непонятная конструкция, но она полезна. Конечно, это Linux, так что есть несколько способов содрать шкуру с кота. Некоторые функциональные возможности, предоставляемые настоящими документами, могут быть воспроизведены другими способами. Эти альтернативные методы обычно более сложны. В программировании и скриптинге «более сложный» также означает «более подверженный ошибкам» и что ваш код сложнее поддерживать.

В чем документы действительно преуспевают, так это в автоматизации команд, которые вы хотите отправить на удаленный компьютер из соединения, установленного из скрипта. Установить соединение несложно, но как только соединение будет установлено, как вы «закачаете» свои команды из сценария в оболочку на удаленном компьютере? Здесь документы позволяют сделать это очень просто.

Основные принципы работы с здесь документами

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

COMMAND << limit_string
 .
 .
text 
data
variables
.
.
limit_string

  • КОМАНДА: это может быть любая команда Linux, которая принимает перенаправленный ввод. Обратите внимание, что команда echo не принимает перенаправленный ввод. Если вам нужно написать на экран, вы можете использовать команду cat, которая делает это.
  • <: оператор перенаправления.
  • limit_string: это ярлык. Это может быть что угодно, если только оно не отображается в списке данных, которые вы перенаправляете в команду. Он используется для обозначения конца списка текста, данных и переменных.
  • Список данных: список данных, которые необходимо передать команде. Он может содержать команды, текст и переменные. Содержимое списка данных передается в команду по одной строке за раз, пока не встретится _limit_string.

Вы, вероятно, увидите примеры документов, которые используют «EOF» в качестве строки ограничения. Мы не одобряем такой подход. Это работает, но «EOF» означает «Конец файла». Помимо редкого случая, когда домашний документ является последним в файле скрипта, «EOF» используется ошибочно.

Это сделает ваши сценарии более читабельными, если вы используете строку ограничения, которая относится к тому, что вы делаете. Если вы отправляете серию команд на удаленный компьютер через Secure Shell (SSH), строка ограничения, называемая чем-то вроде «_remote_commands», будет иметь смысл. Вам не нужно начинать их с символа подчеркивания «_». Мы делаем это, потому что это помечает их как нечто необычное в вашем сценарии.

Простые примеры

Вы можете использовать здесь документы в командной строке и в скриптах. Когда вы вводите следующее в окне терминала, вы будете видеть приглашение продолжения строки «>» каждый раз, когда нажимаете «Enter». Когда вы вводите строку ограничения «_end_of_text» и нажимаете «Enter», список веб-сайтов передается в cat, и они отображаются в окне терминала.

cat << _end_of_text 
How-To Geek 
Review Geek 
LifeSavvy 
CloudSavvy IT
MindBounce
_end_of_text

Это не самое полезное упражнение, но оно показывает, что команде ничего не отправляется до тех пор, пока не будет собран весь список данных и не встретится предельная строка. Команда cat не получает никаких входных данных, пока вы не введете предельную строку «_end_of_text» и не нажмете клавишу «Enter».

Мы можем сделать то же самое в сценарии. Введите или скопируйте этот пример в редактор, сохраните файл как «heredoc-1.sh» и закройте редактор.

#!/bin/bash

cat << "_end_of_text"
Your user name is: $(whoami)
Your current working directory is: $PWD
Your Bash version is: $BASH_VERSION
_end_of_text

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

chmod +x heredoc-1.sh

Этот сценарий содержит две переменные среды: $PWD и $BASH_VERSION. Имена переменных среды заменяются их значениями данных — текущим рабочим каталогом и версией Bash — при выполнении скрипта.

Сценарий также использует подстановку команд в команде whoami. Имя команды заменяется ее собственным выводом. Вывод всего скрипта записывается в окно терминала командой cat. Запускаем скрипт, вызывая его по имени:

./heredoc-1.sh

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

#!/bin/bash

cat <<- "_end_of_text"
Your user name is: $(whoami)
Your current working directory is: $PWD
Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-1.sh

Обработка символов табуляции

По умолчанию символы табуляции в вашем списке данных будут сохранены и записаны в окно терминала. Скопируйте и сохраните этот пример как «heredoc-2.sh». Сделайте его исполняемым с помощью команды chmod. Отредактируйте строки с отступом, чтобы убедиться, что они имеют один или два символа табуляции в начале строки, а не серию пробелов.

#!/bin/bash

cat << _end_of_text
Your user name is: $(whoami)
  Your current working directory is: $PWD
    Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-2.sh

Вкладки записываются в окно терминала.

Если добавить тире «-» к оператору перенаправления, документ здесь будет игнорировать начальные символы табуляции. Сохраните этот пример как «heredoc-3.sh» и сделайте его исполняемым.

#!/bin/bash

cat <<- _end_of_text
Your user name is: $(whoami)
  Your current working directory is: $PWD
    Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-3.sh

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

Циклы и другие логические конструкции обычно имеют отступ. Если ваш здесь документ содержится в разделе сценария с отступом, использование тире «-» с оператором перенаправления устраняет проблемы форматирования, вызванные начальными символами табуляции.

#!/bin/bash

if true; then
  cat <<- _limit_string
  Line 1 with a leading tab.
  Line 2 with a leading tab.
  Line 3 with a leading tab.
  _limit_string
fi

Перенаправление в файл

Вывод команды, используемой с документом здесь, может быть перенаправлен в файл. Используйте операторы перенаправления «>» (создайте файл) или «>>» (создайте файл, если он не существует, добавьте в файл, если он существует). после строки ограничения в первой строке документа здесь.

Этот сценарий называется «heredoc-4.sh». Он перенаправит свой вывод в текстовый файл с именем «session.txt».

#!/bin/bash

cat << _end_of_text > session.txt
Your user name is: $(whoami)
Your current working directory is: $PWD
Your Bash version is: $BASH_VERSION
_end_of_text
./heredoc-4.sh
cat session.text

Передача вывода другой команде

Выходные данные команды, используемой в этом документе, могут быть переданы в качестве входных данных для другой команды. Используйте оператор вертикальной черты | после строки ограничения в первой строке документа здесь. Мы собираемся направить вывод команды here document, cat, в sed. Мы хотим заменить все вхождения буквы «а» на букву «е».

Назовите этот сценарий «heredoc-5.sh».

#!/bin/bash

cat << _end_of_text | sed 's/a/e/g'
How
To
Gaak
_end_of_text
./heredoc-5.sh

«Gaak» исправлен на «Geek».

Отправка параметров в функцию

Команда, которая используется с здесь документом, может быть функцией в скрипте.

Этот скрипт передает некоторые данные о транспортном средстве в функцию. Функция считывает данные так, как если бы они были введены пользователем. Затем распечатываются значения переменных. Сохраните этот скрипт как «heredoc-6.sh».

#!/bin/bash

# the set_car_details() function
set_car_details ()
{
read make
read model
read new_used
read delivery_collect
read location
read price
}

# The here document that passes the data to set_car_details()
set_car_details << _mars_rover_data
NASA
Perseverance Rover
Used
Collect
Mars (long,lat) 77.451865,18.445161
2.2 billion
_mars_rover_data

# Retrieve the vehicle details
echo "Make: $make"
echo "Model: $model"
echo "New or Used: $new_used"
echo "Delivery or Collection: $delivery_collect"
echo "Location: $location"
echo "Price \$: $price"
./heredoc-6.sh

Информация о транспортном средстве записывается в окно терминала.

Создание и отправка электронной почты

Мы можем использовать здесь документ, чтобы составить и отправить электронное письмо. Обратите внимание, что мы можем передавать параметры команде перед оператором перенаправления. Мы используем команду Linux mail, чтобы отправить электронное письмо через локальную почтовую систему на учетную запись пользователя с именем «dave». Опция -s (тема) позволяет указать тему письма.

Этот пример формирует скрипт «heredoc-7.sh».

#!/bin/bash

article="Here Documents"

mail -s 'Workload status' dave << _project_report
User name: $(whoami)
Has completed assignment:
Article: $article
_project_report
./heredoc-7.sh

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

mail

Использование здесь документов с SSH

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

Этот скрипт называется «heredoc-8.sh». Мы собираемся подключиться к удаленному компьютеру под названием «remote-pc». Учетная запись пользователя называется «dave». Мы используем параметр -T (отключить выделение псевдотерминала), потому что нам не нужно назначать интерактивный псевдотерминал.

В разделе сценария «поработайте здесь» мы могли бы передать список команд, и они будут выполняться на удаленном компьютере. Конечно, можно было просто вызвать скрипт, который был на удаленном компьютере. Удаленный сценарий может содержать все команды и подпрограммы, которые вы хотите выполнить.

Все, что будет делать наш скрипт — heredoc-8.sh — это обновить журнал подключений на удаленном компьютере. Учетная запись пользователя и отметка времени и даты записываются в текстовый файл.

#!/bin/bash

ssh -T dave@remote-pc.local << _remote_commands

# do some work in here

# update connection log
echo $USER "-" $(date) >> /home/dave/conn_log/script.log
_remote_commands

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

./heredoc-8.sh

Отобразится некоторая информация об удаленном компьютере, и мы вернемся в командную строку.

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

cat conn_log/script.log

Каждое соединение указано для нас.

Странное имя, аккуратные черты

Здесь документы причудливы, но эффективны, особенно когда они используются для отправки команд на удаленный компьютер. Было бы просто создать скрипт процедуры резервного копирования с помощью rsync. Затем сценарий мог подключиться к удаленному компьютеру, проверить оставшееся место на диске и отправить электронное письмо с предупреждением, если места становится мало.