bashのヒアドキュメント(here document)の使い方|設定ファイル生成・コマンド入力・インデントの実践例

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, シェルスクリプト > bashのヒアドキュメント(here document)の使い方|設定ファイル生成・コマンド入力・インデントの実践例
「設定ファイルをcatで上書きしたいけど、複数行の文字列をどう扱えばいいんだろう」
「スクリプトの中でコマンドに複数行の入力を渡したい」

こうした場面で使うのがbashのヒアドキュメント(here document)です。
echo を何十行も並べる必要はありません。<< 演算子を使えば、複数行のテキストをそのまま扱えます。

この記事では、ヒアドキュメントの基本構文から、設定ファイルの生成・シェルスクリプト内でのコマンド入力・インデント制御まで、現場で即使える実践的な使い方を解説します。RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済みです。

この記事のポイント

<<EOF で複数行テキストをそのままコマンドに渡せる
<<'EOF'(シングルクォート)で変数展開を抑止できる
<<-EOF でインデントのタブを自動除去できる
・設定ファイル生成・mysql入力・ssh越し実行の3パターンが定番


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

ヒアドキュメントとは何か

ヒアドキュメント(here document)は、シェルスクリプトで複数行のテキストをリテラルとして扱う構文です。
通常のリダイレクト >< と同様に、コマンドへの入力として機能します。

基本構文は次のとおりです。

コマンド <<EOF 1行目のテキスト 2行目のテキスト $変数名は展開される EOF

ポイントは2点です。
・終端文字列(ここでは EOF)はどの文字列でも構わない。ENDTEXTSCRIPT なども使われる
・終端文字列の行は行頭に書く(スペースやタブがあると終端と認識されない)

「ヒアドキュメント」という名前は「ここにドキュメントがある(here is the document)」という意味から来ています。

基本的な使い方

1. cat へ渡して画面表示する

最もシンプルな使い方が、cat への入力です。

cat <<EOF Hello, Linux! Today is $(date +%Y-%m-%d) EOF

実行結果:

Hello, Linux! Today is 2026-05-27

$(date +%Y-%m-%d) はコマンド置換として実行されます。変数・コマンド置換が有効なのがデフォルトのヒアドキュメントの特徴です。

2. ファイルへリダイレクトして設定ファイルを生成する

スクリプトで設定ファイルを動的に生成するのが、実務で最も多い使い方です。

#!/bin/bash SERVER_IP="192.168.1.100" ADMIN_EMAIL="admin@example.com" cat > /etc/myapp/myapp.conf <<EOF # myapp 設定ファイル(スクリプト自動生成) server_ip=${SERVER_IP} admin_email=${ADMIN_EMAIL} log_level=info EOF

cat > ファイル名 <<EOF の形にすることで、変数を展開しながらファイルを上書きします。
>> に変えれば追記になります。

3. 変数展開を抑止する(シングルクォート形式)

終端文字列をシングルクォートで囲むと、変数展開・コマンド置換が一切行われません。
PHPやbashのスクリプトファイル自体をテンプレートから生成するときに必須の書き方です。

cat > /tmp/check.sh <<'EOF' #!/bin/bash echo "現在のユーザー: $USER" echo "ホスト名: $(hostname)" EOF

実行結果(/tmp/check.sh の内容):

#!/bin/bash echo "現在のユーザー: $USER" echo "ホスト名: $(hostname)"

$USER$(hostname) がそのまま文字列として書き出されています。
通常形式との使い分けを間違えると、スクリプトに意図しない展開結果が埋め込まれるので注意してください。

インデント制御(<<-EOF)

1. タブ除去オプションを使う

シェルスクリプトを関数の中で書くとき、ヒアドキュメント内のテキストがインデントできず見た目が崩れることがあります。
<<-(ハイフン付き)を使うと、各行の先頭にあるタブ文字が自動的に除去されます。

#!/bin/bash create_config() { cat > /etc/myapp.conf <<-EOF # タブでインデントしている server=localhost port=8080 EOF } create_config

上の例では行頭のタブ文字が除去されます。スペースは除去されないことに注意してください。
エディタで自動的にスペースに変換する設定になっている場合は <<- が機能しません。インデント文字が本当にタブかどうかを確認してから使いましょう。

2. インデント除去を使わない場合の代替策

スペースインデントの環境では <<- が使えません。その場合は終端文字列を関数外に追い出すか、sed でインデントを除去するのが現場の定石です。

# sedでスペースインデントを除去する例 cat <<EOF | sed 's/^ //' server=localhost port=8080 EOF

応用・実務Tips

1. mysqlコマンドへ複数行のSQLを渡す

データベース管理でよく使うパターンです。

mysql -u root -p"${DB_PASS}" "${DB_NAME}" <<EOF CREATE TABLE IF NOT EXISTS users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(200) NOT NULL UNIQUE ); INSERT INTO users (name, email) VALUES ('admin', 'admin@example.com'); SHOW TABLES; EOF

mysql コマンドは標準入力をSQLとして実行します。スクリプト内でSQLを1行ずつ echo するよりはるかに可読性が高くなります。

2. ssh越しにリモートで複数コマンドを実行する

sshのリモートコマンド実行にヒアドキュメントを組み合わせると、複数コマンドをまとめて送れます。

ssh user@192.168.1.10 <<'EOF' echo "=== ディスク使用量 ===" df -h echo "=== メモリ使用量 ===" free -m echo "=== 直近のログ ===" journalctl -n 20 --no-pager EOF

シングルクォート <<'EOF' にしているので、変数はリモート側のシェルで展開されます。ローカルの変数を渡したい場合はダブルクォートなし(通常形式)にします。

3. sudo teeで権限の高いファイルを書く

root権限が必要なファイルを書き換えるときは、sudo tee と組み合わせます。
sudo cat > ... では cat が root でもリダイレクトはユーザー権限で処理されるため書き込めません。

# NG: リダイレクト先がroot権限で保護されている場合は失敗する # sudo cat > /etc/sysctl.d/99-custom.conf << EOF # OK: sudo teeを使う cat <<EOF | sudo tee /etc/sysctl.d/99-custom.conf > /dev/null # カスタムカーネルパラメータ net.core.somaxconn = 65535 vm.swappiness = 10 EOF # 設定を即時反映する sudo sysctl --system

実際のサーバーでの実行結果:

* Applying /usr/lib/sysctl.d/00-system.conf ... * Applying /etc/sysctl.d/99-custom.conf ... net.core.somaxconn = 65535 vm.swappiness = 10

4. Pythonなど他言語スクリプトをbashから生成・実行する

インフラ整備スクリプトで、一時的なPythonコードをbashから生成して実行するパターンです。

#!/bin/bash TARGET_DIR="/var/log/myapp" python3 <<EOF import os import glob files = glob.glob('${TARGET_DIR}/*.log') print(f"ログファイル数: {len(files)}") for f in sorted(files): size = os.path.getsize(f) print(f" {f}: {size:,} bytes") EOF

${TARGET_DIR} はbash側で展開され、Pythonコードに埋め込まれます。
本番環境でよく使う手法ですが、可読性が下がるため、コードが長くなるなら独立したPythonファイルに切り出す方が保守しやすいです。

トラブルシュート・エラー対処

1. 終端文字列が認識されない(heredoc never closes)

症状:スクリプトを実行しても終わらない、または「unexpected EOF」エラーが出る。
原因:終端文字列(EOF)の行にスペースやタブが入っている。

# NG: EOFの前にスペースが入っている(<<- を使わない場合) cat <<EOF テキスト EOF ← これは終端と認識されない! # OK: EOFは必ず行頭から cat <<EOF テキスト EOF

<<- を使う場合はタブのみ除去されます。スペースが混在していると依然として終端と認識されません。

2. 変数が展開されてしまう・されない

展開させたくないのに展開される:終端文字列をシングルクォートで囲む。
展開させたいのに展開されない:シングルクォートを外す。

# 変数を展開する(デフォルト) cat <<EOF ユーザー: $USER EOF # 変数を展開しない(ファイル生成時に使う) cat <<'EOF' ユーザー: $USER EOF

3. sudo teeで書いても内容が空になる

症状sudo tee でファイルを書いたがファイルが空になる。
原因tee の前に /dev/null へのリダイレクトを付け忘れ、tee が標準出力に出力してしまい、それが別のリダイレクトに使われている。
対処| sudo tee ファイル名 > /dev/null の形にして tee の標準出力を捨てる。

4. シェルスクリプトでset -eと組み合わせると途中終了する

set -e 環境でヒアドキュメント内のコマンドが失敗すると、スクリプト全体が終了します。
エラーが起きうる箇所は || true ではなく if 文で処理するか、その箇所だけ set +e で一時解除してください。

set -e # 失敗しても継続したい場合は set +e / set -e で挟む set +e mysql -u root -p"${DB_PASS}" "${DB_NAME}" <<EOF DROP TABLE IF EXISTS tmp_work; EOF set -e

本記事のまとめ

やりたいこと 構文
複数行テキストをコマンドへ渡す(変数展開あり) コマンド <<EOF ... EOF
変数展開を抑止してファイルへ書き出す cat > ファイル <<'EOF' ... EOF
行頭のタブを除去してインデントを整える コマンド <<-EOF ... EOF
root権限ファイルへ書き込む cat <<EOF | sudo tee ファイル > /dev/null
ssh越しに複数コマンドを実行する ssh user@host <<'EOF' ... EOF
mysqlへ複数行SQLを渡す mysql -u root -p ... <<EOF ... EOF
ヒアドキュメントは「書き方を覚えると、すぐにスクリプトの品質が上がる」代表的な構文のひとつです。
設定ファイル生成・データベース操作・リモート実行のどれにも使えるので、まず cat > ファイル <<EOF の形から試してみてください。

bashのシェルスクリプトをもっと深く学びたい方は、set -xコマンドでシェルスクリプトをデバッグする方法getoptsコマンドでbashスクリプトの引数を処理する方法もあわせてご覧ください。
また、コマンドの実行結果をファイルと画面に同時に残したい場面ではteeコマンドで標準出力とファイルに同時出力する方法が役立ちます。
シェルスクリプトのエラー処理を体系的に学ぶならtrapコマンドでbashスクリプトのシグナルを捕捉・処理する方法もあわせてどうぞ。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、
Linux Master Pro Seminar(2日間ハンズオン)では bashスクリプト・設定ファイル管理・サーバー自動化まで、
実際のサーバーを触りながら実務レベルのシェルスクリプト技術を習得できます。

>> セミナー詳細・お申込みはこちら

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。