С ssh, как вы можете запустить команду на удаленной машине без выхода?

29

Обычно, если вы передаете команду 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
Вы пропустили "без выхода" часть вопроса? Я совершенно уверен, что это завершится после завершения команды.
иконоборец

Ответы:

26

Вы можете попробовать следующую команду, чтобы запустить 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 видит, что имеет псевдо-терминал, и отвечает в интерактивном режиме.

Одинарные кавычки гарантируют, что все это передается на удаленный сервер в качестве команды, которая будет запущена вашей оболочкой по умолчанию.

Еще раз спасибо Dogbane за предоставление необходимой подсказки с -t. Я имел обыкновение решать эту проблему expect, которая определенно убивает мышь из пушки. (:

user1179239
источник
2

Попробуйте это решение.

echo "command" | ssh user@remote_host

Логин является интерактивным, и ваша команда передается так, как если бы вы вводили ее в интерактивной командной строке. Сеанс заканчивается, как если бы вы набрали

ssh user@remote_host 'command'
user210540
источник
3
Если сеанс завершается после завершения команды, это не отвечает на вопрос. Весь смысл команды заключается в том, что после выполнения команды нужно оставить интерактивный сеанс, а не просто отправлять команды на серверы ssh.
иконоборчество
Это, по крайней мере, хорошо для симуляции взаимодействия для выполнения команды без использования -tсобственного файла bash. +1
laggingreflex
0

Используйте ssh -X, чтобы использовать termIO cmds.

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

ethrbunny
источник
но после завершения всей цепочки у меня не осталось интерактивного сеанса, верно? Это все еще закрывается, верно?
иконоборчество
И не могли бы вы рассказать о решении termIO?
иконоборчество
0

почему бы не установить detach в удаленной системе и использовать:

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

Это глупо и не проверено, но я думаю, что это должно работать.

Создайте скрипт с именем (например) remote-starter, который принимает аргумент в кавычках после аргумента user @ 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, чтобы файл не запускался при следующем входе в систему.

иконоборец
источник