biến biến trong ssh


7

Tôi đang cố gắng chuyển một biến sang ssh từ xa nhưng không hoạt động. Mã của tôi là:

#!/bin/bash
set -x
conexion="user@xx.yy.zz.pp"
parameter="$1"
ssh -T $conexion <<'ENDSSH' 
clear
echo "$parameter"
ENDSSH

Tôi thi hành:

./script.sh try

Nó nói với tôi:

parameter: Undefined variable.

Xin giúp đỡ?


4
hãy thử sử dụng ENDSSH mà không cần trích dẫn.
Archemar

1
@ user650034 nếu điều này giải quyết vấn đề của bạn, vui lòng đánh dấu câu trả lời là đã được phê duyệt.
ddnomad

Câu trả lời:


8

Truyền các biến (biến môi trường) sshlà có thể nhưng thường bị hạn chế.

Bạn cần nói với khách hàng để gửi cho họ. Ví dụ với OpenSSH, đó là:

ssh -o SendEnv=parameter host cmd...

Nhưng bạn cũng cần máy chủ chấp nhận nó ( AcceptEnvchỉ thị cấu hình với OpenSSH). Chấp nhận bất kỳ biến nào là một rủi ro bảo mật lớn, do đó thường không được thực hiện theo mặc định, mặc dù một số triển khai ssh cho phép một số biến trong một số không gian tên (như LC_*trong một số triển khai OpenSSH).

Bạn cũng cần xuất biến trước khi gọi ssh, như:

LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END

Ở trên, chúng ta chuyển nội dung của $parameter bashbiến shell thành biến LC_parametermôi trường ssh. sshgửi nó tới sshd, nếu nó chấp nhận nó, chuyển nó dưới dạng biến môi trường tới shell đăng nhập của người dùng, sau đó chuyển nó tới cshlệnh đó (sau đó có thể mở rộng nó).

Nhưng như đã đề cập trước đó, điều đó sẽ không hoạt động trừ khi quản trị viên của hostmáy đã thêm một AcceptEnv LC_parameterhoặc AcceptEnv LC_*(điều đó đôi khi được thực hiện theo mặc định) vào sshdcấu hình.

Thông Undefined variablebáo lỗi trong ví dụ của bạn cho thấy vỏ đăng nhập của người dùng từ xa là cshhoặc tcsh. Tốt hơn hết là gọi vỏ một cách rõ ràng để tránh những điều bất ngờ ( ssh host cshcũng có nghĩa là một tty không được yêu cầu nên bạn không cần -T). Lưu ý $LC_parameter:qcú pháp, đó là cshcách để truyền nội dung của một nguyên văn biến, không "$LC_parameter"phải là không hoạt động nếu biến chứa các ký tự dòng mới.

Nếu sử dụng LC_*biến không phải là một tùy chọn, thì thay vào đó, bạn có thể có trình vỏ máy khách ( bashtrong trường hợp của bạn) mở rộng biến. Một cách ngây thơ sẽ là với

ssh host csh << END
echo "$variable"
END

Nhưng điều đó sẽ nguy hiểm vì nội dung của biến sẽ được giải thích bởi shell từ xa. Nếu $variablecó chứa `reboot`hoặc "; reboot; : "ví dụ, điều đó sẽ có hậu quả xấu.

Vì vậy, trước tiên bạn cần đảm bảo biến được trích dẫn chính xác theo cú pháp của shell từ xa. Ở đây, tôi sẽ tránh cshnơi khó thực hiện và sử dụng sh/ bash/ kshthay vào đó.

Sử dụng chức năng trợ giúp để thực hiện trích dẫn sh:

shquote() {
  awk -v q=\' -v b='\\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q b q q, ARGV[i])
       printf "%s ", q ARGV[i] q
      }
      print ""
      exit
    }' "$@"
}

Và gọi sshlà:

ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END

Xem cách chúng ta thoát khỏi cái thứ ba $để việc mở rộng $parameterđược thực hiện bởi shell từ xa chứ không phải cái cục bộ.


không cần phải là biến môi trường, biến có thể được mở rộng và được chuyển dưới dạng văn bản. Đây dường như là ý định và là những gì được thực hiện trong câu trả lời của @ ddnomad.
ctrl-alt-delor

Giải thích tốt và sử dụng SendEnvAcceptEnvnhư sử dụng chúng đúng cách vượt qua một biến chứ không phải là một giá trị . Đây là, nói đúng ra, những gì đã được yêu cầu.
Kusalananda

@richard, nhưng như tôi nói, cách tiếp cận ngây thơ đó là không đáng tin cậy và nguy hiểm. Câu trả lời của tôi cũng cung cấp chi tiết về cách thực hiện việc mở rộng đó một cách đáng tin cậy / an toàn
Stéphane Chazelas

@Kusalananda, một nhà phân tích hệ thống không được trả lời những gì khách hàng đã nói một cách nghiêm túc, họ phải tìm ra những gì họ muốn, thường là với một loạt các câu hỏi. Tôi đã ở trong nhiều tình huống, trong đó khách hàng sẽ yêu cầu một cái gì đó, sử dụng các từ trong miền của lập trình viên / kỹ sư phần mềm / nhà phân tích, mà không biết những từ đó thực sự có nghĩa là gì, và các thành viên trong nhóm của tôi sẽ lấy từ đó theo mệnh giá và cung cấp cho họ một cái gì đó không đu.
ctrl-alt-delor

3

Trong số các thủ thuật khác (như chuyển LC_*các biến môi trường), bạn có thể làm như sau:

PARAMETER="123"
ssh user@host PARAMETER="$PARAMETER" bash -s <<- __EOF
    echo \$PARAMETER
__EOF

Ưu điểm của phương pháp này là không có yêu cầu export PARAMETER, thêm tên của nó vào AcceptEnv(trong trường hợp tên không bắt đầu LC_) trong cấu hình /etc/ssh/sshd_configtrên máy chủ từ xa, thêm SendEnvvào máy chủ cục bộ (đến -ohoặc đến /etc/ssh/ssh_config).


Điều này có vấn đề tiêm mã giống như câu trả lời của ddnomad.
Brian McCutchon

2

Xóa dấu ngoặc kép ENDSSHtrên dòng thứ 4 sẽ giúp ích.

Lịch sự: @Archemar trong các bình luận cho câu hỏi.

CẢNH BÁO Như đã được @ StéphaneChazelas nêu trong phần bình luận cho câu trả lời này, việc làm này sẽ khiến $parameterbiến trong tài liệu ở đây được mở rộng bởi shell cục bộ, có nghĩa là nội dung của biến sẽ được hiểu là mã shell bởi shell từ xa , có nghĩa là nó giới thiệu một lỗ hổng tiêm lệnh. Vì vậy, nói chung nó không được khuyến khích để làm như vậy.


2
Điều đó sẽ khiến $parameterbiến trong tài liệu ở đây được mở rộng bởi shell cục bộ, điều đó có nghĩa là nội dung của biến sẽ được hiểu là mã shell bởi shell từ xa, có nghĩa là nó đưa ra lỗ hổng tiêm lệnh ví dụ nếu giá trị của $parameterlà không hoàn toàn dưới sự kiểm soát của bạn và bạn đã không vệ sinh nó.
Stéphane Chazelas

@ StéphaneChazelas điểm tốt Tôi sẽ thêm một cảnh báo cho câu trả lời
ddnomad
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.