Shell の pipe と redirection を実装する
新年なので Shell の pipe と redirection を実装した。
前回の記事はこちら
前回実装してみて、さすがに pipe と redirection ぐらいは実装しておいてもいいのでは?と思って実装してみた。
pipe
パイプについての説明は
が分かりやすくて、ここを見ると大体いい感じに実装できた。
一つ困ったのは、試しに
$ ls | ls
とした時に
ls: write error: Broken pipe
が確率的に発生していた。試しに C で同じような実装をすると特に発生せず、速度の問題かと思って C で sleep
しても再現しなくて困っていた(まあこんなコマンド打つことないけど…)。
結局原因は Python がデフォルトでは SIGPIPE
を無視することで、これによって後段の ls
が終了しても前段が正しく終了せずに ls
が実行されてしまっていた。確率的に起きていたのは SIGPIPE
が execvp
が実行される前か後かの違いによるものだと思う。
Python で SIGPIPE
を無視しないようにすると直ったので良かった。
signal.signal(signal.SIGPIPE,signal.SIG_DFL)
redirection
リダイレクションも pipe と原理は同じで、ファイルディスクリプタを dup
するだけでシュッと実装できた。
段々気合でパースしている部分が大変になってきている…。
面白かったのは
$ ls > a | cat
とした時に zsh では出力がなされたけど bash / dash では出力されなかった。
これは、 zsh の multios
という機能によって zsh が redirection と pipe どちらにも出力しているからだった。
unsetopt multios
すると、bash / dash と同じ挙動になった。なるほど〜