Unyablog.

のにれんのブログ

Shell の pipe と redirection を実装する

新年なので Shell の pipe と redirection を実装した。

前回の記事はこちら

nonylene.hatenablog.jp

前回実装してみて、さすがに pipe と redirection ぐらいは実装しておいてもいいのでは?と思って実装してみた。

pipe

github.com

パイプについての説明は

パイプでつなぐ - PukiWiki

が分かりやすくて、ここを見ると大体いい感じに実装できた。

一つ困ったのは、試しに

$ ls | ls

とした時に

ls: write error: Broken pipe

が確率的に発生していた。試しに C で同じような実装をすると特に発生せず、速度の問題かと思って C で sleep しても再現しなくて困っていた(まあこんなコマンド打つことないけど…)。

結局原因は Python がデフォルトでは SIGPIPE を無視することで、これによって後段の ls が終了しても前段が正しく終了せずに ls が実行されてしまっていた。確率的に起きていたのは SIGPIPEexecvp が実行される前か後かの違いによるものだと思う。

PythonSIGPIPE を無視しないようにすると直ったので良かった。

signal.signal(signal.SIGPIPE,signal.SIG_DFL)

redirection

リダイレクションも pipe と原理は同じで、ファイルディスクリプタdup するだけでシュッと実装できた。

github.com

段々気合でパースしている部分が大変になってきている…。

面白かったのは

$ ls > a | cat

とした時に zsh では出力がなされたけど bash / dash では出力されなかった。

これは、 zshmultios という機能によって zsh が redirection と pipe どちらにも出力しているからだった。

zsh.sourceforge.net

unsetopt multios すると、bash / dash と同じ挙動になった。なるほど〜