Khi ssh'ing, làm cách nào tôi có thể đặt biến môi trường trên máy chủ thay đổi từ phiên này sang phiên khác?


92

Khi tôi sshvào một máy chủ, làm thế nào tôi có thể chuyển một biến môi trường từ máy khách sang máy chủ? Biến môi trường này thay đổi giữa các cách gọi khác nhau của ssh vì vậy tôi không muốn ghi đè $HOME/.ssh2/environmentmỗi khi tôi thực hiện cuộc gọi ssh. Tôi có thể làm cái này như thế nào?


2
Câu hỏi của bạn cần phải cụ thể hơn.
Ignacio Vazquez-Abrams

3
Câu hỏi đã đủ rõ ràng với tôi. Tuy nhiên, từ sshtrang man, tôi không thấy cách nào khác ngoài việc đặt biến theo cách thủ công một khi bạn đã đăng nhập vào máy chủ, trừ khi bạn sửa đổi ~ / .ssh2 / môi trường.
garyjohn

Có phải là một biến khác nhau mỗi lần? Hay một giá trị khác?
Dennis Williamson


1
Cách khác, vì điều này đã phổ biến hơn. Nó không quan trọng nó cũ hơn.
kenorb

Câu trả lời:


110

Tất nhiên, bạn có thể đặt biến môi trường bên trong lệnh, tuy nhiên bạn sẽ phải cẩn thận khi trích dẫn: hãy nhớ rằng trình bao của bạn sẽ phân tích dòng lệnh cục bộ của bạn, và sau đó trình điều khiển từ xa sẽ đi theo chuỗi nhận.

Nếu bạn muốn một biến có cùng giá trị trên máy chủ mà nó có trên máy khách, hãy thử SendEnvtùy chọn:

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

Điều này đòi hỏi sự hỗ trợ từ máy chủ, mặc dù. Với OpenSSH, tên biến phải được cấp phép /etc/sshd_config.

Nếu máy chủ chỉ cho phép một số tên biến cụ thể, bạn có thể làm việc xung quanh đó; ví dụ: thiết lập chung cho phép LC_*thông qua và bạn có thể thực hiện các thao tác sau:

ssh -o SendEnv = LC_MYVAR máy chủ.example.com 'MYVAR = $ LC_MYVAR; bỏ đặt LC_MYVAR; xuất khẩu MYVAR; Lệnh của tôi'

Nếu thậm chí LC_*không phải là một tùy chọn, bạn có thể truyền thông tin trong TERMbiến môi trường, luôn được sao chép (tuy nhiên có thể có giới hạn độ dài). Bạn vẫn phải đảm bảo rằng trình điều khiển từ xa không hạn chế TERMbiến để chỉ định loại thiết bị đầu cuối đã biết. Chuyển -ttùy chọn sang ssh nếu bạn không bắt đầu trình bao tương tác từ xa.

env TERM = "thông tin bổ sung: $ TERM" ssh -t server.example.com 'MYVAR = $ {TATE%: *}; HẠN = $ {HẠN ## *:}; xuất khẩu MYVAR; Lệnh của tôi'

Một khả năng khác là xác định biến trực tiếp trong lệnh:

ssh -t server.example.com 'export MYVAR = "thông tin bổ sung"; Lệnh của tôi'

Do đó, nếu truyền một biến cục bộ:

ssh -t server.example.com 'export MYVAR =' "'$ LOCALVAR'" '; Lệnh của tôi'

Tuy nhiên, hãy cẩn thận khi trích dẫn các vấn đề: giá trị của biến sẽ được nội suy trực tiếp vào đoạn mã shell được thực thi ở phía xa. Ví dụ cuối cùng ở trên giả định rằng $LOCALVARkhông chứa bất kỳ dấu ngoặc đơn nào ( ').


2
Cảm ơn rất nhiều, tôi đã nổi cơn thịnh nộ rằng các biến LC_ * ngu ngốc được xuất trên ssh và câu trả lời của bạn hướng tôi đến nơi cần tìm. Tôi chỉ cần vô hiệu hóa nó trong ~ / .ssh / config
akostadinov

1
Tôi đang ở trong tình huống của poster gốc, nhưng biến mà tôi muốn chuyển tiếp là HẠN, vì vậy tôi hơi bối rối trước câu trả lời của bạn. Điều này tự động chuyển tiếp TERM đã bị vô hiệu hóa bởi các phiên bản OpenSSH gần đây?
Nghi ngờ

1
@Doub Mặc định là từ chối tất cả các biến môi trường ở phía máy chủ, với các AcceptEnvchỉ thị sshd_configtheo mong muốn của quản trị viên. Nhưng TERMđược xử lý đặc biệt, theo như tôi biết, không có cách nào để lọc nó ở phía máy chủ (nó được đặt trong môi trường của shell bất kể cài đặt cấu hình nào). Bạn có chắc chắn không có tập lệnh hồ sơ nào ghi đè lên nó (như /etc/profilehoặc ~/.profilehoặc ~/.bashrc) không?
Gilles

2
@Gilles: Tôi đã kiểm tra lại lần nữa và trừ khi tôi thêm TATE vào chỉ thị AcceptEnv của mình một cách rõ ràng, thì HẠN không được thông qua. Tôi không mở shell, nhưng chạy lệnh trực tiếp, ví dụ: "ssh -o SendEnv = TERM shell.example.com env". Điều đó in tất cả các biến môi trường và TERM chỉ xuất hiện nếu nó trong SendEnv trên máy khách và AcceptEnv trên máy chủ. Nếu tôi chạy "ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}" không chấp nhận AcceptEnv hoặc SendEnv, nó sẽ in "câm", mà tôi không chắc là nó đến từ đâu (env thậm chí không chắc là nó đến từ đâu liệt kê HẠN trong trường hợp đó).
Nghi ngờ

7
@Doub ơi, tôi hiểu rồi. TERMchỉ được truyền nếu máy khách yêu cầu máy chủ phân bổ một tty. Nếu không có thiết bị đầu cuối ở phía xa, nó sẽ vô dụng để truyền TERM. Khi bạn chỉ định một lệnh, nếu bạn muốn có một thiết bị đầu cuối ở phía xa, bạn cần -ttùy chọn dòng lệnh (hoặc RequestTTYtrong ~/.ssh/config).
Gilles

12

Nếu bạn có thể quản trị máy chủ đích, bạn có thể định cấu hình sshd để cho phép chuyển các biến môi trường cục bộ của bạn sang máy chủ đích.

Từ trang người đàn ông 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.

cấu hình sshd thường sống ở /etc/ssh/sshd_config


7
Thật hữu ích khi biết rằng điều này được đặt thành "không" theo mặc định!
jathanism

6

Vì vậy, trên máy khách của bạn, bạn có một số biến môi trường và bạn muốn nó có sẵn cho lệnh từ xa? Tôi không nghĩ có một cách để ssh vượt qua nó một cách kỳ diệu, nhưng bạn có thể làm điều gì đó như thế này. Thay vì sử dụng, hãy nói:

ssh remote.host my_command

Bạn có thể làm được việc này:

ssh remote.host env ENV_VAR=$ENV_VAR my_command

"có lẽ"? Tôi ước tôi đọc nó trước khi thực sự thử câu trả lời này. Không làm việc cho tôi.
tishma

1
Quan tâm đến chi tiết về bất kỳ lỗi nhận được, vv?
pioto

1
@pioto Có thể trích dẫn, ví dụ: nếu ENV_VAR có khoảng trắng trong đó
Martin C. Martin

Trên Mac, bạn phải có tùy chọn -t cho phiên bản tương tác, nếu không, nó có vẻ bị kẹt. Vì vậy, điều này có thể hoạt động: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan

3

Phản hồi của @ blankset (không phù hợp với tôi) đã đưa tôi đến câu trả lời này:

Bạn có thể thêm lệnh này vào ~/.ssh/authorized_keystập tin của bạn :

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

export VARIABLE=<something>đã thoát ngay lập tức và kết nối SSH đã bị đóng (khóa tôi khỏi máy chủ), trong khi đó /usr/bin/env ... $SHELLsẽ chạy shell mặc định của bạn với môi trường được sửa đổi.


Điều này chỉ bị treo khi đăng nhập cho tôi. Khi tôi gỡ bỏ, SSH trở lại bình thường và tôi nhận được vỏ đăng nhập thông thường.
Nick Sweeting

@NickSweeting bạn đã thử có thể thay thế $SHELLbằng một vỏ thực tế chưa? Đồng thời kiểm tra xem / usr / bin / env có tồn tại trên máy chủ không. Tuy nhiên, giải pháp không hoàn hảo: Tôi đã nhận thấy rằng nó bị treo khi tôi muốn sử dụng scphoặc một lệnh nội tuyến.
madprog

Vâng, đó là điều đầu tiên tôi đã thử. Thật không may, không bao giờ có nó để làm việc, kết thúc cho phép PermitUserEnvironment yesvà sử dụng environment="..."thay vì command="...".
Nick Sweeting

Điều này đang làm việc tốt cho tôi.
Ông Tao

3

Trên máy khách cục bộ của ~/.ssh/configbạn, bạn có thể thêm SetEnv, ví dụ:

Host myhost
  SetEnv FOO=bar

Lưu ý: Kiểm tra man ssh_config.

Sau đó, trên máy chủ, đảm bảo cho phép máy khách vượt qua các biến môi trường nhất định trong /etc/ssh/sshd_configtệp cấu hình của bạn :

AcceptEnv LANG LC_* FOO BAR*

Lưu ý: Kiểm tra man sshd_config.


1

Bạn có thể thử gọi một lệnh tùy chỉnh, giả sử bạn có thiết lập đăng nhập ssh không cần mật khẩu. Trên máy chủ, hãy chỉnh sửa mục nhập ~ / .ssh / ủy quyền của bạn tương ứng với khóa từ máy khách của bạn:

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

Nhìn vào liên kết này trong phần Lệnh cưỡng bức để biết thêm chi tiết.


1
Tôi đã thử điều này, nhưng nó không hoạt động. Nó chạy lệnh và thoát, vì vậy không có phiên tương tác. Đó có phải là hành vi bình thường? Nếu vậy, điều đó có thể hữu ích nếu tất cả những gì bạn muốn làm là cho phép một khóa cụ thể để kích hoạt một lệnh cụ thể, nhưng nếu bạn muốn truyền thông tin được sử dụng trong một phiên (như câu hỏi) thì vô dụng cho mục đích đó . Không có phiên nào.
iconoclast

1

Tôi đã tạo một bản dựng OpenSSH tùy chỉnh cho một thiết bị có cramfs trong thư mục chính và / etc (Cram FS chỉ đọc) vì vậy ~ / .ssh / môi trường sẽ không hoạt động nếu không xây dựng lại toàn bộ FS và các trường này đã được triển khai thiết bị (Hệ thống nhúng Do đó sử dụng CRAMFS). Bạn có thể chỉ định trong sshd_config vị trí của tệp authroized_keys nhưng vì một số lý do, môi trường = chỉ hoạt động cho các biến môi trường trong ~ / .ssh / authroized_keys. Chỉnh sửa / etc / profile không phải là một tùy chọn và tôi phải tải ssh trong một thư mục không chuẩn. Trong session.c sau child_set_env (... "MAIL" ...) chỉ cần thêm các biến môi trường mà bạn cần (Đây là một hack tôi biết ...) nhưng chỉ cần ai đó cần một số env được mã hóa cứng cho một phiên nếu bạn là biên dịch từ nguồn bạn có thể làm điều này. TGI-FLOSS


0

chỉ một lệnh đơn giản:

ssh -t your_host_or_ip 'export some_var_name=whatever_you_want; bash'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.