bashやzsh、tcshなどの高機能シェルには、いろいろと便利な機能がある。独自の拡張機能には互換性の問題もあるが、個人的には作業の効率化のため、必要なものはうまく使う方がいいと思っている。
個人的に良く使うbashの機能でプロセス置換(Process Substitution)がある。下記の記事でも紹介している。
ざっくり言うと、プロセスの実行結果を入出力ファイルとして扱うことが出来る機能。
プロセス置換の例
プロセス置換の基本
例えば下記の例。lsコマンドの出力が、catコマンドの入力ファイルとして結びついている。
$ cat <(ls) Documents KBASIC1_TRYDATA.tar.gz TRY_DATA TUKUBAI-TUTORIAL bin temp work
プロセス置換の利点は、通常はファイルしか入力出来ないような場合でも、コマンドの実行結果を直接入力に出来ること。またパイプの途中で他のコマンドの乱入や乱出が出来ること。
diffでプロセス置換
私がよく使うのが、2つのコマンドの実行結果の差分をdiffで確認する時。通常だとコマンドの結果をファイルに保存する必要があるが、プロセス置換を使うと不要になる。
$ diff <(ls) <(ls -a) 0a1,14 > . > .. > .Xauthority > .bash_history > .bash_profile > .bashrc > .history > .lesshst > .login > .login_conf > .ssh > .vim > .viminfo > .vimrc
リモートシェル芸の合わせ技
また、下記のようにsshをリモートシェルとして使い、2つのサーバでのコマンド実行結果の差分を確認するのに使っている。
$ diff <(ssh remote1 'コマンド') <(ssh remote2 'コマンド')
FreeBSDでの注意点
設定しないとエラー
ということで便利なbashのプロセス置換だが、FreeBSDで使う時にはある設定が必要だ。設定をしないと、下記のようにエラーが出て悲しいことになる。
$ cat <(ls) diff: /dev/fd/63: そのようなファイルまたはディレクトリはありません
fdescをマウント
下記のコマンドを実行する必要がある。このfdescって何なのか?誰か教えてくれ・・・
$ sudo mount -t fdescfs fdesc /dev/fd
実行後は下記のコマンドでfdescfs
の行があることを確認する。
$ mount /dev/ada0p2 on / (ufs, local, journaled soft-updates) devfs on /dev (devfs, local, multilabel) fdescfs on /dev/fd (fdescfs) $ df Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ada0p2 19278684 9034412 8701980 51% / devfs 1 1 0 100% /dev fdescfs 1 1 0 100% /dev/fd
これでbashのプロセス置換を使うことが可能になる。
$ cat <(ls) Documents KBASIC1_TRYDATA.tar.gz TRY_DATA TUKUBAI-TUTORIAL bin temp work
起動時にfdescをマウント
ただし、このままだと再起動すると/dev/fdへのマウントが解除されてしまうので、/etc/fstabにfdescの行を追加しておく。フィールドの区切り文字はタブ文字なのに注意しよう。
$ cat /etc/fstab # Device Mountpoint FStype Options Dump Pass# /dev/ada0p2 / ufs rw 1 1 /dev/ada0p3 none swap sw 0 0 fdesc /dev/fd fdescfs rw 0 0
補足
実はこの設定、パッケージでbashをインストールすると、最後にメッセージが出てきている。bashをパッケージでインストールsudo pkg install bash
した時のスクリーンショットを貼り付けておく。
もしマウントが出来ないぜ!?という方がいらっしゃったら、下記のくんすとさんの記事が参考になるかもしれん。
また@bsdhackさんからリプライがあった。
fdescってのはファイルディスクリプタを仮想デバイスにするためのドライバらしい。/dev/fd/ファイルディスクリプタ番号
というファイルとして仮想的に見せかけるようだ。bashのプロセス置換はfdescを使ってIOを開く実装ということかな?
@papiron fdesc ってFDを仮想デバイスにするためのドライバじゃないでしょうかね? /dev/fd/XX をアクセスした時にプロセス毎のFDをデバイスとして見せてくれるためのドライバ(説明下手ですが
— Mitzyuki IMAIZUMI (@bsdhack) February 26, 2016
fdescfsについてのマニュアルはこちらにあった。