mkfifoコマンドで名前付きパイプを作成する方法|プロセス間通信とパイプの実践例

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, シェルスクリプト > mkfifoコマンドで名前付きパイプを作成する方法|プロセス間通信とパイプの実践例
「コマンド同士でデータをやりとりしたいけど、パイプだと一方向にしか流せない」「シェルスクリプトで2つのプロセスを協調動作させたいのに、うまくつなぐ方法が分からない」

こういった場面で役立つのが、名前付きパイプ(FIFO)です。通常のパイプ(|)は2つのコマンドを直結するだけですが、名前付きパイプはファイルシステム上にパイプを「実体化」します。異なるシェルや無関係なプロセス同士でも、ファイル名を通じてデータをやりとりできる点が大きな違いです。

この記事では、mkfifoコマンドの使い方を基礎から解説します。名前付きパイプの仕組みと通常のパイプとの違い、実際の作成手順、プロセス間通信への応用例、そしてよくある落とし穴まで、実機での動作確認をまじえて説明します。

この記事のポイント

・mkfifo コマンドでFIFO特殊ファイル(名前付きパイプ)を作成できる
・名前付きパイプは異なるシェル・プロセス間でデータを受け渡す手段になる
・FIFOへの書き込みは読み手がいるまでブロックされる特性がある
・rm で削除するまでファイルシステム上に残り続ける点が通常パイプと異なる


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

名前付きパイプ(FIFO)とは何か

Linuxには2種類のパイプがあります。

無名パイプ(anonymous pipe):コマンドラインで | を使って2つのコマンドを直結するもの
名前付きパイプ(named pipe / FIFO):ファイルシステム上に特殊ファイルとして存在し、名前を通じて複数のプロセスが読み書きできるもの

FIFOは「First In, First Out」の略で、先に書き込まれたデータが先に読み出される順序を意味します。ls -l で確認すると、ファイル種別が p(pipe)と表示されます。

1. 通常パイプとの違い

通常のパイプ(|)は、左のコマンドの標準出力を右のコマンドの標準入力に直結します。生存期間はコマンドが動いている間だけです。

# 通常パイプ: cmd1 と cmd2 が同じコマンドラインに存在しないと使えない ls /var/log | grep "\.log$" | head -5

名前付きパイプの場合は、読み手と書き手が別々のシェルで動いていても構いません。

項目 通常パイプ(|) 名前付きパイプ(FIFO) ファイルシステムへの実体 なし(カーネル内部のみ) あり(p属性の特殊ファイル) 利用できるプロセス 同一コマンドライン上の親子プロセス 任意の無関係なプロセス 生存期間 コマンド実行中のみ 明示的に削除するまで残る 作成方法 シェル構文(|) mkfifo コマンド

2. FIFOのブロッキング特性

名前付きパイプには、理解しておくべき重要な特性があります。書き手がFIFOに書き込もうとすると、読み手が現れるまでブロック(一時停止)されます。逆に、読み手がFIFOを開こうとしても、書き手が現れるまでブロックされます。

これはカーネルレベルの仕様で、FIFOがデータを永続化しない(一時的なデータ転送路にすぎない)ことに由来します。この動作を前提にスクリプトを組まないと、プロセスがハング(応答なし)する原因になります。

mkfifoコマンドの基本的な使い方

1. 構文とオプション

# 基本構文 mkfifo [オプション] FIFO名 # 主なオプション # -m モード : 作成するFIFOのパーミッションを指定(例: -m 644)

オプションなしで実行すると、デフォルトのパーミッション(umask適用後、通常 0644)でFIFOが作成されます。

2. FIFOを作成して確認する

# /tmp 以下に名前付きパイプを作成 $ mkfifo /tmp/mypipe # ls -l でファイル種別を確認(先頭が "p" になる) $ ls -l /tmp/mypipe prw-r--r--. 1 ec2-user ec2-user 0 6月 20 10:00 /tmp/mypipe # file コマンドで種別を確認 $ file /tmp/mypipe /tmp/mypipe: fifo (named pipe)

ls -l の先頭文字が p になっていれば、名前付きパイプとして正しく作成されています。サイズは常に 0 と表示されます。これはデータを蓄積するファイルではなくデータ転送路だからです。

3. パーミッションを指定して作成する

# 所有者のみ読み書き可能な FIFO を作成 $ mkfifo -m 600 /tmp/private_pipe $ ls -l /tmp/private_pipe prw-------. 1 ec2-user ec2-user 0 6月 20 10:02 /tmp/private_pipe

複数ユーザーが存在するサーバーで特定のプロセス間だけにデータをやりとりさせたい場合は、-m 600-m 660 で制限します。

名前付きパイプを使ったプロセス間通信の実践例

1. 基本動作の確認(2つのターミナルで試す)

まず、最もシンプルな動作確認から始めます。2つのターミナルを開いて試してください。

ターミナルA(読み手):

# FIFOを作成して、読み出し待ちにする $ mkfifo /tmp/mypipe $ cat /tmp/mypipe # ← ここでブロックされる(書き手が来るまで待つ)

ターミナルB(書き手):

# 別のターミナルから FIFO に書き込む $ echo "hello from terminalB" > /tmp/mypipe

ターミナルBで書き込んだ瞬間に、ターミナルAの cat が受け取って表示します。

# ターミナルAの出力 hello from terminalB $

2. シェルスクリプトでのバックグラウンド活用

実際のスクリプトでは、読み手をバックグラウンドで起動してからFIFOに書き込む流れが一般的です。

#!/bin/bash FIFO=/tmp/work_pipe mkfifo "$FIFO" # 読み手をバックグラウンドで起動 while IFS= read -r line; do echo "受信: $line" done < "$FIFO" & READER_PID=$! # 書き手として複数行を送る for i in 1 2 3; do echo "メッセージ $i" > "$FIFO" done wait "$READER_PID" rm -f "$FIFO" echo "完了"

# 実行結果 受信: メッセージ 1 受信: メッセージ 2 受信: メッセージ 3 完了

ポイントは「読み手をバックグラウンド(&)で起動してからFIFOに書き込む」順序です。逆にすると書き手がブロックされてデッドロック状態になります。

3. ログをリアルタイムで複数プロセスに配信する

tee と組み合わせると、1つのデータストリームを複数の処理に分岐できます。

# 2つの FIFO を作成 mkfifo /tmp/pipe_a /tmp/pipe_b # 処理A: エラー行だけ抽出して記録 grep "ERROR" < /tmp/pipe_a > /var/log/myapp_errors.log & # 処理B: 行数をカウント wc -l < /tmp/pipe_b > /tmp/line_count.txt & # アプリのログを両方に送る tail -f /var/log/myapp.log | tee /tmp/pipe_a /tmp/pipe_b > /dev/null # 後片付け rm -f /tmp/pipe_a /tmp/pipe_b

tee は標準入力を複数の出力先に同時に流せます。tee ファイルA ファイルB のように書くと、FIFOを「中継ステーション」として複数のフィルタ処理を並列に動かせます。

4. 進捗通知に使う(長時間バッチとの連携)

長時間かかるバッチ処理の進捗を、別のシェルから監視する用途にも使えます。

#!/bin/bash PROGRESS_PIPE=/tmp/progress mkfifo "$PROGRESS_PIPE" # 監視プロセス(進捗表示)をバックグラウンドで起動 while IFS= read -r msg; do echo "[$(date +%H:%M:%S)] $msg" done < "$PROGRESS_PIPE" & MONITOR_PID=$! # 実際のバッチ処理 for step in "DB接続確認" "データ取得中" "集計処理中" "レポート出力中"; do sleep 1 # 処理の代わり echo "$step" > "$PROGRESS_PIPE" done echo "完了" > "$PROGRESS_PIPE" wait "$MONITOR_PID" rm -f "$PROGRESS_PIPE"

# 実行結果 [10:05:01] DB接続確認 [10:05:02] データ取得中 [10:05:03] 集計処理中 [10:05:04] レポート出力中 [10:05:05] 完了

トラブルシュート・よくあるエラー

1. プロセスがハング(ブロックされたまま止まる)

症状:FIFOに書き込もうとしたら、コマンドが返ってこない。

原因:読み手プロセスが存在しないか、FIFOを開いていない。

# 読み手なしで書こうとするとブロックされる $ echo "test" > /tmp/mypipe # ← ここで止まる # 別ターミナルで確認 $ ps aux | grep "echo test" ec2-user 1234 0.0 0.0 ... T pts/1 0:00 bash -c echo test > /tmp/mypipe # 解除: 別ターミナルで読み手を起動するか、Ctrl+C で中断

対処:
・必ず「読み手を先に起動」してから書き手を動かす順序を守る
O_NONBLOCK フラグで開く(Cプログラムの場合)か、バックグラウンドに逃がす

2. FIFOへの書き込みが「Broken pipe」で失敗する

症状:echo: write error: Broken pipe と表示される。

原因:読み手が先に終了して、FIFOの読み込み側が閉じられた状態で書き込もうとした。

# 対策: 書き手と読み手の終了タイミングを合わせる # 読み手がループで待ち続けるよう設計するか # 書き手が終了したら読み手も終了するよう制御する

3. 既に同名のFIFOが存在してエラーになる

$ mkfifo /tmp/mypipe mkfifo: '/tmp/mypipe' を作成できません: ファイルが存在します # 解決策: 事前に削除または mktemp で一意な名前を使う $ rm -f /tmp/mypipe && mkfifo /tmp/mypipe # または mktemp で一時FIFOを安全に作成 $ TMPFIFO=$(mktemp -u) # -u は実際に作成しない(ファイル名取得のみ) $ mkfifo "$TMPFIFO"

4. スクリプト終了時にFIFOが残る

スクリプトが異常終了するとFIFOが削除されずに残ります。trap を使って確実に後片付けしましょう。

#!/bin/bash FIFO=/tmp/cleanup_test mkfifo "$FIFO" # スクリプト終了時(正常・異常問わず)にFIFOを削除 trap "rm -f '$FIFO'" EXIT # ここでエラーが起きても FIFO は削除される some_command_that_may_fail

trap ... EXIT を使うことで、Ctrl+C や予期しないエラー終了でもFIFOが確実に消えます。

本記事のまとめ

やりたいこと コマンド
名前付きパイプを作成する mkfifo /tmp/mypipe
パーミッションを指定して作成する mkfifo -m 600 /tmp/mypipe
FIFOの種別を確認する ls -l /tmp/mypipe(先頭が p)
FIFOを削除する rm -f /tmp/mypipe
1つのストリームを複数処理に分岐する tee /tmp/pipe_a /tmp/pipe_b > /dev/null
終了時にFIFOを自動削除する trap "rm -f '$FIFO'" EXIT

名前付きパイプは、異なるシェルやプロセス間でデータを受け渡す場面で真価を発揮します。通常のパイプでは実現できない「書き手と読み手の分離」ができるため、複雑なデータフロー設計やバッチ処理の進捗監視に活用できます。

注意点はブロッキング動作です。書き手と読み手の起動順序を意識し、trap による後片付けをセットにする習慣をつけておくと、予期せぬハングやFIFOの残留を防げます。

シェルスクリプトでプロセス間通信が必要になった時の選択肢として、ぜひ手元で動かして試してみてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Linux無料マニュアルを受け取る >>

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

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

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

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

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

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

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

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

この記事を書いた人

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

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

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