BASH создать подошву для SSH и продолжить с потоком программы

Я пытаюсь написать оболочку script, которая автоматизирует некоторые задачи запуска на основе моего местоположения (home/campusA/campusB). Я еду в университет и занимаюсь занятиями в двух разных университетских городках (следовательно, в кампусе A/campusB). Мое местоположение определяется, с какой беспроводной сетью я подключен. Для целей этого script мы можем предположить, что я буду подключен к одной из этих сетей при вызове script, а мой script знает, к какому я подключен, на основе вызова iwconfig.

Это то, что я хочу сделать:

cat file1 > file2 # always do this, regardless of where I am
if Im at home:
    start tweetdeck, thunderbird, skype

else if Im at campusA:
    activate the login script # I need to login on a webform before I get internet access. 
                              # I have written a script to automate this. 
                              # Wait for this script to finish before doing anything else
    myProg2 & # I want myProg2 running in the background until I shutdown my computer.

else if Im at campusB:
    ssh [email protected] # this is the problematic line
    myProg2 & # I want myProg2 running in the background until I shutdown my computer.

start tweetdeck, thunderbird
close the terminal with the "exit" command

Проблема в том, что беспроводная сеть campusB находится за брандмауэром, который предоставляет мне доступ в Интернет ТОЛЬКО после того, как я успешно прошел ssh [email protected]. После успешного ssh мне нужно, чтобы окно терминала было активным, чтобы удерживать доступ в Интернет. Если я закрою окно терминала, я потеряю доступ в Интернет (это плохо).

Когда я пытаюсь сделать только ssh [email protected], script останавливается, потому что я не выхожу из команды ssh. Я не могу ^C выйти из него, а это значит, что остальная часть script никогда не выполняется. У меня также такая же проблема, если я просто закрываю окно терминала, пытаясь убить сеанс ssh.

Некоторые поисковики привезли меня в subshell, который я либо неправильно использую, либо не могу использовать для решения моей проблемы. Итак, как мне решить эту проблему? Я был бы признателен за любую помощь - я был в этом какое-то время и не могу найти ничего полезного. Если это имеет значение, я бы предпочел не хранить мой пароль ssh в script

Кроме того, амперсандинг вызова ssh (ssh [email protected] &), похоже, не приносит пользы (может кто-нибудь объяснить, почему?)

Заранее благодарю

ИЗМЕНИТЬ

Я должен уточнить, что ssh-соединение должно быть активным, чтобы у меня был доступ в Интернет. Таким образом, когда я закрываю окно терминала, мне нужно, чтобы ssh-соединение все еще было активным.

Ответ 1

У меня был script, который зацикливался на 6 серверах, вызывая через ssh в фоновом режиме. В 1 части script было применено неверное поведение поставщика; приложение не "отпустило" соединение должным образом. (другие части script с использованием ssh в фоновом режиме работали нормально).

Я обнаружил, что использование ssh -t -t устраняет проблему. Может быть, это тоже поможет вам. (товарищ по команде нашел это в Интернете, и мы потратили так много времени, я никогда не возвращался, чтобы прочитать статью, которая предложила это. На странице руководства в нашей системе не было намека на то, что это возможно)

Надеюсь, что это поможет.

Ответ 2

Вот несколько соображений, которые могут помочь.

Суб-оболочки

Sub-shells развивает новые процессы, но не возвращает управление вызывающей оболочке. Если вы хотите разветкить суб-оболочку для выполнения этой работы, вам нужно добавить & в строку.

(ssh [email protected]) &

Но это не выглядит убедительной причиной использования под-оболочки. Если у вас были команды с номерами, которые вы хотели выполнить по порядку друг от друга, но параллельно с вызывающей оболочкой, возможно, это было бы полезно. Например...

(dothis.sh; thenthis.sh; andthislastthingtoo.sh) &

Разветвление

Я не уверен, почему & не работает для вас, но может быть стоит посмотреть nohup, Это делает команду "иммунной" проверять сигналы.

nohup ssh [email protected] (попробуйте с и без & в конце)

Пароли

Не хранить пароли в script необходимо для любой автоматизации ssh. Вы можете выполнить это с использованием криптографии с открытым ключом, которая является неотъемлемой чертой ssh. Я не буду вдаваться в подробности здесь, потому что есть number of отличный ресурсы во всех средах с настройкой этого. Я настоятельно рекомендую исследовать это дальше.

Если вы идете по этому маршруту, я также предлагаю запустить ssh в "пакетном режиме", который отключит запрос пароля и автоматически отключится от сервера, если он перестанет отвечать на запросы через 5 минут.

ssh -o 'BatchMode=yes' [email protected]

Постоянство

Затем, если вы хотите сохранить соединение, запустите некоторый глупый цикл в bash!:)

ssh -o 'BatchMode=yes' [email protected] "while (( 1 == 1 )); do sleep 60; done"

Ответ 4

Наличие ssh с псевдо-tty в фоновой оболочке

В дополнение к ответу @shellter я хотел бы сделать некоторую точность:

где @shelter сказал:

В man-странице нашей системы не было намека на то, что такая возможность возможна

В моей системе (Debian 7 GNU/Linux), если я ударил:

man -Pcol\ -b ssh| grep -A3 '^ *-t '

Я мог бы читать:

     -t      Force pseudo-tty allocation.  This can be used to execute arbi‐
             trary screen-based programs on a remote machine, which can be
             very useful, e.g. when implementing menu services.  Multiple -t
             options force tty allocation, even if ssh has no local tty.

Да: Множество опций -t принудительно назначают tty, даже если ssh не имеет локального tty.

Это означает: если вы дистанционно запускаете инструмент, который требует доступа к pseudo terminal (pty like /dev/pts/0), вы можете запустить их с помощью -t.

Но это будет работать только в том случае, если ssh запускается из консоли консоли (ака с собственным pty). Если вы планируете запустить их, это консольный сеанс без консоли, например фоновые сценарии, вы можете использовать Multiple -t для принудительного распределения псевдо-tty из ssh.

Несколько ssh-оболочек на одном ssh-соединении

В дополнение к ответам @tommy и @geekosaur, я бы сделал некоторую точность:

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

Как только соединение установлено, ssh может (и знает, как) использовать их для управления множеством вещей в этом соединении:

  • -L позволяет управлять удаленными TCP-соединениями с локальными компьютерами/сетью. (полный синтаксис: -L localip:localport:distip:distport), где localip может быть указан, чтобы другие хосты из одного и того же локального домена могли получить доступ к одному и тому же привязке tcp, а distip мог использовать любой хост из удаленной сети (не только localhost): -L192.168.1.31:8443:google.com:443 разрешить любому хосту из локального домена доходить до Google через ваш хост: http://192.168.1.31:8443

  • -R То же замечание обратным образом!

  • -M Сообщите ssh, чтобы открыть локальный unix-сокет для связывания следующих консолей ssh. Просто откройте два оконечных окна. Сначала в обоих окнах нажмите: ssh somewhere, чем нажмите netstat -tan | grep :22 или netstat -tan | grep 192.168.1.31:22 (предполагая, что 192.168.1.31 - ваш IP-адрес вашего хоста)

    Чем сравнить все ваши сеансы ssh и в первом терминале, нажмите: ssh -M somewhere, а во-вторых, просто ssh somewhere. вы можете видеть во втором терминале:

    $ ssh somewhere
    + ssh somewhere
    Last login: Mon Feb  3 08:58:01 2014 from elsewhere
    

    Если теперь вы нажмете netstat -tan | grep 192.168.1.31:22 (на любом из двух запущенных ssh-сеансов;), вы должны увидеть, что существует только одно tcp-соединение.

    Этот вид функций можно использовать в сочетании с -L и, возможно, с некоторыми sleep 86399...

    Чтобы обойти маршрутизатор-убийца tcp, который закрывает каждое неактивное TCP-соединение с более чем 120 секунд, я запускаю:

    ssh -M somewhere 'while :;do uptime;sleep 60;done'
    

    Это гарантирует, что соединение останется включенным, даже если я не нажимаю клавишу более двух минут.

Ответ 5

Проблема с & заключается в том, что ssh теряет доступ к своему стандартному вводу (терминалу), поэтому, когда он переходит к чтению чего-либо для отправки на другую сторону, он либо получает ошибку, либо выходит, либо является kill ed системой с SIGTTIN, которая неявно приостанавливает ее. Для этого используются опции -n и -f: -n указывает, что он не использует стандартный ввод, -f сообщает ему, что он настраивает любые необходимые туннели и т.д., Затем закрывает поток терминала.

Таким образом, лучший способ сделать это, вероятно, сделать

ssh -L 9999:localhost:9999 -f host & # for some random unused port

а затем вручную удалите ssh перед выходом из системы. С другой стороны,

ssh -L 9999:localhost:9999 -n host 'while :; do sleep 86400; done' </dev/null &

(Перенаправление - убедиться, что SIGTTIN не произойдет.)

Пока вы на нем, вы можете сохранить идентификатор процесса и закрыть его из .logout/.bash_logout:

ssh -L 9999:localhost:9999 -n host 'while :; do sleep 86400; done' < /dev/null & echo $! >~.ssh_pid; chmod 0600 ~/.ssh_pid

и в .bash_logout:

if test -f ~/.ssh_pid; then
  set -- $(sed -n 's/^\([0-9][0-9]*\)$/\1/p' ~/.ssh_pid)
  if [ $# = 1 ]; then
    kill $1 >/dev/null 2>&1
  fi
  rm ~/.ssh_pid
fi

Дополнительный код пытается избежать того, что кто-то саботирует ваш ~/.ssh_pid, потому что я профессиональный параноик.

(Код не проверен и может иметь тире)

Ответ 6

Прошло некоторое время с тех пор, как я использовал ssh, и я не могу проверить его прямо сейчас, но вы попробовали ключ -f?

ssh -f [email protected]

На странице man написано, что это фоны ssh. Не уверен, почему & не будет работать, но я предполагаю, что он интерпретирует его как команду для запуска на удаленной машине.

Ответ 7

Может быть, экран + ssh тоже будет соответствовать счету?

Что-то вроде:

screen -d -m -S sessionName cmd

screen -d -m -S sessionName cmd &

# reconnect with
screen -r sessionName