zsh zptyはmacOSでは動作しません。 Linuxで実行できますか?

zsh zptyはmacOSでは動作しません。 Linuxで実行できますか?

zshモジュールzsh / zptyは、Apple M1 macOSシステムで実行されているLinux仮想マシンで正しく実行されているようです。ただし、macOSでは同じ方法は機能しません(同じホストでも)。私はmacOSにプリインストールされたzshバージョン/bin/zshとhomebrewからインストールされたzshバージョンの両方でこれを試しました。

私の観察によると、zptyコマンドを実行して疑似端末を作成し、その中でコマンドを実行すると、実際にプロセスが生成されます。しかし、書き込みプロセスは機能しません。以下はいくつかの例です。インタラクティブzshセッションで、次のコマンドを1つずつ入力しました。

zmodload zsh/zpty
zpty -b hello 'vim --clean'
zpty -w hello ':e foo'
zpty -w hello $'aHello there from foo file\e:w'
cat foo
zpty -d hello

macOSではcat失敗し、cat: foo: No such file or directoryLinuxではこれが表示されますHello there from foo file

zptyで何を達成したいですか?疑似端末でプロセスを開始し、zsh手動の予定に応じて非同期で入力を送信したいと思います。私はプロセスの標準出力に興味がありません。理想的な解決策は、CPUリソースを束ねたり、遅延ループなしですべての標準出力を破棄することです。また、expect他の外部プログラムを使用する代替ソリューションを探していません。

これはzshまたはmacOSのバグですか? dtraceのようにバイパスできますか?これ?しかし、それがSIP(System Integrity Protection)に関連している場合は驚きます。

答え1

私はこれがあなたのコードのバグだと言いたいです。これは、うまくいかないかもしれないことを意味します。 Linuxで動作するという事実が他の人にも機能するという保証もなく、LinuxがmacOSよりも優れているという意味でもありません。

  1. vimにコマンドを送信し、vimが反応するのを待ちません。したがって、foo最終的にはこれが起こる可能性が高いですが、zshがより速く、ファイルが準備される前に確認します。これはvimとzshの相対的な実行速度に依存し、これはそれぞれの正確なバージョン、システムライブラリ、オペレーティングシステムのカーネル、CPU、ムーンフェイズなどによって異なります。
  2. 端末はデータを読み取ることができないため、書き込み中にvimがブロックされる可能性があります。停止するかどうかは、vimがどのくらい書きたいか(システムライブラリ(特にCurses)とterminfoエントリによって異なります)と、端末がデータを消費する前に端末インタフェースで書くことができる量によって異なります(これはvimのカーネル、おそらくzshによって使用されるシステムライブラリにあるかもしれません)。

正しい解決策は、vimが目的の操作を実行したことを確認するまで端末からデータを読み取ることです。つまり、「B write」行を待っているのです。これにより、vimがブロックされず、十分に長く待つことができます。

macOSでいくつかの実験をしましたが、デバッガでは見ることができませんでした。このコードを試してください。しばらく待ってから、vimが作成したすべての内容を読み、特定の確認を待たずにファイルを確認します。

rm -f foo
zpty -b hello 'vim --clean'
zpty -w hello ':e foo'
zpty -w hello $'iHello there from foo file\e:w'
sleep 0.02
zpty -r hello > >(xxd)
ls foo
zpty -d hello

私にとっては、fooこれを実行するときにそれがあるかもしれないしないかもしれません。sleepシステム値をしきい値に近づけるように調整する必要があるかもしれません。私のコンピュータでは、sleep 0.2mustはfoo常に存在し、省略はsleep常に存在しませんfoo。ただし、上記のように、これはさまざまなパラメータによって異なります。

次のコードはfoo保存されるまで確実に待ちます(Vimのメッセージにが含まれていると仮定し、代わりに私の設定で実行するとメッセージにがB written含まれます)。vimvim --cleanbytes written

rm -f foo
zpty -b hello 'vim --clean'
zpty -w hello ':e foo'
zpty -w hello $'iHello there from foo file\e:w'
while zpty -r hello data; [[ $data != *"B written"* ]]; do sleep 0.1; done
ls foo
zpty -d hello

関連情報