как запустить туннель в фоновом режиме как часть сценария оболочки

653
abbood

Я постоянно запускаю эти две команды, чтобы подключиться к моему экземпляру rds в aws, защищенном брандмауэром (поэтому я туннелирую через экземпляр ec2), вот так:

Команда 1: открыть туннель (запустить в фоновом режиме)

ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub & 

Команда 2: подключиться к БД через туннельный порт:

PGPASSWORD=password psql dbname -U user -h ip_address -p port; 

это потрясающе, но я хотел бы объединить их в одну функцию. Но у меня ничего не получалось

попытка 1: запустить без второстепенных вещей:

function db() { ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub & PGPASSWORD=password psql dbname -U user -h ip_address -p port; } 

просто говорит мне это:

$proddb [1] 62924 psql: could not connect to server: Connection refused Is the server running on host "127.0.0.1" and accepting TCP/IP connections on port 6666? 

хотя начальная команда выполняется в фоновом режиме:

ps aux | grep host (standard input):435:abdullah 62924 0.0 0.0 4315660 5828 s006 S 3:06PM 0:00.03 ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub 

и если я сразу же запускаю следующую команду после нее .. я подключаюсь к БД просто отлично!

PGPASSWORD=password psql dbname -U user -h ip_address -p port; user=> 

как мне сделать эту работу?

1

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

2
A.B

Первая команда не успела установить туннель при запуске второй команды, что дало «Отказ в соединении».

Просто не используйте, &а используйте вместо этого параметр -f:

-f
Запрашивает ssh перейти в фон непосредственно перед выполнением команды. Это полезно, если ssh собирается запрашивать пароли или парольные фразы, но пользователь хочет сделать это в фоновом режиме. Это подразумевает -n. Рекомендуемый способ запуска программ X11 на удаленном сайте - это что-то вроде ssh -f host xterm.
Если для параметра конфигурации ExitOnForwardFailure установлено значение «да», клиент, запущенный с параметром -f, будет ожидать успешного установления всех переадресаций с удаленного порта, прежде чем перейти в фоновый режим.

Собрав все это вместе, замените строку ssh в функции:

ssh -o ExitOnForwardFailure=yes -f -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub 

таким образом, запуск функции несколько раз, не оставит (несколько-1) бесполезный запуск SSH.

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

ssh -o ExitOnForwardFailure=yes -f -L port:host:5432 user@$ip -i ~/.ssh/key.pub sleep 15 
Отличный ответ .. но не могли бы вы объяснить `|| : `часть или это опечатка? abbood 6 лет назад 0
Если вы установите параметр оболочки `-e` где-нибудь, сбой отменит все. `:` is no-op (более короткая команда `true`). так что используя `|| : `construct только локально отключает` -e`. Ожидается, что ssh потерпит неудачу при втором вызове, потому что прежний ssh ​​все еще работает (он разветвился как демон и не умрет). в любом случае, возможно, это бесполезно, возможно, `-e` уже отключен в функции. также возможно заменить -N короткой командой сна: ssh все равно будет ждать окончания использования туннеля перед выходом A.B 6 лет назад 0
Что произойдет, если первый вызов потерпит неудачу? Т.е. мои туннельные учетные данные недействительны? Будет ли это немедленно прервать все? abbood 6 лет назад 0
pgsql жаловался бы как раньше A.B 6 лет назад 0
В любом случае я удалю это `|| : `. Это не очень полезно и сбивает с толку людей, читающих ответ A.B 6 лет назад 0
@abbood добавил альтернативный вариант A.B 6 лет назад 0