日々之迷歩

世の中わからんことだらけ

ITが複雑で難しくなっていく様に翻弄される日々です。微力ながら共著させていただいた「シェル・ワンライナー160本ノック」をよろしくお願い申し上げます。

FreeBSDでbashのプロセス置換を使う時の注意点

bashやzsh、tcshなどの高機能シェルには、いろいろと便利な機能がある。独自の拡張機能には互換性の問題もあるが、個人的には作業の効率化のため、必要なものはうまく使う方がいいと思っている。

個人的に良く使うbashの機能でプロセス置換(Process Substitution)がある。下記の記事でも紹介している。

papiro.hatenablog.jp

ざっくり言うと、プロセスの実行結果を入出力ファイルとして扱うことが出来る機能。

プロセス置換の例

プロセス置換の基本

例えば下記の例。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した時のスクリーンショットを貼り付けておく。

f:id:papiro:20160226005737p:plain

もしマウントが出来ないぜ!?という方がいらっしゃったら、下記のくんすとさんの記事が参考になるかもしれん。

kunst1080.hatenablog.com

また@bsdhackさんからリプライがあった。 fdescってのはファイルディスクリプタを仮想デバイスにするためのドライバらしい。/dev/fd/ファイルディスクリプタ番号というファイルとして仮想的に見せかけるようだ。bashのプロセス置換はfdescを使ってIOを開く実装ということかな?

fdescfsについてのマニュアルはこちらにあった。

www.yosbits.com