![Definir $ 0 na fonte do zsh?](https://rvso.com/image/1586953/Definir%20%24%200%20na%20fonte%20do%20zsh%3F.png)
Estou tentando criar um comando que se comporte como um “link simbólico através de ssh”, ou seja, chame um script remoto como se fosse chamado localmente. Meu roteiro é:
#!/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
Para isso usarei <(command)
, uma substituição de processo que criará um fifo com um caminho como /proc/self/fd/<n>
, redirecionará command
o stdout de para ele e avaliará para esse caminho. fifo=<(echo 'hi!'); echo $fifo; cat $fifo
irá ecoar /proc/self/fd/14
(ou algo assim) e então hi!
.
Então isso deve funcionar, vamos ver se a coisa de “Uso” funciona. Salvarei esse script em meu $PATH e o executarei pelo nome do arquivo exec-remote
.
#!/bin/zsh
source <(ssh myserver 'cat bin/mycommand')
Quase! Isso resulta no script remoto dizendo
Usage: /proc/self/fd/12 <number>
em vez de
Usage: exec-remote <number>
… o que significa que, ao fornecer o código do script remoto, $0
ele está definido para o caminho fifo da substituição do processo.
Mas o comando do zsh source
parece aceitar apenas parâmetros posicionais ( $@
):
#!/bin/zsh
source <(ssh myserver 'cat bin/mycommand') $0
… fará meu script dizer:
error: “/proc/self/fd/12” is not a valid number
Então, como posso fazer o zsh executar meu código remoto e deixá-lo $0
sozinho ao fazê-lo?
Responder1
Acho que source
só atrapalha. Salve o seguinte (localmente) como exec-from-myserver
:
#!/bin/sh
name=${0##/}
exec zsh -c "$(ssh myserver "cat 'bin/$name'")" "$0" "$@"
Torne-o executável e crie um link simbólico para ele:
ln -s exec-from-myserver mycommand
ln -s exec-from-myserver foo-bar-baz
# etc.
(Nota: a string cat 'bin/whatever_name_you_chose'
seráanalisadono lado remoto. Nomes literais '
quebrarão o código ou farão com que ele se comporte mal; você pode até realizar injeção de código nomeando links simbólicos de uma determinada maneira. Como é você quem escolhe os nomes, isso não é realmente crítico. Use nomes normais e tudo ficará bem.)
Agora, se você ligar mycommand
, o script local exec
interpretará zsh
o remoto bin/mycommand
e $0
em seu contexto será definido com o valor útil de previous (local) $0
. A chamada foo-bar-baz
tentará extrair e interpretar o controle remoto bin/foo-bar-baz
. Exemplos:
$ ./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.
Notas:
- Uma nuance na minha terminologia: "o script remoto" existe no lado remoto como um arquivo, mas é interpretado localmente; “o gato remoto” é verdadeiramente remoto.
exec-from-myserver
sempre usazsh -c
, o shebang no script remoto é completamente ignorado (sua experiênciasource
também o ignorou).