Запуск процесса по ssh, использующему удар и затем уничтожающему его на sigint

Я хочу запустить несколько заданий на различных машинах с помощью ssh. Если пользователь затем прерывает основной сценарий, я хочу закрыть все задания корректно.

Вот короткий пример того, что я пытаюсь сделать:

#!/bin/bash
trap "aborted" SIGINT SIGTERM
aborted() {
    kill -SIGTERM $bash2_pid
    exit
}

ssh -t remote_machine /foo/bar.sh &
bash2_pid=$!
wait

Однако процесс bar.sh все еще выполняет удаленную машину. Если я делаю те же команды в окне терминала, оно закрывает процесс на удаленном хосте.

Существует ли простой способ заставить это произойти, когда я запускаю скрипт удара? Или я должен заставить его войти в систему удаленной машины, найти правильный процесс и уничтожить его тот путь?

править: Кажется, что я должен пойти с опцией B, уничтожив remotescript посредством другого соединения SSH

Таким образом, не я хочу знать, как я получаю remotepid? Я попробовал что-то вроде:

remote_pid=$(ssh remote_machine '{ /foo/bar.sh & } ; echo $!')

Это не работает, так как это блокируется.

Как я ожидаю переменной, чтобы распечатать и затем "выпустить" подпроцесс?

12
задан getekha 21 July 2010 в 08:07
поделиться

2 ответа

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

Когда ssh подключен к вашему терминалу; ведет себя неплохо. Однако отсоедините его от своего терминала, и становится (как вы заметили) проблемой сигнализировать или управлять удаленными процессами. Вы можете закрыть ссылку, но не удаленные процессы.

Остается один вариант: использовать ссылку как способ для удаленного процесса получить уведомление о том, что ему необходимо завершить работу. Самый простой способ сделать это - использовать блокирующий ввод-вывод. Сделайте ввод удаленного чтения из ssh и когда вы хотите, чтобы процесс завершился; отправьте ему некоторые данные, чтобы удаленная операция чтения разблокировала и он мог продолжить очистку:

command & read; kill $!

Это то, что мы хотели бы запустить на удаленном компьютере. Мы вызываем нашу команду, которую хотим запустить удаленно; мы читаем строку текста (блоки до тех пор, пока не получим ее), и когда мы закончим, сигнализируем команде о завершении.

Чтобы отправить сигнал от нашего локального сценария на удаленный, все, что нам нужно сделать сейчас, это отправить ему строку текста. К сожалению, здесь Bash не предлагает много хороших вариантов. По крайней мере, если вы хотите быть совместимым с bash <4.0.

В bash 4 мы можем использовать сопроцессы:

coproc ssh user@host 'command & read; kill $!'
trap 'echo >&"${COPROC[1]}"' EXIT
...

Теперь, когда локальный сценарий завершается (не перехватывайте INT , TERM и т. Д.). Просто EXIT ) он отправляет новую строку в файл во втором элементе массива COPROC . Этот файл представляет собой канал, который подключен к stdin ssh , эффективно маршрутизируя нашу линию на ssh . Удаленная команда считывает строку, завершает чтение и уничтожает команду.

Перед bash 4 все стало немного сложнее, так как у нас нет сопроцессов. В этом случае нам нужно сделать конвейер самостоятельно:

mkfifo /tmp/mysshcommand
ssh user@host 'command & read; kill $!' < /tmp/mysshcommand &
trap 'echo > /tmp/mysshcommand; rm /tmp/mysshcommand' EXIT

Это должно работать практически в любой версии bash.

17
ответ дан 2 December 2019 в 06:44
поделиться

Вы можете рассмотреть возможность монтирования удаленной файловой системы и запуска сценария с главного блока. Например, если ваше ядро скомпилировано с fuse (можно проверить следующим образом):

/sbin/lsmod | grep -i fuse

Вы можете смонтировать удаленную файловую систему следующей командой:

sshfs user@remote_system: mount_point

Теперь просто запустите ваш скрипт на файле, расположенном в mount_point.

-1
ответ дан 2 December 2019 в 06:44
поделиться
Другие вопросы по тегам:

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