З допомогою ssh, як можна запускати команду на віддаленій машині, не виходячи з неї?


28

Зазвичай, якщо ви передаєте команду, щоб ssh так було

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

Ви отримуєте неінтерактивний сеанс, і ssh завершується, як тільки виконується команда (або сценарій, або будь-що інше). Як я можу отримати інтерактивний сеанс та ще запустити команду, яку я вказав із своєї локальної машини. Наприклад, я хотів би мати можливість відкрити екран і перезапустити певний екранний сеанс:

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

але це не дозволено, повертаючи помилку "Повинен бути підключений до терміналу." що я припускаю, що по суті означає "повинен викликати цю команду з інтерактивної оболонки".

Як інший приклад, я використовую тону машин на роботі, які часто вимагають від мене спільного облікового запису, щоб мати права робити певні речі (так, я знаю: погана ідея, але не звинувачуйте мене, я не налаштовував це на те, спосіб), і вони зазвичай мають ksh як оболонку за замовчуванням. Я хотів би увійти, перейти на bash (або zsh) та надати джерело .bash_profile (або .zshrc) мого облікового запису. Це було б легко, якби я міг встановити інтерактивний сеанс ssh і передати команду віддаленій машині для запуску при вході в систему.

Я маю на увазі дуже незрозуміле (і неперевірене) рішення, яке опублікую, але сподіваюся, що хтось знає кращий спосіб.

ОНОВЛЕННЯ: для тих, хто цього не усвідомлював, я не планую робити все це вручну, тому сказати мені відкрити інтерактивну сесію, а потім зробити це вручну, насправді нічого не вирішує.

2-е ОНОВЛЕННЯ: Щоб спробувати ще раз уточнити: я намагаюся запускати (довільні) команди на сервері (програмно вказані на клієнті), але потім відкриваю інтерактивну сесію, на яку впливає все, що робиться цими програмними командами.


echo "command" | ssh user@remote_host
laggingreflex

2
Ви пропустили частину питання "не виходячи"? Я впевнений, що це завершиться після завершення команди.
іконоборство

Відповіді:


25

Ви можете спробувати наступну команду, щоб запустити bash та створити власний профіль при ssh:

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

4
+1. -tПеремикач усуває проблему запитувач з screenа.
Патчі

3
Чи можна це використовувати з довільними командами, не закриваючи з'єднання? Якщо я спробую ssh -t www.dev "echo 'hi there'", з'єднання негайно закривається після виконання команди.
іконоборство

11

Спираючись на відповідь догбена, повне рішення виглядає так:

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

Тут я використовую, -tщоб примусити виділити псевдотермінал, необхідний для інтерактивної оболонки. Потім я виконую на сервер дві команди: спочатку те, що я хотів зробити перед відкриттям інтерактивної оболонки (у моєму випадку, зміною каталогу на певну папку), а потім самою інтерактивною оболонкою. bash бачить, що він має псевдотермінал і реагує інтерактивно.

Одиничні лапки забезпечують передачу всієї справи на віддалений сервер як команду, яку слід виконувати за допомогою стандартної оболонки.

Ще раз дякую собачці за надання необхідної підказки -t. Раніше я вирішував цю проблему expect, яка, безумовно, вбиває мишку гарматами. (:


2

Спробуйте це рішення.

echo "command" | ssh user@remote_host

Логін - інтерактивний, і ваша команда передається так, ніби ви ввели її в інтерактивний командний рядок. Сеанс закінчується так, ніби ви ввели

ssh user@remote_host 'command'

3
Якщо сеанс припиняється після завершення команди, це не відповідає на питання. Весь сенс команди повинен залишатися з інтерактивним сеансом після виконання команди, а не просто надсилати команди на сервери через ssh.
іконоборство

Це, принаймні, добре для імітації взаємодії для команди, що виконується, без використання -tчи власного файлу bash. +1
відставання рефлексу

0

Використовуйте ssh -X для використання termIO cmds.

Крім того, ви можете зв'язати свої cmds як "ssh 'source ~ / .bashrc && cd && do" "


але після завершення роботи всього ланцюжка у мене не залишається інтерактивного сеансу, правда? Він все ще закривається, правда?
іконоборство

А ви б хотіли детальніше розробити термін рішення?
іконоборство

0

чому б не встановити від’єднати на віддаленій системі та використовувати:

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

чи буде це запущено 'ls', а потім залишить мене з інтерактивним сеансом? Що робити, якщо замість 'ls' я запускаю 'source .somefile', щоб отримати псевдоніми та функції. Чи вони будуть доступні в моєму інтерактивному сеансі, або він буде працювати під іншим сеансом?
іконоборство

Ні, через те detach, lsщо не підтримує сеанс відкритим і від'єднається без друку виводу, lsале він все одно запуститься.
Ден Д.

Я намагаюся запускати (довільні) команди на сервері (програмно вказані на клієнті), але потім відкриваю інтерактивну сесію, на яку впливає все, що робиться цими програмними командами. Тож якщо я вас правильно зрозумів, це мені не допоможе.
іконоборство

0

Відповідь laggingreflex близька ... Я б змінив її так:

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

На жаль, вам, мабуть, не сподобається, як це працює, тому що "cat" буферизує рядки, які він пише для stdout ... Якщо ми створимо сценарій під назвою "echo-cat", який виглядає приблизно так:

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

ми отримаємо такий же результат без буферизації:

echo-cat "command" | ssh user@remote_host

Це, ймовірно, наблизить вас до вашої мети ...


0

Це хитро і неперевірено, але я думаю, що це має працювати.

Створіть сценарій з назвою (наприклад) віддаленого запуску, який приймає цитований аргумент після аргументу користувача @ host:

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

Цей скрипт повинен спочатку зберегти цитовану команду (без лапок) у файлі з назвою (наприклад) .onetimeна віддаленій машині, а потім виконати звичайну команду ssh, на цей раз не передаючи жодної команди, яку слід запустити на віддаленій машині. (Якщо запускається ssh user@example.com з сценарію, може працювати запуск exec ssh user@example.com.)

Щоб це працювало, віддалена машина повинна джерело .onetimeзі свого .bash_profile або .zshrc або будь-якого іншого. Після запуску .onetimeйого слід видалити .onetime, тому файл не запускається наступного разу, коли ви регулярно входите в систему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.