Shell
如何在安裝了fish的遠端伺服器上使用fish而不更改登錄shell?
我經常
ssh
在幾個不同的伺服器上,其中一些沒有fish
安裝,但很多都安裝了。如果可用,我想獲得fish
shell(中途更改總是很乏味,並且您會失去已鍵入內容的歷史記錄),但是更改預設 shell 不是一個好主意,因為:
- 我需要更換許多不同的機器;
- 在許多其他上,我通過 LDAP 登錄,並且更改儲存在 LDAP 上的 shell 會在
fish
不可用的機器上中斷;- 一般來說,由於
fish
不兼容 POSIX-sh,將其作為預設 shell 可能會破壞腳本執行的命令ssh
;- 最後,有幾台機器的使用者與其他人共享(或者,我必須登錄另一個使用者),所以更改預設 shell 不是一個好主意。
因此,理想情況下,我希望有這樣的命令在可用時
ssh
自動啟動fish
,或者只保留提供的任何預設 shell。
經過一些實驗,我整理了
fissh
腳本:#!/bin/sh ssh "$@" -t "sh -c 'if which fish >/dev/null ; then exec fish -li; else exec \$SHELL -li; fi'"
"$@"
轉發傳遞給的所有參數ssh
-t
強制分配 tty(否則ssh
在指定命令時預設為無 tty)sh -c
是必需的,因為我們不知道另一端可能有什麼外殼 - 在我的個人機器上,我確實有fish
預設外殼,這會因不同的if
語法而中斷;which fish
如果找到執行檔則成功fish
;在這種情況下,它是exec
-ed (要求互動式和登錄 shell);- 否則,我們回退到
$SHELL
,這是目前使用者的預設 shell($
被轉義,否則它會被sh
“在這一邊”擴展)。
-li
在任何一種情況下都通過,以確保我們實際上獲得了一個登錄的互動式**shell。雖然-i
POSIX 強制要求任何外殼,-l
但“只是”一個常見的擴展,但不將其放入可能會導致不好的意外。請注意,
stdout
ofwhich
是隱藏的(在正常情況下,我們不關心在哪裡fish
找到),但是stderr
(在找不到錯誤消息的fish
地方)故意保持不變,作為對使用者的警告,儘管我們最好意圖,fish
找不到。為了完成體驗,在我的機器上,
fish
我通過創建一個~/.config/fish/completions/fissh.fish
包含自定義完成的文件來添加對自定義完成的支持complete -c fissh -w ssh
指示
fish
具有fissh
與ssh
.