![在 zsh 的源代碼中設定 $0?](https://rvso.com/image/1586953/%E5%9C%A8%20zsh%20%E7%9A%84%E6%BA%90%E4%BB%A3%E7%A2%BC%E4%B8%AD%E8%A8%AD%E5%AE%9A%20%240%EF%BC%9F.png)
我正在嘗試創建一個行為類似於“通過 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
為此,我將使用<(command)
,一個進程替換,它將創建一個帶有類似於 的路徑的 fifo /proc/self/fd/<n>
,將 的標準輸出重定向command
到它,並評估該路徑。fifo=<(echo 'hi!'); echo $fifo; cat $fifo
將回顯/proc/self/fd/14
(或類似),然後hi!
.
所以這應該可以解決問題,讓我們看看「使用」是否有效。我將把這個腳本保存到我的 $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
解釋zsh
遠端腳本bin/mycommand
,並$0
在其上下文中設定為 previous (local) 的有用值$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.
筆記:
- 我的術語有一個細微差別:「遠端腳本」作為檔案存在於遠端,但在本地進行解釋; 「遙遠的貓」確實很遙遠。
exec-from-myserver
總是使用zsh -c
,遠端腳本中的 shebang 被完全忽略(您的實驗source
也忽略了它)。