![$0 in der zsh-Quelle festlegen?](https://rvso.com/image/1586953/%240%20in%20der%20zsh-Quelle%20festlegen%3F.png)
Ich versuche, einen Befehl zu erstellen, der sich wie ein „Symlink über SSH“ verhält, d. h. ein Remote-Skript aufruft, als ob es lokal aufgerufen würde. Mein Skript ist:
#!/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
Hierfür verwende ich <(command)
, eine Prozessersetzung, die ein FIFO mit einem Pfad wie erstellt /proc/self/fd/<n>
, command
die Standardausgabe von dorthin umleitet und die Auswertung anhand dieses Pfads vornimmt. Es fifo=<(echo 'hi!'); echo $fifo; cat $fifo
wird ein Echo /proc/self/fd/14
(oder so ähnlich) ausgegeben und dann hi!
.
Das sollte also funktionieren. Mal sehen, ob die Sache mit der „Verwendung“ funktioniert. Ich speichere dieses Skript in meinem $PATH und führe es über seinen Dateinamen aus exec-remote
.
#!/bin/zsh
source <(ssh myserver 'cat bin/mycommand')
Fast! Das Ergebnis ist, dass das Remote-Skript sagt:
Usage: /proc/self/fd/12 <number>
anstatt
Usage: exec-remote <number>
… was bedeutet, dass beim Abrufen des Codes des Remote-Skripts $0
der FIFO-Pfad der Prozessersetzung eingestellt ist.
Aber der Befehl von zsh source
scheint nur Positionsparameter ( $@
) zu akzeptieren:
#!/bin/zsh
source <(ssh myserver 'cat bin/mycommand') $0
… lässt mein Skript sagen:
error: “/proc/self/fd/12” is not a valid number
Wie kann ich also erreichen, dass zsh meinen Remote-Code ausführt, ohne $0
ihn dabei zu verändern?
Antwort1
Ich denke, source
das ist nur ein Hindernis. Speichern Sie Folgendes (lokal) als exec-from-myserver
:
#!/bin/sh
name=${0##/}
exec zsh -c "$(ssh myserver "cat 'bin/$name'")" "$0" "$@"
Machen Sie es ausführbar und erstellen Sie dann einen symbolischen Link darauf:
ln -s exec-from-myserver mycommand
ln -s exec-from-myserver foo-bar-baz
# etc.
(Hinweis: Die Zeichenfolge cat 'bin/whatever_name_you_chose'
wirdanalysiertauf der Remote-Seite. Namen mit Literalwerten '
beschädigen den Code oder führen zu Fehlfunktionen. Sie können sogar Code-Injektion durchführen, indem Sie Symlinks auf eine bestimmte Weise benennen. Da Sie die Namen auswählen, ist dies nicht wirklich kritisch. Verwenden Sie normale Namen, dann ist alles in Ordnung.)
Wenn Sie jetzt aufrufen , interpretiert mycommand
das lokale Skript den Remote-Befehl und wird in seinem Kontext auf den nützlichen Wert von previous (local) gesetzt . Der Aufruf versucht, den Remote-Befehl abzurufen und zu interpretieren . Beispiele:exec
zsh
bin/mycommand
$0
$0
foo-bar-baz
bin/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.
Anmerkungen:
- Eine Nuance in meiner Terminologie: „Das Remote-Skript“ existiert auf der Remote-Seite als Datei, wird aber lokal interpretiert; „die Remote-Cat“ ist wirklich remote.
exec-from-myserver
verwendet immerzsh -c
, der Shebang im Remote-Skript wird vollständig ignoriert (Ihr Experiment mitsource
hat ihn ebenfalls ignoriert).