コマンド専用ユーティリティを使用した「zsh」機能の処理

コマンド専用ユーティリティを使用した「zsh」機能の処理

(この質問ではMaccaffeinateツールを例として使用していますが、この概念はxargsユーティリティを引数として受け入れるすべてのツールに適用されます。)

Mac用のツールではcaffeinateユーティリティ名を受け入れます(caffeinate sleep 1たとえば、sleepユーティリティはどこにあります)。zshツール自体を変更せずに機能を許可する方法はありますか?たとえば、

function mysleep {
  sleep 2
}

caffeinate mysleep    # mysleep: No such file or directory

編集:この質問は実際にBashと重複しています。答えを教えてくれてありがとう。しかし、zshではexport -f動作しません。 zshでこれを行う方法はありますか? (bash混雑を減らすためにラベルを削除しています。)

ベストアンサー1

caffeinateコマンドが新しいプロセスで実行されることを期待します。

機能を解釈するにはコマンドがzsh必要ですzsh

関数定義(および必要な他の関数)を渡す必要があります。たとえば、次のようになります。

mysleep() {
  sleep 2
}
caffeinate zsh -c "$(functions mysleep);mysleep"

functions mysleepbyが最終的に解釈されるように関数を呼び出す前に、解釈のためにmysleepnewに渡した関数定義をダンプします。zshzshcaffeinate

mysleep() {
  sleep 2
};mysleep

以下と比較するとbash

mysleep() {
  sleep 2
}
export -f mysleep
caffeinate bash -c "mysleep"

(入力時に2文字短くする)bash以下を行います。

execve("/path/to/caffeinate",
  ["caffeinate", "bash", "-c", "mysleep"],
  ["BASH_FUNC_mysleep%%=() {  sleep 2\n}", rest-of-environment])

zsh、私達は次を得ます:

execve("/path/to/caffeinate",
  ["caffeinate", "zsh", "-c", "mysleep () {\n\tsleep 2\n};mysleep"],
  [rest-of-environment])

後者のアプローチにはいくつかの利点があります。

  • 私たちは完全な制御権を持っています。関数定義を渡す方法とそれを使用する方法を知っています。ここでは、シェルショックのような不快なことが発生する可能性が少なくなります。
  • 関数定義を渡すbash環境変数の名前には%文字が含まれているため(たとえば、文字以外の場合でも)、その変数が実行するコマンドに伝播されるというsudo保証はありません。caffeinatebash
  • 伝播すると、関数定義はargv []ではなくenvp []に格納されるため、その環境で実行されている他のすべてのコマンドの環境が汚染されることを意味します(sleepこの場合は例を含む)。
  • (マイナー)bashシェルコードは短いですが、より多くのデータを渡すため、execve()このシステムコールのE2BIG制限にさらに影響を与えます。

その環境を使用したい場合でも、次のことができます。

FUNCS=$(functions mysleep) caffeinate zsh -c '
  eval "$FUNCS";mysleep'

この場合、関数が実行されているときに実行するだけですが、必ずしもcaffeinate関数caffeinateを実行する必要はなく、次のような他の方法を使用できます。

mysleep | caffeinate cat

cat実行される限りmysleep実行されます。mysleepそれでも別のプロセスで実行されますが、これは標準出力に影響しますmysleep

mysleep 3> {fd}>(caffeinate cat)

両方の問題を解決します。

上記のようにこれmysleepを行うとcat。ただし、パイプの書き込み端は$fd10より大きい新しく割り当てられたファイル記述子(に格納されています)にあり、mysleep通常は記録されません。catしたがって、何も読みませんが、パイプのファイルが終了するのを待ちます。これはmysleep(およびこのfdを継承するすべての子プロセス)が終了した場合にのみ発生します。

おすすめ記事