とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど

開催予定の勉強会

読者登録と各種SNSのフォローもよろしくお願いいたします。

今更だけどpeeコマンドが便利だった話

忙しい人向けのまとめ

pee コマンドは標準出力を複数のコマンドに同時にパイプできるよ!

teeコマンドってあるじゃん?

tee というコマンドがありますよね。標準入力を標準出力と同時に、ファイルに書き出すコマンドです。よく使うのは、コマンドの出力をroot権限でファイルに書き出したい場合でしょう。

例えば、以下のコマンドは「echoの出力を/etc以下に(root権限で)書き込みたい」という時に初心者がやりがちな間違いです。意図はわかるのですが、この場合 echo コマンドが(無意味に)root権限で起動するものの、リダイレクトはシェルを動かしている一般ユーザー権限で実行されるため、無慈悲にもPermission deniedとなります。

$ sudo echo hoge > /etc/fuga

これを意図通りに動かすには、/etc 以下に書き込むプロセスをroot権限で起動する必要があります。そこで登場するのが tee コマンドなわけです。上記の間違いを tee を使って書き直すと以下のようになります。

$ echo hoge | sudo tee /etc/fuga

そして tee コマンドは、標準入力を複数のファイルに同時に書き込むこともできます。以下の例では、/etc/fuga / etc/piyo /etc/foo /etc/bar という四つのファイルに、同じ内容が書き込まれます。

$ echo hoge | sudo tee /etc/{fuga,piyo,foo,bar}

peeはteeのパイプ版

標準入力の内容をファイルに書き出す tee コマンドに対し、パイプに書き出すのが pee コマンドです*1

ここまで聞くと「標準入力をパイプに書き出す? 普通にパイプ繋げばいいじゃん」と思うでしょう。pee コマンドの真価は、tee と同様に、出力先を複数指定できるところにあります。

例えばこんな使い方はどうでしょう。

ps コマンドの出力を grep して、特定のプロセスの情報だけを表示したいことがよくあります。こんな感じですね。

$ ps -fe | grep '[z]sh'
mizuno   1413882 1413881  0 11:11 pts/0    00:00:01 -zsh

はい、複数のカラムに色々な情報が表示されましたが、この数字って何の意味でしたっけ? ps コマンドは一行目にヘッダが表示されるのですが、プロセス名で grep してしまうと、当然ヘッダは表示されません。そこで一行目だけを表示する、head コマンドと同時にパイプしてみましょう。

$ ps -fe | pee "head -n 1" "grep [z]sh"
UID          PID    PPID  C STIME TTY          TIME CMD
mizuno   1413882 1413881  0 11:11 pts/0    00:00:01 -zsh

ps コマンドの出力が、headgrep それぞれにパイプされ、期待した出力を得ることができました。

なに? grep の条件を複数指定してor検索すればいいじゃんって? ぎゃふん

それはさておき、コマンドを直列に繋ぐパイプを並列に分岐させられるのは、色々な使い途がありそうです。ただしそれぞれのコマンドの終了順は保証されていないようなので、そこだけは留意する必要がありそうですね。

ちなみに pee は、Ubuntuでは moreutils パッケージに含まれています。このパッケージには色々と便利なコマンドが含まれているので、興味があったら見てみてください。筆者のお勧めは vidir vipe sponge です。

*1:これは「pipeのtee」の略であり、決しておしっこではないと思います。たぶん。