Сценарий оболочки: SSH к удаленной машине, затем выход: «выход» не работает

52897
Marius Hofert

У меня есть сценарий оболочки следующего типа:

#!/bin/bash  ssh mylogin@myremotemachine.com echo "Hi" exit 

Я запускаю его локально, чтобы что-то сделать на удаленном сервере (обозначается как «echo« Hi »»). Однако, когда я запускаю его, я вижу подсказку на удаленном сервере, поэтому команда 'exit' не выполняется. Когда я вручную набираю «exit» в удаленном приглашении, я вижу, что «Соединение с myremotemachine.com» закрыто, а затем «Привет». Как я могу настроить скрипт оболочки таким образом, чтобы он правильно выходил и отображал (локальное) приглашение, из которого я его выполнил?

https://unix.stackexchange.com/questions/89747/ssh-exits-after-quit-case-in-bash-script и ssh и shell через ssh: как выйти? кажутся немного связанными, но я не мог приспособить идеи, представленные там.

ОБНОВИТЬ

Следующая, не очень минимальная версия приводит к Unmatched '..

#!/bin/bash  date=`date "+%Y-%m-%d"` rsync -acxzP --delete --link-dest=/u3/mylogin/backup/old_backup /home/mylogin mylogin@myremotemachine.com:/u3/mylogin/backup/$date\_backup ssh mylogin@myremotemachine.com bash -c "' rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup exit '" 

Если я уберу двойные кавычки в этом фрагменте, я получу: bash: -c: option requires an argumentиdate: Undefined variable.

2

4 ответа на вопрос

7
R J

Это должно решить вашу проблему.

ssh mylogin@myremotemachine.com << HERE rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup HERE 

Или вы можете сделать следующее. Поместите все команды, которые вы хотите запустить на удаленном хосте, в отдельный скрипт. Дайте ему имя как remote.sh

Теперь запустите следующее

ssh mylogin@myremotemachine.com 'bash -s' < /path/to/remote.sh 

Где удаленный .sh содержит.

rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup 
Привет, RJ, спасибо за помощь. Я предпочитаю первое решение (я знал о втором). Тем не менее, я получаю `Псевдо-терминал не будет выделен, потому что stdin не является терминалом. Предупреждение: нет доступа к tty (неверный дескриптор файла). Таким образом, в этой оболочке нет управления заданиями. Но команды выполняются, как и ожидалось. Marius Hofert 10 лет назад 1
Привет Мариус. Это дружеское напоминание от ssh о том, что выполняется сценарий под заданием, у которого нет доступа к TTY, вместо обычного ожидаемого двоичного файла. Поэтому вы не можете прервать его с помощью Ctrl + c или приостановить его с помощью Ctrl + z или других интерактивных команд. Это безвредно и может быть безопасно проигнорировано. R J 10 лет назад 1
хорошо спасибо. Это хорошее решение. Marius Hofert 10 лет назад 0
1
barlop

Ты можешь сделать

$ssh user@comp echo abc<ENTER>

затем он запустит эту команду (выводит abc) и завершит работу

Спасибо! Это эквивалентно добавлению символа новой строки в конце скрипта для имитации ввода каретки? Иногда все работает даже без этого. Когда это обязательно? У меня есть вопрос относительно этого: https://unix.stackexchange.com/questions/362203/when-do-i-need-a-carriage-return-at-the-end-of-my-job-script-submitted -по-SSH. Будет красиво, если бы вы могли объяснить это там. Sibbs Gambling 7 лет назад 0
@SibbsGambling Я не уверен, что вы неправильно поняли .. означает нажать клавишу ввода .. Новые строки в конце скрипта, я не уверен, я не так много использую * nix. barlop 7 лет назад 0
1
Ctark

Несмотря на то, что ответ «barlops» правильный, я думаю, что мы можем расширить его, чтобы сделать его более понятным. Поскольку вы, похоже, используете скрипт, я бы предложил что-то вроде этого:

#!/bin/bash  ssh mylogin@myremotemachine.com "echo Hi\!" 

Дополнительное чтение: я также предлагаю вам также изучить специальные символы и, когда вам нужно их избежать, поскольку bash будет автоматически анализировать восклицательные знаки, когда они заключены в двойные кавычки. Вы можете решить это, используя одинарные кавычки или символ обратной косой черты, чтобы «убежать» от него.

Редактировать:

#!/bin/bash date=`date "+%Y-%m-%d"` rsync -acxzP --delete --link-dest=/u3/mylogin/backup/old_backup /home/mylogin mylogin@myremotemachine.com:/u3/mylogin/backup/$date\_backup ssh mylogin@myremotemachine.com ' date=`date "+%Y-%m-%d"` rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup ' 

Когда я попробовал упрощенную версию, переменная даты работает без проблем, возможно, это исправит проблему bash -c, которая у вас возникла. Также выход не нужен в конце, когда последняя команда выполняется, сессия ssh автоматически закрывается.

Привет Ctark, спасибо за помощь. В этом нет специальных символов. Очевидно, что 'echo' здесь - лишь минимальный пример; Существуют различные строки кода, которые должны выполняться удаленно. Таким образом, я не уверен, насколько эта «запись всего в одну строку» должна помочь ... действительно, есть несколько строк кода Marius Hofert 10 лет назад 0
... но на самом деле ты прав. Если я помещу все в одну строку, «выход» работает. Хммм ... но сценарий больше не читается :-( можно ли использовать фигурные скобки или какую-то группировку? Marius Hofert 10 лет назад 0
В этом случае я бы предложил эту ссылку: http://www.unixmantra.com/2014/03/a-simple-way-to-send-multiple-line-commands-over-ssh.html Кажется, в основном, что ты спрашиваешь. (Я мог бы скопировать вставить, но там много информации, и она поможет вам понять, ПОЧЕМУ это работает, так что вы тоже учитесь!) Ctark 10 лет назад 1
Он содержит много информации, спасибо. Но это не предполагает «общего лучшего» подхода. Подход, основанный на `EOF`, не работал для меня (те же причины, что и в приведенной вами ссылке). Затем я попробовал подход "bash -c". Но если я инкапсулирую код в "'...", как предложено, я получу 2x `Unmatched' .`. Если использовать только одну пару кавычек (одинарную или двойную), я получаю `bash: -c: опция требует аргумента`. Код выполнен, поэтому мы близки :-) Marius Hofert 10 лет назад 0
Самый простой способ - просто использовать ssh с одинарными кавычками, НО, если у вас есть другие одинарные кавычки в оставшейся части скрипта, который вы хотите использовать, тогда он испортится. Если вы можете изменить все одинарные кавычки в скрипте, который вы хотите запустить, на двойные кавычки, то просто: ssh $ host 'строка 1 строка 2 строка 3 "некоторые параметры" В конце этой статьи автор говорит о попытке использовать одиночные цитаты, но, похоже, это не очень нравится, и он не говорит о резолюции. В основном, если вам не нужны переменные или одинарные кавычки, вы можете просто использовать первый пример. Ctark 10 лет назад 1
Подход `... batch -c` является наилучшим (поскольку он также решает еще одну незначительную проблему, которая возникла у меня со сценарием). Тем не менее, наблюдение остается: если я напишу операторы в разных строках, я получу «Непревзойденные» .` ошибки / предупреждения. Только если я напишу их в одной строке (`;` -separated), тогда это полностью работает. Странно (?) Как это работает на сайте, на который вы указываете. Marius Hofert 10 лет назад 0
Можно ли размещать разные строки, похоже, что некоторые из них используют в них одинарные кавычки. Если они это сделают, это то, где вы получаете ваши непревзойденные ошибки. Если вы используете точки с запятой, то у вас нет открывающей / закрывающей одинарной кавычки. Я не могу больше, пока не увижу код, который вы используете. Ctark 10 лет назад 1
Привет, я обновил оригинальный пост с не очень минимальной версией. Как вы можете видеть, это по сути скрипт для резервного копирования на удаленную машину через `rsync`. Фактическая команда `rsync` немного сложнее, но это не должно играть никакой роли. Marius Hofert 10 лет назад 0
Извлеките двойные кавычки из начала и конца, сделав это: `ssh mylogin@myremotemachine.com bash -c 'rm -f / u3 / mylogin / backup / old_backup ln -s $ date \ _backup / u3 / mylogin / backup / old_backup exit '`Тестируйте с помощью чего-то простого, если это начинает работать, затем добавляйте вещи до тех пор, пока они не сломаются, и переходите оттуда. Ctark 10 лет назад 0
Если я сделаю это (и получу соответствующие переводы строк; см. Обновление выше), я получу `bash: -c: опция требует аргумент` и` date: Undefined variable`. Marius Hofert 10 лет назад 0
Если ваш обновленный скрипт - это все, что вы делаете, можете ли вы переместить переменную даты в ssh и удалить bash -c? Смотрите мой обновленный ответ, что я имею в виду. Ctark 10 лет назад 0
Когда я перемещаю `date`" внутрь ", я получаю` date: Undefined variable`. Поскольку это была проблема с оболочкой, я включил выражение `bash` прямо перед переменной` date` (чтобы перейти на bash, чтобы определить `date`), но затем я получил` bash: -c: option требует аргумента`. Marius Hofert 10 лет назад 0
Даже если вы нашли другой способ, обновленный ответ для всех, кто сталкивается с этим. причина, по которой вы получили неопределенную переменную, связана с тем, что команда rsync использует date, поэтому она нужна вам как внутри, так и вне скрипта ssh (если вы не используете bash -c и если у вас возникают другие проблемы). Рад, что вы наконец-то нашли решение, которое сработало, извините, в моем решении все еще были ошибки. Ctark 10 лет назад 1
1
Kamil

Может быть, у вас нет новой строки в конце скрипта?

Если LFпосле выхода нет пустой строки (точно - символа перевода строки) - ваш скрипт не будет "нажимать" ввод программно.

Привет, спасибо за помощь, я проверил сценарий, и у меня там были две новые строки, так что это не проблема. Marius Hofert 10 лет назад 0
У меня есть вопрос относительно этого: https://unix.stackexchange.com/questions/362203/when-do-i-need-a-carriage-return-at-the-end-of-my-job-script-submitted -по-SSH. Будет красиво, если бы вы могли объяснить это там. Sibbs Gambling 7 лет назад 0

Похожие вопросы