ssh и shell через ssh: как выйти?

22

Я запускаю удаленный скрипт через SSH так:

ssh user@ipaddress '~/my_script.sh'

Все идет хорошо, но как только скрипт завершен, соединение не закрывается. Я должен нажать CTRL-C, чтобы разорвать текущее соединение.

Я пробовал команду «exit» в «~ / my_script.sh», и она бесполезна. Я пробовал команду "logout" в ~ / my_script.sh и получаю сообщение:

logout: not login shell: use exit

...

Любая идея, как я мог бы сделать, чтобы автоматически и правильно закрыть SSH после завершения сценария?

(Модификация для уточнения :) Вот что внутри моего скрипта:

#!/bin/sh
path_sources_qas=/sources/QuickAddress/
path_qas_bin=/usr/bin/qas

umount_disque_qas()
{
  # Umount du disque 'qas' s'il n'avait pas été 'umount' :
  nom_disque_monte=`cat /etc/mtab | grep qas | awk '{ print $2}'`
  if [ "$nom_disque_monte" != "" ]
  then
    echo "For safety, umount : $nom_disque_monte"
    umount $nom_disque_monte
  fi

}

# Umount twice (we never know if a st***d guy mounted it twice) :
umount_disque_qas
umount_disque_qas

echo "--------------------------------"
echo "Install ISO quick address..."
nom_fichier_iso=`ls -t $path_sources_qas | awk '{if (NR==1) {print $1}}'`
echo "Mount disk $nom_fichier_iso..."
mount -o loop -t iso9660 $path_sources_qas/$nom_fichier_iso /mnt/qas
echo "Done."

# All the folders are like this :
# /usr/bin/qas/Data.old.10
# /usr/bin/qas/Data.old.11
# /usr/bin/qas/Data.old.12
# ...

echo "--------------------------------"
echo "Stopping QuickAdress server..."
cd $path_qas_bin/apps/
./wvmgmtd shutdown qaserver:2021
sleep 3
echo "Done."

# Get last number of the folder:
num_dernier_dossier_backup=`ls -Atd $path_qas_bin/Data.old* | awk '{if (NR==1) {print $1}}' | awk -F . '{print $NF}'`
# Add 1 :
let "num_dernier_dossier_backup += 1"
# Full name :
nom_dossier_backup=Data.old.$num_dernier_dossier_backup
echo "--------------------------------"
echo "Saving Data to $nom_dossier_backup..."
cd $path_qas_bin
mv Data $nom_dossier_backup
echo "Done."


echo "--------------------------------"
echo "Copying new folder Data..."
cd $path_qas_bin
cp -r /mnt/qas/Data .
echo "Done."

echo "--------------------------------"
echo "Deleting unused datas..."
cd $path_qas_bin/apps/
rm -f $path_qas_bin/Data/frxmos.dap
echo "Done."

echo "--------------------------------"
echo "Restart server..."
cd $path_qas_bin/apps/
./qaswvd &
sleep 3
echo "Done."
sleep 3

echo "--------------------------------"
echo "Check: server state: you should read 'OK':"
./wvmgmtd srvlist
echo "Done."

echo "--------------------------------"
echo "Check: active licences (only one here):"
./wvmgmtd licencelistread qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: counters: number of addresses left:"
./wvmgmtd counterinforead qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: Datasets avalaibles:"
./wvmgmtd datalistread current qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: "meters" for "licence by click":"
./wvmgmtd meterslistread current qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Removing virtual disk..."
umount_disque_qas
echo "Done."

echo "All done"
echo "Click 'Ctrl-C' to quit."

exit

Когда я запускаю его через SSH, он запускается и в конце я читаю «Все готово». так что это означает, что он достигает последних 2 строк .

Любая идея, как я мог сделать, чтобы закрыть автоматически и пр

Оливье Понс
источник
1
Что в сценарии?
Игнасио Васкес-Абрамс
@Olivier: Вы перенаправляете какие-либо порты (включая агент и X)? Соединение ssh закрывается, когда команда завершается и все TCP-соединения закрываются.
Жиль "ТАК - прекрати быть злым"
@Gilles: нет, я просто создаю оболочку для запуска скрипта, ничего не передается.
Оливье Понс
1
@Olivier: Если у вас есть ~/.ssh/config, попробуйте без него, и передайте параметры -a -x(и нет -o), чтобы sshубедиться, что пересылка не происходит. Если это все еще не работает, покажите содержимое сценария.
Жиль "ТАК - перестань быть злым"
@Olivier: запускает ли скрипт какую-либо фоновую работу, которую он может ожидать? К сожалению задания, похоже, ничего не возвращают в сценарии ssh. Пример: ssh <yourusername>@localhost '(ls; sleep 10 &); echo Done; jobs'отобразит список файлов, покажет готово и подождет 10 секунд, прежде чем вернуться.
asoundmove

Ответы:

19

Выход из сценария оболочки не работает, потому что он выходит из сценария, а не из оболочки. Для выхода из оболочки после завершения скрипта выполните

ssh user@ipaddress '~/my_script.sh && exit'

Это запустит скрипт и выйдет из оболочки.

Wuffers
источник
3
Это должно быть выход. Скрипт это оболочка.
Приостановлено до дальнейшего уведомления.
@ Денис: Это не работает для него, так что это может сработать.
Wuffers
2
@Г-н. Man: Ваша команда эквивалентна оригиналу, за исключением того, что она вынуждает оболочку существовать между sshdзапущенной оболочкой myscript.sh. Написанное exitвами будет действовать при выходе из скрипта, что не помогает. Единственное, как может работать ваше решение, - это если сценарий делает что-то странное, когда его родитель является, sshdи не делает этого странного, когда его родитель - оболочка.
Жиль "ТАК - перестань быть злым"
Как это не помогает? Выход закроет оболочку и завершит соединение, правильно? И разве это не то, что плакат хочет?
Wuffers
3
@MrMan: ~/my_script.sh && exitвыход, как только ~/my_script.shвыходит. Если сценарий оболочки не завершится, ваша команда все равно никогда не доберется до exitбиты. Так что это просто бесполезно.
Жиль "ТАК - перестань быть злым"
12

Соединение ssh остается открытым, когда завершается процесс, запущенный ssh ​​(здесь, оболочкой), если есть другие процессы, которые все еще используют его. Я не знаю точных правил, которым следует демон ssh, но соединение используется, по крайней мере, если стандартный вывод любого дочернего процесса все еще подключен к исходному каналу, предоставленному ssh. Для сравнения:

ssh somehost 'sleep 5 &'  # exits after 5 seconds
ssh somehost 'sleep 5 >/dev/null &'  # exits immediately seconds

Когда вы запускаете демон, вы должны закрасить его и закрыть его файловые дескрипторы. По крайней мере, используйте это:

./qaswvd </dev/null >/dev/null 2>/dev/null &

Вы можете добавить nohupвпереди; здесь это не будет иметь значения, но было бы полезно, если бы скрипт запускался из терминала. Многие программы, предназначенные для работы в качестве демонов, имеют параметры командной строки, которые позволяют им переходить в режим форка, закрывать файловые дескрипторы, игнорировать сигналы и другие тонкости. Проверьте в qaswvdдокументации, если она есть. Вы также можете исследовать утилиты «daemonizer».

Жиль "ТАК - перестань быть злым"
источник
Была такая же проблема, и это работает. Принятый ответ не работает.
Энди
5

Я видел этот пост, когда гуглил для разрешения той же ситуации. Хотя решить проблему @ Оливера уже поздно, поскольку принятый ответ явно не работает ни для ОП, ни для меня (не знаю, почему он принят), я все же хотел бы опубликовать собственное решение для будущего гуглера. Все просто: добавьте -fопцию в sshкоманду:

ssh -f user@ipaddress '~/my_script.sh'

РЕДАКТИРОВАТЬ

Эффект -fопции заключается в том, чтобы поместить sshв фоновом режиме, так что без добавления дополнительной опции возможно, что соединение все еще живо, даже если кажется, что оно разорвано. При желании можно обратиться к ответу, приведенному в другом посте на этом сайте.

Лео Фанг
источник
Внимание: эта (-f) не будет работать, если в исходном скрипте есть подсказки для ввода данных пользователем.
madD7
3

Как и Игнасио, мне любопытно узнать, что в твоем сценарии.

Возможно, вы могли бы попытаться сократить ваш скрипт до наименьшего возможного примера, который приводит к ошибке.

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

Если пустой скрипт вызывает у вас проблемы, вы можете изучить конфигурацию ssh, например, .bash_logout или некоторые другие, вызываемые при выходе, которые могут вызвать проблему?

asoundmove
источник
Спасибо за ваше предложение, теперь я добавил образец моего сценария в свой вопрос.
Оливье Понс
@Olivier: Вы добавили только не относящиеся к делу части вашего сценария. Опубликуйте сценарий (и инструкции по использованию, если необходимо), который позволит читателям воспроизвести вашу проблему . Упростите сценарий настолько, насколько это возможно, но не дальше.
Жиль "ТАК - перестань быть злым"
@ Жиль Спасибо. Я изменил свой вопрос и добавил весь сценарий. Надеюсь это поможет. Кажется, что проблема может быть в том, что я запускаю фоновый процесс ( строка «./qaswvd &» ). Может ли это быть источником проблемы?
Оливье Понс
1
@Olivier: Да, ваш основной процесс будет ждать остановки фонового процесса перед выходом. Если вы хотите, чтобы что-то продолжалось после выхода, вы можете попробовать nohup. Не уверен, что он работает с ssh, но попробуйте, это не повредит.
asoundmove
2

Вы можете, вероятно, использовать задания в вашем скрипте. Если это так, оболочка просто ждет, пока ваша работа будет завершена, и не хочет отсоединяться.

Я не собираюсь делать репосты, просто перешлю вам http://en.wikipedia.org/wiki/Nohup#Existing_jobs

Алексей Хилькевич
источник
Я изменил свой вопрос и добавил весь сценарий. Надеюсь это поможет. Кажется, что проблема может быть в том, что я запускаю фоновый процесс (строка «./qaswvd &»). Если вы правы, это может быть источником проблемы?
Оливье Понс
Процесс с задним фоном - это проблема, но nohupэто не проблема напрямую, поскольку на стороне сервера нет терминала: я думаю, что виновником является именно дескриптор открытого файла.
Жиль "ТАК - перестать быть злым"
Да, я думаю, что это проблема, вы можете попробовать это прокомментировать или применить хак по ссылке выше
Алексей Хилькевич
1

Вам нужно будет убить ваш родительский процесс из вашего скрипта.

kill -SIGHUP $PPID

OmnipotentEntity
источник
0

Проблема, скорее всего, в следующей строке.

./qaswvd &

Эта команда, вероятно, все еще выполняется и будет держать канал ssh открытым до тех пор, пока stdin и stdout & stderr не будут закрыты.

Используйте это вместо:

./qaswvd </dev/null >/dev/null 2>&1 &
edirks
источник