Tại sao xuất một biến trong vỏ ssh lại in danh sách các biến được xuất?


17

Xem xét điều này:

$ ssh localhost bash -c 'export foo=bar'
terdon@localhost's password: 
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x HOME="/home/terdon"
declare -x LOGNAME="terdon"
declare -x MAIL="/var/spool/mail/terdon"
declare -x OLDPWD
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin"
declare -x PWD="/home/terdon"
declare -x SHELL="/bin/bash"
declare -x SHLVL="2"
declare -x SSH_CLIENT="::1 55858 22"
declare -x SSH_CONNECTION="::1 55858 ::1 22"
declare -x USER="terdon"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SESSION_ID="c5"
declare -x _="/usr/bin/bash"

Tại sao việc xuất một biến trong bash -cphiên chạy qua ssh lại dẫn đến danh sách các declare -xlệnh đó (danh sách các biến hiện được xuất, theo như tôi có thể nói)?

Chạy cùng một thứ mà bash -ckhông làm điều đó:

$ ssh localhost  'export foo=bar'
terdon@localhost's password: 
$

Nó cũng không xảy ra nếu chúng ta không export:

$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password: 
$ 

Tôi đã kiểm tra điều này bằng cách sshing từ máy Ubuntu này sang máy khác (cả chạy bash 4.3.11) và trên máy Arch, sshing cho chính nó như được hiển thị ở trên (bash phiên bản 4.4.5).

Những gì đang xảy ra ở đây? Tại sao xuất một biến trong một bash -ccuộc gọi tạo ra đầu ra này?


Điều này không trả lời câu hỏi, nhưng đầu ra là kết quả của việc chạy export. Zsh làm điều tương tự.
Stephen Kitt

@StephenKitt vâng, tôi biết điều đó export, tôi đang cố gắng hiểu chuyện gì đang xảy ra. Tôi sẽ chỉnh sửa để làm rõ rằng điều này chỉ xảy ra khi xuất.
terdon

À, tôi đã đọc "danh sách các biến hiện được xuất, theo như tôi có thể nói" có nghĩa là bạn không biết đầu ra đến từ đâu.
Stephen Kitt

@StephenKitt Ý tôi là tôi không chắc đó là mỗi biến được xuất hay một tập hợp con cụ thể hay là gì. Oh! Bạn có nghĩa là nó là đầu ra của exportchạy một mình? Điều đó tôi đã không hiểu.
terdon

Lưu ý rằng foo=barkhông xuất hiện trong danh sách.
deltab

Câu trả lời:


31

Khi bạn chạy một lệnh thông qua ssh, nó được chạy bằng cách gọi cờ của bạn $SHELLbằng -ccờ:

-c    If the -c option is present, then commands are read from 
      the first non-option argument command_string.  If there  are
      arguments  after the command_string, the first argument is 
      assigned to $0 and any remaining arguments are assigned to
      the positional parameters.  

Vì vậy, ssh remote_host "bash -c foo"sẽ thực sự chạy:

/bin/your_shell -c 'bash -c foo'

Bây giờ, vì lệnh bạn đang chạy ( export foo=bar) chứa khoảng trắng và không được trích dẫn chính xác để tạo thành một tổng thể, nên lệnh exportnày được coi là lệnh sẽ được chạy và phần còn lại được lưu trong mảng tham số vị trí. Điều này có nghĩa exportlà được chạy và foo=barđược truyền cho nó như là $0. Kết quả cuối cùng giống như chạy

/bin/your_shell -c 'bash -c export'

Lệnh đúng sẽ là:

ssh remote_host "bash -c 'export foo=bar'"

9

ssh nối các đối số với khoảng trắng và có vỏ đăng nhập của người dùng từ xa diễn giải nó, vì vậy:

ssh localhost bash -c 'export foo=bar'

ssh đang yêu cầu shell từ xa để giải thích

bash -c export foo=bar

lệnh (có hiệu lực, nếu máy chủ từ xa là Unix-like, nó sẽ chạy vỏ từ xa với the-shell, -cbash -c export foo=barnhư các đối số).

Hầu hết vỏ sẽ giải thích rằng dòng lệnh như chạy các bashlệnh với bash, -c, exportfoo=barnhư các đối số (để chạy exportkhi $0chứa foo=bar) trong khi bạn muốn nó để chạy nó với bash, -cexport foo=barnhư các đối số.

Vì vậy, bạn cần sử dụng một dòng lệnh như:

ssh localhost "bash -c 'export foo=bar'"

(hoặc là:

ssh localhost bash -c \'export foo=bar\'

cho vấn đề đó) vì vậy:

bash -c 'export foo=bar'

dòng lệnh được truyền đến shell từ xa. Đó là dòng lệnh sẽ được giải thích bởi hầu hết các vỏ như chạy các bashlệnh với bash, -cexport foo=barnhư các đối số. Lưu ý rằng sử dụng

ssh localhost 'bash -c "export foo=bar"'

sẽ không hoạt động nếu shell đăng nhập của người dùng từ xa rchoặc esví dụ "không phải là toán tử trích dẫn đặc biệt. Dấu ngoặc đơn là toán tử trích dẫn di động nhất (mặc dù có một số biến thể về cách chúng được diễn giải giữa các shell, xem Cách thực thi lệnh đơn giản tùy ý trên ssh mà không cần biết trình đăng nhập của người dùng từ xa? Để biết thêm về điều đó).

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.