題 當ssh'ing時,如何在服務器上設置一個環境變量,從一個會話到另一個會話?


當我 ssh 進入服務器,如何將環境變量從客戶端傳遞到服務器?此環境變量在ssh的不同調用之間更改,因此我不想覆蓋 $HOME/.ssh2/environment 我每次打一個ssh電話。我怎樣才能做到這一點?


82
2017-07-13 16:59


起源


你的問題需要更具體。 - Ignacio Vazquez-Abrams
這個問題對我來說已經很清楚了。但是,來自 ssh 除非你修改〜/ .ssh2 / environment,否則除了你登錄到服務器後手動設置變量之外,我看不到任何其他方法。 - garyjohn
每次都是一個不同的變量嗎?還是一個不同的價值? - Dennis Williamson
可能重複 如何通過ssh命令傳遞環境變量? - Tonin
其他方式,因為這已經更受歡迎。沒關係它的年齡越大。 - kenorb


答案:


當然,您可以在命令中設置環境變量,但是您必須小心引用:記住您的shell將解析您的本地命令行,然後遠程shell將在字符串上運行它收到。

如果您希望變量在客戶端上的服務器上獲得相同的值,請嘗試使用 SendEnv 選項:

ssh -o SendEnv = MYVAR server.example.com mycommand

但這需要服務器的支持。使用OpenSSH,必須授權變量名稱 /etc/sshd_config

如果服務器只允許某些特定的變量名,你可以解決這個問題。例如,常見的設置允許 LC_* 通過,您可以執行以下操作:

ssh -o SendEnv = LC_MYVAR server.example.com'MYVAR = $ LC_MYVAR;未設置LC_MYVAR;出口MYVAR; mycommand的“

如果均勻 LC_* 不是一個選項,你可以傳遞信息 TERM 環境變量,總是被複製(但可能有長度限制)。你仍然需要確保遠程shell不限制 TERM 變量以指定已知的終端類型。通過 -t 如果你沒有啟動遠程交互式shell,則選擇ssh。

env TERM =“額外信息:$ TERM”ssh -t server.example.com'MYVAR = $ {TERM%:*}; TERM = $ {TERM ## *:};出口MYVAR; mycommand的“

另一種可能性是直接在命令中定義變量:

ssh -t server.example.com'導出MYVAR =“額外信息”; mycommand的“

因此,如果傳遞局部變量:

ssh -t server.example.com'export MYVAR ='“'$ LOCALVAR'”'; mycommand的“

但是,要注意引用問題:變量的值將直接插入到遠程端執行的shell片段中。上面的最後一個例子假設 $LOCALVAR 不包含任何單引號(')。


98
2017-07-13 19:25



非常感謝,我很憤怒,愚蠢的LC_ *變量在ssh上導出,你的答案指示我去哪裡看。我只需要在〜/ .ssh / config中禁用它 - akostadinov
我正處於原始海報的情況,但我想要轉發的變量是TERM,所以我對你的答案感到有些困惑。最近的OpenSSH版本是否禁用了TERM的自動轉發功能? - Doub
@Doub默認是拒絕服務器端的所有環境變量 AcceptEnv 指令 sshd_config 根據管理員的要求。但 TERM 特別對待,據我所知,沒有辦法在服務器端過濾它(它在shell的環境中設置,無論任何配置設置)。你確定沒有覆蓋它的配置文件腳本(比如 /etc/profile 要么 ~/.profile 要么 ~/.bashrc)? - Gilles
@Gilles:我再次測試了它,除非我明確地將TERM添加到我的AcceptEnv指令中,否則TERM不會被傳遞。我沒有打開shell,而是直接運行命令,例如:“ssh -o SendEnv = TERM shell.example.com env”。打印所有環境變量,只有在客戶端的SendEnv和服務器上的AcceptEnv中才顯示TERM。如果我使用AcceptEnv或SendEnv運行“ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}”,它會打印“dumb”,我不知道它來自哪裡(env甚至沒有在這種情況下列出術語)。 - Doub
@Doub哦,我明白了。 TERM 僅在客戶端請求服務器分配tty時才傳輸。如果遠程端沒有終端,那麼傳輸將毫無用處 TERM。指定命令時,如果要在遠程端有終端,則需要 -t 命令行選項(或 RequestTTY 在 ~/.ssh/config)。 - Gilles


如果您可以管理目標主機,則可以配置sshd以允許將本地環境變量傳遞到目標主機。

從sshd_config手冊頁:

 PermitUserEnvironment
     Specifies whether ~/.ssh/environment and environment= options in
     ~/.ssh/authorized_keys are processed by sshd.  The default is
     "no".  Enabling environment processing may enable users to bypass
     access restrictions in some configurations using mechanisms such
     as LD_PRELOAD.

sshd配置通常生活在 /etc/ssh/sshd_config


12
2018-02-03 17:09



知道默認設置為“no”非常有用! - jathanism


那麼,在您的客戶端上,您有一些環境變量,並且您希望遠程命令可以使用它?我認為沒有辦法讓ssh神奇地傳遞它,但你可能會做這樣的事情。而不是使用,說:

ssh remote.host my_command

你可以這樣做:

ssh remote.host env ENV_VAR=$ENV_VAR my_command

6
2017-07-13 17:52



“大概”?我希望在實際嘗試這個答案之前我已經讀過了。不適合我。 - tishma
注意詳細說明收到的任何錯誤等? - pioto
@pioto可能會引用,例如如果ENV_VAR中有空格 - Martin C. Martin
在Mac上,你必須有一個交互式版本的-t選項,否則它看起來卡住了。所以這可能有效:$ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command - muenalan


@ emptyset的回复(這對我不起作用)讓我得到了這個答案:

您可以將此命令添加到您的 ~/.ssh/authorized_keys 文件:

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>

export VARIABLE=<something> 當時正在退出,並且SSH連接已關閉(將我鎖定在服務器之外),而 /usr/bin/env ... $SHELL將使用修改後的環境運行您的默認shell。


2
2018-05-14 14:36



這只是在我登錄時掛起。當我刪除它時,SSH恢復正常,我得到了我通常的登錄shell。 - Nick Sweeting
@NickSweeting你有沒有嘗試過更換 $SHELL 有一個實際的外殼?還要檢查服務器上是否存在/ usr / bin / env。然而,解決方案並不完美:我注意到它在我想要使用時掛起 scp 或內聯命令。 - madprog
是的,這是我嘗試的第一件事。不幸的是,從來沒有讓它工作,最終啟用 PermitUserEnvironment yes 和使用 environment="..." 代替 command="..."。 - Nick Sweeting


假設您有無密碼的ssh登錄設置,您可以嘗試調用自定義命令。在服務器上,編輯與您客戶端的密鑰對應的〜/ .ssh / authorized_keys條目:

command="export VARIABLE=<something>" ssh-rsa <key>

看著 這個鏈接 在該部分 強制命令 更多細節。


1
2017-07-13 17:15



我嘗試過這個,但它不起作用。它運行命令並退出,因此沒有交互式會話。這是正常的行為嗎?如果是這樣,如果您只想允許特定鍵觸發特定命令,但是如果您想傳遞信息,那麼這可能很有用 在會話中使用 (正如問題所述)那麼它就沒有用了。沒有會話。 - iconoclast


我在主目錄和/ etc(Cram FS是只讀的)中為cram​​fs設備製作了一個OpenSSH的自定義版本,所以〜/ .ssh / environment不能在不重建整個FS的情況下工作,這些都是現場部署的設備(嵌入式系統因此使用CRAMFS)。您可以在sshd_config中指定authroized_keys文件的位置,但由於某種原因,環境=僅適用於〜/ .ssh / authroized_keys中的環境變量。編輯/ etc / profile不是一個選項,我不得不在非標準目錄中加載ssh。在session.c中,在child_set_env之後(...“MAIL”...)只需添加你需要的環境變量(這是我知道的一個黑客...)但是如果你是某個人需要一些硬編碼的envs從源代碼編譯你可以做到這一點。 TGI-FLOSS


1
2017-08-28 16:55