Bash

為什麼“ssh -t”在登錄和執行命令方面不起作用?

  • September 21, 2021

我在 Mac OS Big Sur 上執行虛擬 Ubuntu 16.04 Linux 實例(使用 vagrant)。我可以很好地執行以下兩個命令(一個用於 ssh 進入虛擬伺服器,第二個用於在其中執行命令)……

$ ssh myvirtual.local
Warning: Permanently added '10.0.4.19' (ECDSA) to the list of known hosts.
Last login: Wed Sep 15 16:37:57 2021 from 10.0.4.1
$ foreman start -f Procfile.debug
16:38:26 rails.1      | started with pid 27884
16:38:26 worker.1     | started with pid 27885
16:38:26 scheduler.1  | started with pid 27887
...

我希望能夠將這兩個命令結合起來,所以我嘗試了

$ ssh -t myvirtual.local 'foreman start -f Procfile.debug’
Warning: Permanently added '10.0.4.19' (ECDSA) to the list of known hosts.
bash: foreman: command not found
Connection to 10.0.4.19 closed.

我很困惑我需要執行什麼其他設置才能有一個命令來模擬我最初正在做的事情。有什麼想法嗎?

在這種情況下的主要區別在於,ssh host以登錄模式啟動您的登錄 shell(以在其前面添加它來sshd啟動它,這告訴 shell 它必須通過讀取一個, , ,或(可能還有系統中的)啟動腳本來初始化登錄會話,具體取決於在 shell 實現上)和互動方式(因為它發出提示以獲取您的輸入)。就是這種模式。-``argv[0]``.profile``.bash_profile``.zprofile``.zlogin``.login``/etc``rlogin``ssh

在 中時ssh -t host 'some shell code',使用and作為參數sshd執行您的登錄 shell,但不告訴它是登錄 shell。該外殼也是非互動式的,程式碼不會從終端提示您。這就是模式。-c``some shell code``rsh

在您的情況下,很可能找不到該命令,因為會話初始化文件中設置$PATH變數的某些指令尚未執行。

請注意,並非所有 shell 都可以作為登錄 shell 並解釋作為參數給出的程式碼。

bash外殼可以。當它開始bash時將作為登錄 shell啟動,但在傳遞 a or選項時也會啟動,然後即使傳遞了要執行的命令(POSIX 模式除外),then1¹ 仍將讀取登錄會話初始化文件。argv[0]``-``-l``--login``-c

所以在這裡,而不是這樣做:

ssh -t host 'some code'

你可以這樣做:

ssh -t host "exec bash --login -c 'some code'"

這將啟動另一個. bash_ _~/.bash_profile``/etc/profile``/etc/profile.d``$PATH``some code

或者您可以嘗試找到進行$PATH定義的文件並執行以下操作:

ssh -t host '. /path/to/that/file && some code'

這仍然存在另一個區別,即 shell 不是互動式的,並且您的啟動文件可能會決定在互動時的行為與非互動時的行為不同(通過檢查 in 的存在i$-通過檢查$PS1變數的存在)。

bash當作為登錄 shell 執行時,即使在互動時(與大多數其他 shell 中發生的情況相反),在啟動時也不會解釋~/.bashrc(互動式 shell 自定義文件),但大多數人通過source ~/.bashrc在他們的~/.bash_profile. 預設情況下~/.profile,Debian 和衍生產品上的預設設置是這樣做的(當然只有當 shell 是這樣bash時)。

bash預設情況下通過 ssh 呼叫時不會解釋~/.bashrc,但可以在編譯時使用SSH_SOURCE_BASHRC配置選項進行配置。Debian 和 Ubuntu 等衍生產品確實可以做到這一點。因此,在執行時ssh ubuntu-host 'some code',如果您的登錄 shell 是該機器上的 bash ,則將啟動的bashshell將在解釋之前解釋。sshd``~/.bashrc``some code

~/.bashrc最終以rloginand模式解釋也是如此rsh,但正如@Quasimodo 所指出的,~/.bashrcDebian 和 Ubuntu 的預設設置在頂部:

# If not running interactively, don't do anything
case $- in
   *i*) ;;
     *) return;;
esac

所以,如果$PATH在這些行下面有一個定義,它們只會在rlogin模式中解釋(bash互動的地方,$-包含i~/.bashrc來源~/.profile),而不是rsh模式(~/.bashrc來源,但它的大部分內容被跳過為外殼不是互動式的)。


¹ 在以argv[0]開頭-(與以-l/相對--login)的情況下,傳遞 a 時是否將其視為登錄 shell-c code取決於是否已啟用bash編譯。NON_INTERACTIVE_LOGIN_SHELLS

引用自:https://unix.stackexchange.com/questions/669157