Với ssh, làm thế nào bạn có thể chạy một lệnh trên máy từ xa mà không thoát?


28

Thông thường, nếu bạn truyền lệnh cho ssh như vậy

ssh me@example.com 'some-command.sh'

Bạn nhận được một phiên không tương tác và ssh thoát ngay khi lệnh (hoặc tập lệnh hoặc bất cứ thứ gì) được chạy. Làm cách nào tôi có thể có phiên tương tác và chạy lệnh mà tôi đã chỉ định từ máy cục bộ của mình. Chẳng hạn, tôi muốn có thể mở màn hình và khởi động lại một phiên màn hình cụ thể:

ssh me@example.com 'screen -r 12345'

nhưng điều này không được phép, trả về lỗi "Phải được kết nối với thiết bị đầu cuối." mà tôi đoán có nghĩa là về cơ bản "phải gọi lệnh này từ một vỏ tương tác".

Một ví dụ khác, tôi sử dụng rất nhiều máy móc tại nơi làm việc thường yêu cầu tôi sử dụng tài khoản dùng chung để có quyền làm một số việc nhất định (vâng tôi biết: ý tưởng tồi nhưng đừng đổ lỗi cho tôi, tôi đã không thiết lập mọi thứ cách) và họ thường có ksh làm vỏ mặc định. Tôi muốn đăng nhập, chuyển sang bash (hoặc zsh) và lấy nguồn .bash_profile (hoặc .zshrc) của tài khoản của riêng tôi. Điều này sẽ dễ dàng nếu tôi có thể thiết lập một phiên ssh tương tác truyền lệnh cho máy từ xa để chạy khi đăng nhập.

Tôi có một giải pháp rất bùn (và chưa được kiểm tra) trong đầu rằng tôi sẽ đăng, nhưng tôi hy vọng ai đó biết một cách tốt hơn.

CẬP NHẬT: đối với những người không nhận ra điều này, tôi không có kế hoạch làm tất cả những điều này bằng tay, vì vậy, bảo tôi mở một phiên tương tác và sau đó thực hiện bằng tay không thực sự giải quyết được gì.

CẬP NHẬT thứ 2: Để thử một lần nữa để làm rõ: Tôi đang cố chạy các lệnh (tùy ý) trên máy chủ (được chỉ định theo chương trình trên máy khách) nhưng sau đó mở phiên tương tác bị ảnh hưởng bởi bất kỳ điều gì được thực hiện bởi các lệnh lập trình đó.


echo "command" | ssh user@remote_host
laggingreflex

1
Bạn đã bỏ lỡ phần "không thoát" của câu hỏi? Tôi khá chắc chắn rằng điều này sẽ thoát sau khi lệnh kết thúc.
iconoclast

Câu trả lời:


23

Bạn có thể thử lệnh sau để khởi động bash và tìm nguồn hồ sơ của riêng bạn khi bạn ssh:

ssh  -t hostname "bash --rcfile ~user/.bashrc"

4
+1. Các -t chuyển đổi khắc phục vấn đề của người hỏi với screen cũng.
Patches

3
Điều này có thể được sử dụng với các lệnh tùy ý, mà không đóng kết nối? Nếu tôi cố gắng ssh -t www.dev "echo 'hi there'", kết nối được đóng ngay lập tức sau khi lệnh được thực thi.
iconoclast

10

Dựa trên câu trả lời của dogbane, một giải pháp hoàn chỉnh trông giống như:

ssh -t user@server 'cd /a/great/place; bash'

Ở đây tôi sử dụng -t để buộc phân bổ một thiết bị đầu cuối giả, cần thiết cho một vỏ tương tác. Sau đó, tôi thực thi hai lệnh trên máy chủ: đầu tiên là điều tôi muốn làm trước khi mở shell tương tác (trong trường hợp của tôi, thay đổi thư mục thành một thư mục cụ thể), và sau đó là chính vỏ tương tác. bash thấy rằng nó có một thiết bị đầu cuối giả và phản hồi tương tác.

Các trích dẫn duy nhất đảm bảo toàn bộ điều được chuyển đến máy chủ từ xa dưới dạng lệnh được chạy bởi trình bao mặc định của bạn.

Một lần nữa xin cảm ơn dogbane vì đã cung cấp manh mối cần thiết với -t. Tôi đã từng giải quyết vấn đề này với expect, đó chắc chắn là giết một con chuột bằng một khẩu pháo. (


2

Hãy thử giải pháp này.

echo "command" | ssh user@remote_host

Đăng nhập là tương tác và lệnh của bạn được thông qua như thể bạn gõ nó trên dòng lệnh tương tác. Phiên kết thúc như thể bạn đã gõ

ssh user@remote_host 'command'

3
Nếu phiên kết thúc sau khi lệnh hoàn thành, thì điều này không không phải trả lời câu hỏi. Toàn bộ điểm của lệnh sẽ được để lại với một phiên tương tác sau khi lệnh được thực thi, không phải chỉ để gửi lệnh đến máy chủ thông qua ssh.
iconoclast

Điều này ít nhất là tốt để mô phỏng một tương tác để lệnh thực thi, không sử dụng -t hoặc tập tin bash của riêng bạn. +1
laggingreflex

0

Sử dụng ssh -X để sử dụng các lệnh termINAL.

Ngoài ra - bạn có thể xâu chuỗi các cmds của mình như "ssh 'source ~ / .bashrc & amp; & amp; cd & amp; & amp; do'"


Nhưng sau khi toàn bộ chuỗi hoàn thành, tôi không còn một phiên tương tác, phải không? Nó vẫn đóng cửa, phải không?
iconoclast

Và bạn có quan tâm để giải thích về giải pháp termIO?
iconoclast

0

tại sao không cài đặt tách ra trên hệ thống từ xa và sử dụng:

ssh -t user@example.com "/home/user/bin/detach ls"

điều này sẽ chạy 'ls' và THEN để lại cho tôi một phiên tương tác? Điều gì sẽ xảy ra nếu, thay vì 'ls', tôi chạy 'nguồn .somefile' để lấy một số bí danh và hàm. Chúng sẽ có sẵn trong phiên tương tác của tôi hay nó sẽ được chạy dưới một phiên khác?
iconoclast

Không, do detach, ls không giữ phiên mở và sẽ ngắt kết nối mà không in đầu ra của ls nhưng nó vẫn chạy.
Dan D.

Tôi đang cố chạy các lệnh (tùy ý) trên máy chủ (được chỉ định theo chương trình trên máy khách) nhưng sau đó mở phiên tương tác bị ảnh hưởng bởi bất kỳ điều gì được thực hiện bởi các lệnh lập trình đó. Vì vậy, nếu tôi hiểu bạn chính xác, điều này không giúp tôi.
iconoclast

0

Câu trả lời của laggingreflex đã gần ... Tôi sẽ thay đổi nó như sau:

echo "command\n$(cat -)" | ssh user@remote_host

Thật không may, bạn có thể không thích cách làm việc đó, vì "mèo" đệm các dòng mà nó viết cho thiết bị xuất chuẩn ... Nếu chúng ta tạo một tập lệnh có tên là "echo-cat" trông giống như thế này:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

chúng ta sẽ nhận được kết quả tương tự mà không cần đệm:

echo-cat "command" | ssh user@remote_host

Điều đó có thể sẽ giúp bạn tiến gần hơn đến mục tiêu của bạn ...


0

Điều này là bùn, và chưa được kiểm tra, nhưng tôi nghĩ nó nên hoạt động.

Tạo tập lệnh có tên (ví dụ) bộ khởi động từ xa có đối số được trích dẫn sau đối số người dùng @ host:

remote-starter user@example.com 'some-command.sh arg1 arg2'

Tập lệnh này trước tiên phải lưu lệnh được trích dẫn (không có dấu ngoặc kép) trong tệp có tên (ví dụ:) .onetime trên máy từ xa, rồi chạy lệnh ssh thông thường, lần này không chuyển bất kỳ lệnh nào để chạy trên máy từ xa. (Nếu chạy ssh user@example.com từ trong tập lệnh, nó có thể hoạt động để chạy exec ssh user@example.com.)

Để làm việc này, máy từ xa phải nguồn .onetime từ .bash_profile hoặc .zshrc hoặc bất cứ điều gì. Sau khi chạy .onetime, nó nên xóa .onetime, vì vậy tệp không được chạy vào lần sau khi bạn đăng nhập thường xuyên.

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.