zsh のソースで $0 を設定しますか?

zsh のソースで $0 を設定しますか?

私は「SSH 経由のシンボリックリンク」のように動作するコマンド、つまり、ローカルで呼び出されたかのようにリモート スクリプトを呼び出すコマンドを作成しようとしています。私のスクリプトは次のとおりです。

#!/bin/zsh
if (( "$#" = 0 )); then
    echo "Usage: $0 <number>" >&2; exit 1
fi
if ! [[ "$1" =~ '^[0-9]+$' ]]; then
    echo "error: “$1” is not a valid number" >&2; exit 1
fi

このため、私は を使用します。これは、 のようなパスを持つ fifo を作成し、の stdout をそれにリダイレクトし、そのパスを評価する<(command)プロセス置換です。 は (または同様の)をエコーし​​、次に を実行します。/proc/self/fd/<n>commandfifo=<(echo 'hi!'); echo $fifo; cat $fifo/proc/self/fd/14hi!

これでうまくいくはずです。「使用方法」が機能するかどうか確認してみましょう。このスクリプトを $PATH に保存し、ファイル名で実行しますexec-remote

#!/bin/zsh
source <(ssh myserver 'cat bin/mycommand')

ほぼ完了です!リモートスクリプトは次のように表示されます

Usage: /proc/self/fd/12 <number>

の代わりに

Usage: exec-remote <number>

…つまり、リモート スクリプトのコードをソースするときに、$0プロセス置換の FIFO パスが設定されます。

しかし、zsh のsourceコマンドは位置パラメータ ( ) のみを受け入れるようです$@

#!/bin/zsh
source <(ssh myserver 'cat bin/mycommand') $0

…スクリプトでは次のように記述します:

error: “/proc/self/fd/12” is not a valid number

では、リモート コードを実行したまま zsh を実行するにはどうすれば$0よいのでしょうか?

答え1

source邪魔になるだけだと思います。以下を(ローカルに)保存しますexec-from-myserver

#!/bin/sh
name=${0##/}
exec zsh -c "$(ssh myserver "cat 'bin/$name'")" "$0" "$@"

実行可能にして、シンボリックリンクを作成します。

ln -s exec-from-myserver mycommand
ln -s exec-from-myserver foo-bar-baz
# etc.

(注:文字列cat 'bin/whatever_name_you_chose'解析されたリモート側では、リテラルを含む名前は'コードを壊したり、誤動作させたりします。特定の方法でシンボリックリンクに名前を付けると、コードインジェクションを実行することさえできます。名前を選択するのはあなたなので、それほど重要ではありません。通常の名前を使用すれば問題ありません。

ここで を呼び出すとmycommand、ローカル スクリプトはリモート を解釈しexec、そのコンテキストで が previous (local) の有用な値に設定されます。 を呼び出すと、リモート をプルして解釈しようとします。例:zshbin/mycommand$0$0foo-bar-bazbin/foo-bar-baz

$ ./mycommand
Usage: ./mycommand <number>
$ # This was your remote script talking.

$ ./mycommand 1
$ # Executed without complaint.

$ ././mycommand
Usage: ././mycommand <number>
$ # As you can see the remote script is aware of its local name and path used.

$ ./foo-bar-baz 
cat: bin/foo-bar-baz: No such file or directory
$ # This was the remote cat talking, only because there is no remote foo-bar-baz.

ノート:

  • 私の用語のニュアンスは次のとおりです。「リモート スクリプト」はファイルとしてリモート側に存在しますが、ローカルで解釈されます。一方、「リモート cat」は実際にはリモートにあります。
  • exec-from-myserverは常に を使用するとzsh -c、リモート スクリプト内の shebang は完全に無視されます ( を使用した実験でsourceも無視されます)。

関連情報