Emacsシェルを使用するとこの単純なコマンドが失敗するのはなぜですか?
cat file.txt | wc
10241行を含むファイルがあります。 1行に50文字未満です。このコマンドを実行すると、約90%の時間に行数などの誤った結果が表示されます。それでもエラーメッセージは表示されません。
パイプの破裂が一般的なテーマのようですが、合理的な説明が見つかりませんでした。さらに、誰も解決策を提示できませんでした。この単純なコマンドをどのように安定して動作させることができますか?
もちろん、ただ逃げることもできるwc file.txt
。しかし、私はすべてのツールがPiped cat:でうまく機能するより一般的なソリューションを探していますcat file.txt | any_tool_here
。
詳細
CentOS 5を使用しています。この問題は、次の使用時に発生します。eshell (emacs シェル)。私はGNU Emacs 24.5.2を使用しています。
実験
結果の例cat file.txt | wc
(予想:最初の列は常に10241です)
- 8568 25706 110571
- 9837 29513 126947
- 5395 16187 69615
- 9202 27608 118757
- 7299 21899 94199
- 9837 29513 126947
以下を使用した結果の例wc file.txt
:
- 10241 30723 132156
- 10241 30723 132156
- 10241 30723 132156
- 10241 30723 132156
- 10241 30723 132156
- 10241 30723 132156
catコマンド自体は(単独で実行されると)うまく機能します。次のコマンドを使用して複数回確認しましたcat file.txt > file2.txt
。その後、2つのファイルを比較しましたが、同じです。
答え1
使用されているシェル()に関する情報を見るとeshell
、そのシェルのストリーム処理の側面が原因であるようです。通常、パイプはパイプ+フォーク/execの両端を開くことを意味するため、パイプファイル記述子を共有する2つのプロセスが得られ、通信はカーネルを介して直接行われます。これにより、何も失われません。安全性が保証されます(関連パイプまたはストリームがバッファリングされている場合は、ストリームの最後のチャンクをフラッシュする前に、最初のプロセスが正常に終了するまで待つ必要があるかもしれません)。
抜粋で判断すると電子エンクロージャのパンフレット:
Eshellはbashやzshなどのシステムシェルを置き換えることはできません。 Emacsと外部プロセス間でテキストを移動するには、Eshellを使用します。ある外部プロセスから別のプロセスへ(そして別のプロセスへ)出力をパイプする場合は、システムシェルを使用してください。なぜなら、EmacsのIOシステムはバッファであるからです。ストリーム指向ではなく指向的であり、これらの操作では非常に非効率的です。 Eshellでシェルスクリプトを作成するには、そうしないでください。 elisp ライブラリを作成するか、システムシェルを使用します。
通常の方法でこれを行うのではなく、eshellは「バッファ」(オープンファイルのemacsの表現)をデータの中間リポジトリとして使用してパイプを偽にしますwc
。read
、バッファを埋めるために最初のプログラムで追加の入力を待つのではなく、空のemacs
ブロックで応答(read
ストリームの終わりを示すために0を返す)で終わります。その場合、eshellは非効率的であるだけでなく、パイプを扱う際にも欠陥があるという意味だ。