Here documents в Bash: полное руководство и шаблоны
TL;DR
Here documents (heredoc) — это удобный механизм перенаправления многострочного ввода в команды и функции в Bash. Они незаменимы для автоматизации ввода команд на удалённой машине через SSH, генерации файлов и составления писем; при этом важно понимать правила кавычек и экранирования, чтобы контролировать расширение переменных и сохранность табуляции.
Быстрые ссылки
- Here Documents
- Основные принципы Here Documents
- Простые примеры
- Обработка символов табуляции
- Перенаправление в файл
- Передача вывода другой команде (pipe)
- Передача параметров в функцию
- Создание и отправка письма
- Использование с SSH
- Странное имя, полезные особенности

Here documents — это синтаксическая конструкция оболочки, позволяющая передавать многострочный текст через стандартный ввод (stdin) любой команде, которая ожидает ввод. В самых простых случаях это альтернатива echo с множеством строк или созданию временных файлов.
Ключевые моменты в одном предложении:
- Here document начинается с строки вида: COMMAND << limit_string и заканчивается строкой, содержащей только limit_string.
В одном абзаце, простыми словами: heredoc собирает все строки между начальным маркером и конечным маркером и подаёт их команде как её stdin.
Основные принципы Here Documents
Идиоматическое представление heredoc выглядит так:
COMMAND << limit_string
.
.
text
data
variables
.
.
limit_stringКомпоненты:
- COMMAND: любая команда Linux, принимающая вход через stdin (cat, sed, mail, ssh, собственные функции и т.д.). echo не принимает перенаправлённый stdin.
- << : оператор перенаправления here document.
- limit_string: метка, любая строка без пробелов (часто используют EOF, но лучше назвать меткой по смыслу, например _remote_commands).
- Data List: список строк, который будет поступать в stdin команды до встречи со строкой limit_string.
Советы по читаемости:
- Используйте осмысленные limit_string вместо EOF: _backup_script, _remote_commands, _config_block.
- Если в блоке не должны расширяться переменные и выполняться подстановки команд, обрамите limit_string одинарными кавычками: <<’EOF’ или <<’ _EOF’.
Важно: если вы используете кавычки вокруг limit_string (например, “_end_of_text”), содержимое передаётся дословно, без расширения переменных и без подстановки команд.
Примеры и пояснения
Ниже несколько практических примеров — они повторяют базовую демонстрацию и расширяются пояснениями.
Простой пример в командной строке
Если ввести в терминале:
cat << _end_of_text и затем строки:
How-To Geek
Review Geek
LifeSavvy
CloudSavvy IT
MindBounce
_end_of_textто вы увидите, что ничего не было отправлено команде cat до тех пор, пока не встретился маркер _end_of_text. Это демонстрирует, что heredoc собирает ввод целиком и потом подаёт его команде.

И окончательный вывод появится только после закрытия блока:

Пример в скрипте с расширением переменных и подстановкой команд
Скрипт 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 +x heredoc-1.shи запустите:
./heredoc-1.shЗдесь подстановка $(whoami) и расширение $PWD и $BASH_VERSION произойдут до передачи текста в cat. Если вы хотите избежать расширения (показать сами имена переменных), обрамите метку кавычками:
cat <<- "_end_of_text"
...
_end_of_textВ этом случае текст будет передан дословно — переменные не развернутся, подстановок команд не произойдёт.
Обработка символов табуляции
По умолчанию табуляция из heredoc сохраняется. Если heredoc находится внутри отступа (например, внутри блока if или функции), можно использовать <<- (с дефисом) — тогда ведущие символы табуляции будут удалены, но только табуляции (не пробелы).
Пример:
#!/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, в файл — добавив > или >> после первой строки.
Пример 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 создаст или перезапишет session.txt.
Передача вывода другой команде (pipe)
Выходной поток команды, принимающей heredoc, можно передать по каналу в другую команду с помощью |
Пример heredoc-5.sh (замена a на e через sed):
#!/bin/bash
cat << _end_of_text | sed 's/a/e/g'
How
To
Gaak
_end_of_textРезультат: Gaak превращается в Geek.
Передача параметров в функцию
Командой при heredoc может быть функция в вашем скрипте. Функция может читать из stdin с помощью read или циклов.
Пример 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.

Создание и отправка письма
Heredoc часто используют для составления многострочных тел писем в локальных MTA (mailx, mail и т.д.). Пример heredoc-7.sh, который использует local mail:
#!/bin/bash
article="Here Documents"
mail -s 'Workload status' dave << _project_report
User name: $(whoami)
Has completed assignment:
Article: $article
_project_reportПосле запуска письмо появится в локальном почтовом ящике пользователя dave.

Использование с SSH
Одно из самых полезных применений heredoc — передача команд в удалённую оболочку по SSH. Если настроены SSH-ключи, процесс может быть полностью автоматизирован.
Пример heredoc-8.sh — подключение к remote-pc и добавление записи в лог на удалённой машине:
#!/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 с SSH:
- Используйте ssh -T, если не нужен псевдотерминал (тогда удалённая оболочка не будет запускать интерактивные настройки).
- Если внутри heredoc вы используете локальные переменные, подумайте, хотите ли вы, чтобы они развернулись локально до отправки (без кавычек) или чтобы их было видно на удалённой стороне (используйте скобочки и экранирование по необходимости).
- Для защиты секретов лучше не вставлять пароли прямо в heredoc, а использовать ssh-ключи или агенты.
После запуска вы сможете убедиться, что на удалённой машине появилась запись в /home/dave/conn_log/script.log.


Когда heredoc не лучший инструмент (краткие контрпримеры)
- Большие двоичные данные: heredoc передаёт текстовую информацию; для двоичных данных лучше использовать rsync, scp или tar по каналу.
- Чувствительные секреты: не вставляйте пароли и приватные ключи напрямую в heredoc в общедоступных скриптах.
- Очень длинные или часто меняющиеся скрипты удалённого выполнения: лучше поддерживать скрипт на удалённой машине и вызывать его по SSH, чем генерировать огромный heredoc каждый раз.
- Когда требуется интерактивность: некоторые задачи лучше выполнять в интерактивной сессии (tty); использование heredoc с ssh -T отключает псевдотерминал.
Альтернативные подходы
- Here-strings (<<<): для передачи одной короткой строки удобно использовать:
tr 'a' 'e' <<< "Gaak"- Process substitution (<(command)): полезно, когда программа ожидает файл, а вы хотите предоставить вывод команды:
diff <(sort file1) <(sort file2)- Использование временных файлов через mktemp и запись в них перед передачей на удалённую машину.
- Инструменты автоматизации: ansible, fabric, pssh — если нужно управлять множеством хостов и сложной логикой.
- Expect: для сценариев, требующих автоматического ввода паролей или ответов на интерактивные подсказки.
Методология: как выбрать формат heredoc для задачи
- Определите, нужны ли расширения переменных и подстановки команд на локальной стороне.
- Если нет — используйте <<’EOF’ (одинарные кавычки) или заключите limit_string в одинарные кавычки.
- Если heredoc находится внутри отступа и вы хотите убрать ведущие табуляции — используйте <<-EOF.
- Подумайте о безопасности: не вставляйте явные пароли/ключи.
- При работе через SSH тестируйте сначала в режиме echo/логирования, затем применяйте в production.
Cheatsheet: шаблоны и полезные сниппеты
- Дословный heredoc (переменные не разворачиваются):
cat <<'DOC'
This will show $HOME and $(whoami) literally.
DOC- Heredoc с удалением ведущих табуляций:
cat <<-EOF
indented line
EOF- Heredoc, отправляемый по SSH (локальные переменные разворачиваются перед отправкой):
ssh user@host << _CMDS
mkdir -p /tmp/some_dir
cat > /tmp/some_dir/config << CONFIG
key=value
CONFIG
_CMDS- Запись в файл с перезаписью/добавлением:
cat << EOF > /tmp/out.txt
line1
line2
EOF
cat << EOF >> /tmp/out.txt
more lines
EOF- Использование heredoc для создания here-скрипта на удалённой машине:
ssh user@host 'bash -s' <<'REMOTE'
#!/bin/bash
# remote script body
uname -a
REMOTE- Передача JSON в команду, которая ожидает stdin:
jq . <Проверочные сценарии и критерии приёмки
- Скрипт, использующий heredoc, должен корректно работать при запуске под тем же пользователем и в той же среде.
- Переменные разворачиваются только если маркер не заключён в одинарные кавычки.
- При использовании <<- ведущие табуляции должны удаляться, пробелы — сохраняться.
- При отправке через ssh проверяйте наличие записи/файла на удалённой машине.
Роль-based чек-листы
Для администратора (Sysadmin):
- Используйте SSH-ключи, не храните пароли в коде.
- Логируйте изменения и проверяйте журналы на удалённой машине.
Для разработчика (Dev):
- Выбирайте читаемые limit_string и документируйте ожидания по вводу.
- Покройте тестами сценарии, где heredoc используется для передачи параметров в функции.
Для SRE/операций:
- Проверяйте поведение в условиях ошибок сети; добавьте таймауты и ретраи.
- Не используйте heredoc для огромных данных; используйте rsync/scp.
Безопасность и приватность
- Никогда не вставляйте секреты в публично доступные скрипты или репозитории.
- Для секретов предпочитайте SSH-агент, менеджеры секретов (vault) или env-переменные, переданные через безопасные каналы.
- Если heredoc создаёт временные файлы, применяйте mktemp и устанавливайте строгие права на файлы (chmod 600).
- При работе с удалённой стороной не отключайте проверки host key (не используйте -o StrictHostKeyChecking=no в production без серьёзных причин).
Maturity levels — когда heredoc подходит и когда нет
- Уровень 1 (прототип): простой heredoc для быстрой отладки и одноразовых операций.
- Уровень 2 (скрипты): стабильное использование heredoc в поддерживаемых скриптах с учётом кавычек и безопасности.
- Уровень 3 (автоматизация): для масштабных деплоев используйте специализированные инструменты (ansible, fabric) вместо большого количества heredoc в одиночных скриптах.
Небольшой плейбук: проверка удалённого дискового пространства и уведомление
Задача: подключиться к remote-pc, проверить свободное место и при нехватке — отправить письмо.
Примерный шаблон:
#!/bin/bash
THRESHOLD=10 # percent free space threshold
ssh -T dave@remote-pc.local << _CHECK
FREE=
free_pct=$(df -h / | awk 'NR==2{print $5}' | tr -d '%')
if [ "$free_pct" -lt $THRESHOLD ]; then
mail -s 'Low disk space' dave <(В реальном плейбуке вынесите порог и адреса в переменные окружения и используйте ключи SSH.)
Частые ошибки и отладка
- Ошибка: “command not found” внутри heredoc на удалённой машине — проверьте PATH и окружение на той машине.
- Переменные не разворачиваются — убедитесь, что метка heredoc не заключена в одинарные кавычки.
- Неправильно удаляются табуляции — <<- удаляет только символы табуляции, не пробелы.
- Проблемы с кодировкой — убедитесь, что оба хоста используют совместимую кодировку, чаще всего UTF-8.
Заключение
Here documents — простой и гибкий инструмент для передачи многострочного ввода в команды, функции и удалённые оболочки. Правильное использование кавычек, понимание различий между <<, <<- и <<’EOF’, а также осторожное обращение с секретами и большими объёмами данных делают heredoc безопасным и удобным способом автоматизации.
Важно: heredoc — это инструмент; выбирайте его тогда, когда он действительно упрощает задачу: для небольших, управляемых и читаемых блоков ввода. Для более сложных сценариев используйте более подходящие средства автоматизации.
Краткое резюме
- Here documents позволяют передавать многострочный stdin в команды и функции.
- Используйте <<’EOF’ для дословного текста, <<-EOF для удаления ведущих табуляций.
- Для SSH-автоматизации heredoc удобен, но не стоит помещать в него секреты.