Как заставить экран автоматически подключаться к текущему ssh-агенту при повторном подключении к существующему экрану?

48

Если вы запускаете сеанс экрана во время работы ssh-agent (из пересылки ssh -A agent), доступ к ssh-agent работает нормально. Однако, если вы отсоединяетесь от этого сеанса, выходите из системы, снова входите в систему (с переадресацией ssh-agent) и повторно подключаетесь к сеансу экрана, доступ по ssh-agent не работает.

Как это можно исправить?

Der Hochstapler
источник

Ответы:

41

1) В вашем скрипте SSH rc (~ / .ssh / rc) вы установите символическую ссылку из канонического местоположения на «текущий» SSH_AUTH_SOCK. Вот как я это делаю в bash (содержимое ~ / .ssh / rc):

#!/bin/bash
if test "$SSH_AUTH_SOCK" ; then
    ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

(и убедитесь, что chmod 755 ~ / .ssh / rc). «Тест» предназначен только для предотвращения отображения ошибки, если вы не запускаете ssh-agent (т.е. вы используете ssh без -A). Вторая половина этой команды устанавливает символическую ссылку в каноническом месте, которая обновляется до «реального» SSH_AUTH_SOCK во время входа в систему. Это не зависит от использования оболочки в ssh или непосредственного вызова команды, также работает с "ssh -t screen -RRD".

Примечание: существование ~ / .ssh / rc меняет поведение sshd. Примечательно, что он не будет называть xauth. Смотрите man sshd для получения дополнительной информации, и как это исправить.

Кроме того, вы не должны использовать «-v» с ln, как только он сломает rsync-over-ssh со следующей диагностикой:

$ rsync -n addr.maps.dev.yandex.net: .
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(173) [Receiver=3.0.7]

2) В вашем .screenrc вам просто нужно переопределить SSH_AUTH_SOCK для канонического местоположения:

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

Обратите внимание, что вы используете setenv независимо от того, какую оболочку вы используете; Я думаю, что setenv - это экранный синтаксис, а не оболочка.

Решение изначально адаптировано из этого поста , которое не работает, но имеет правильную идею.

apinstein
источник
Это предполагает, что вы сначала войдите, а затем начальный экран. Правильно?
InnaM
1
Как это может быть по-другому? Как бы вы начали экран без входа в систему?
1
Вы правы. Вопрос был сформулирован глупо. Но вам нужно авторизоваться, запустить оболочку и оттуда стартовый экран? Я часто делаю что-то вроде "ssh -t some.machine screen -R".
InnaM
1
Ах хорошо. Ну, я только что попробовал это, и это не работает (т.е. ssh-agent не подключен). Я предполагаю, что ssh не устанавливает соответствующие сокеты при использовании таким способом. Может быть, еще один аргумент - Фу мог бы это очистить?
SSH устанавливает сокеты, просто не запускает оболочку. Но этот совет настолько полезен, что я думаю, что могу просто изменить свои привычки.
innaM
23

Я думаю, что это работает как упрощение ответа @ sandip-bhattacharya. Поместите это в свой ~/.bashrcфайл и запускайте команду экспорта во всех текущих сеансах экрана.

if [ -S "$SSH_AUTH_SOCK" ] && [ ! -h "$SSH_AUTH_SOCK" ]; then
    ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

Это гласит «если $SSH_AUTH_SOCKэто сокет ( -S), а не символическая ссылка ( ! -h), создайте новую символическую ссылку по известному пути. Во всех случаях переопределите, SSH_AUTH_SOCKчтобы указать на известный путь.

В ! -hизбегает создания циклической ссылки , если вы запустите это несколько раз.

Кроме того, если вы используете byobu, он делает это автоматически, без необходимости редактировать файлы конфигурации.

Единственная ошибка, которую я обнаружил в этом ( byobuимеет ее тоже), - если вы откроете второе ssh -Aили ForwardAgentсоединение, оно перезапишет первый сокет, и если вы закроете второе соединение до первого, вы потеряете свой единственный хороший сокет.

Коллин Андерсон
источник
1
Это работает tmuxтакже.
Даг Хёйдал
Прекрасно работает, но ломается при использовании удаленно смонтированных домашних папок. В этом случае используйте ~/.ssh/ssh_auth_sock_"$(hostname)"для вашей символической ссылки. Он будет хранить отдельные сокеты аутентификации для каждого хоста.
Киббер
4

«ssh -t some.machine screen -R» не будет запускать bash и, следовательно, не будет запускать сценарий .bash_profile, в котором создается символическая ссылка.

Вы можете попробовать: ssh -t some.machine bash -c "screen -R"

(конечно, если вы используете bash в качестве оболочки)

Изменить: этот «ответ» на самом деле комментарий к первому ответу, приведенному выше :)

Сообщество
источник
«Первый ответ, данный выше» ничего не значит, так как ответы меняются в порядке, в котором они голосуются и т. Д. Пожалуйста, включите ссылку «Поделиться» из ответа, на который вы ссылаетесь, поскольку это не изменится.
Rjmunro
3

Я думаю, что вам нужно Autossh. Я использую его уже много лет, и в сочетании с экраном он делает все мои терминальные сессии полностью переносимыми и прозрачными. Я просто закрываю lappy, перехожу на новое место, открываю lappy и все мои экраны и вложенные экраны подключаются автоматически. Я даже не думаю об этом больше.

http://www.linux.com/archive/feature/134133

это основа ... Я ruby ​​создал сценарий lil для автоматизации процесса в моем .screenrc для данного хоста. (также выполняет пересылку по ssh, поэтому во всех этих разных местах я могу туннелировать свое соединение через мои серверы)

в дистрибутиве autossh должна быть программа rscreen (и ... есть!)

#!/bin/sh                                                                       
#
# sample script to use autossh to open up a remote screen
# session, or reconnect to an existing one. 
#
# $Id: rscreen,v 1.4 2002/05/07 17:54:13 harding Exp $
#
if [ "X$1" = "X" ]; then
    echo "usage: `basename $0` <host>"
    exit 1
fi

if [ "X$SSH_AUTH_SOCK" = "X" ]; then
    eval `ssh-agent -s`
    ssh-add $HOME/.ssh/id_rsa
fi

#AUTOSSH_POLL=600
#AUTOSSH_PORT=20000
#AUTOSSH_GATETIME=30
#AUTOSSH_LOGFILE=$HOST.log
#AUTOSSH_DEBUG=yes 
#AUTOSSH_PATH=/usr/local/bin/ssh
export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME 

autossh -M 20004 -t $1 "screen -e^Zz -D -R"

Это должно помочь с проблемами SSH / экрана

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

chiggsy
источник
2

Вот метод, который я использую:

SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK) ; eval $SOCK ; export SSH_AUTH_SOCK
DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY) ; eval $DISP ; export DISP

Обычно я настраиваю псевдоним или функцию оболочки с помощью этих команд:

function ssh-screen-auth() {
  SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK)
  eval $SOCK
  export SSH_AUTH_SOCK
  DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY)
  eval $DISP
  export DISPLAY
}

Возможно, вам придется адаптировать регулярное выражение « screen - (r | DR) » к точным командам, которые вы используете для повторного подключения экрана.

  • Первая строка читает переменную окружения SSH_AUTH_SOCK в пространстве процесса только что набранной вами команды " screen -r " и обновляет значение в вашей текущей оболочке.
  • Вторая строка необходима, если вы используете « ssh -X » для пересылки соединений X11: она обновляет переменную DISPLAY таким же образом.

Предостережение с моим методом: все может пойти не так, если на компьютере запущена другая команда « screen ».

Farzy
источник
-1 за ненужное использование sudo.
0xC0000022L
1

Я обычно поддерживаю долгосрочные (более 6 месяцев) сеансы на своем рабочем месте на разных серверах. Поэтому многократное подключение и наличие жизнеспособного ssh-экспедитора было проблематичным. Вот что я настроил в своих системах:

if [ -z "${STY}" -a -t 0 -a X${USER} = Xmyusername ]; then
    reattach () {
        if [ -n "${SSH_AUTH_SOCK}" ]; then
            ln -snf "${SSH_AUTH_SOCK}" "${HOME}/.ssh/agent-screen"
            SSH_AUTH_SOCK="${HOME}/.ssh/agent-screen" export SSH_AUTH_SOCK
        fi
        exec screen -A -D -RR ${1:+"$@"} ;
    }

    screen -wipe
    echo 'starting screen... (type Cntl-C to abort)'
    sleep 5 && reattach
fi

Если я просто войду на удаленный сервер без запуска / повторного подключения экрана, то появятся два «сокета», один используется screenдругим, а другой - новой оболочкой. Не должно быть двух сеансов «запуска», но второй сеанс все еще можно запустить с помощью reattach -S new; в этой ситуации агент будет разделен со ~/.ssh/agent-screenзначением. Чтобы вернуть работающего экспедитора обратно, я бы отсоединил, снова вошел в систему. X${USER} = XmyusernameГарантирует, что код не будет вызываться sudoна том же сервере.

Arcege
источник
1

Я использую вариант того, что @apinstein использует для моего .bashrc .

case "$TERM" in
    screen)
           export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
        ;;
         *)
           if [[ -n "$SSH_AUTH_SOCK" ]]; then
               ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
           fi
        ;;
esac

Это работает для всех приложений, запущенных в моем сеансе экрана. Это будет работать для всех новых оболочек в вашем сеансе экрана. Для существующих оболочек вам нужно запустить export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sockоболочку хоста, чтобы она заработала.

PS Извините, что добавил это как независимый ответ, тогда как он просто основан на ответе @ apinstein. Пришлось сделать это, так как комментарии в stackoverflow не поддерживают блоки кода.

Сандип Бхаттачарья
источник
Почему не всегда символическая ссылка и всегда экспорт?
Коллин Андерсон
@CollinAnderson Два разных поведения. один внутри экранной оболочки, а другой внутри обычной оболочки входа в систему. переменная окружения в оболочке входа в систему устанавливается ssh и, следовательно, там есть символическая ссылка. если мы сделаем это в сеансе экрана, то вызовем цикл символьной ссылки.
Сандип Бхаттачарья
Ааа, верно. Вам нужно будет указать только ссылку, если $ SSH_AUTH_SOCK еще не является ссылкой. Смотрите мой пост superuser.com/a/424588/134212
Коллин Андерсон
0

Я попробовал этот простой вкладыш, как было предложено в статье Давайте подружимся с screen и ssh-agent, и он работает для меня.

Первый раз войдите в Target. Необходимо сделать только один раз.

ssh -o StrictHostKeyChecking=no -C <userid>@<server>

Первый запуск экрана .. Нужно сделать только один раз.

eval `ssh-agent`; /usr/bin/screen -D -R -h 10000
ssh-add

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

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000
Sharjeel
источник
0

Это все действительно хорошие ответы, я делаю это немного по-другому. После запуска нового сеанса ssh и повторного подключения я сбрасываю SSH_AUTH_SOCKпеременную среды, основываясь на содержимом среды root bash. Мне требуется доступ ssh-agent только при использовании svn, поэтому я просто перезагружаюсь, SSH_AUTH_SOCKкак требуется в этих оболочках.

При этом используется файловая система proc, поэтому она специфична для Linux. Я протестировал это только на безголовом Linux-боксе, к которому у меня есть доступ, может потребоваться некоторая настройка, чтобы заставить его работать в других средах.

Сбросить SSH_AUTH_SOCK (это можно сделать псевдонимом).

$ . ~/bin/screen_auth.sh

screen_auth.sh выглядит так

# Find the pid of putty's bash shell
tty=`who | awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { print substr($2, 5) }'`
pid=`ps -t $tty | grep bash | awk '{print $1}'`
# Find the SSH_AUTH_SOCK variable in its enviornment
auth_sock=`xargs --null --max-args=1 echo < /proc/$pid/environ | grep SSH_AUTH_SOCK`
eval "export $auth_sock"
Iain
источник
0

Все вышеперечисленные решения страдают от гонок (либо в нескольких сеансах SCREEN, либо в нескольких соединениях SSH). Единственное универсальное решение, о котором я могу подумать, - это сначала включить SSH_AUTH_SOCK для процесса сервера SCREEN, screen -rа затем перетащить его в сеанс BASH перед каждой интерактивной не встроенной командой. К сожалению, SCREEN и BASH были разработаны без осознания таких проблем, поэтому их сложно реализовать должным образом (хотя никогда не поздно опубликовать запросы функций в обоих проектах). Моя попытка была преодолена для BASH-сессий, которые можно найти здесь:

Установить:

  1. вставьте оба скрипта $HOME/bin, добавьте исполняемый бит;
  2. убедитесь, что $HOME/binидет /usr/binв PATH:

    PATH = $ HOME / Bin: $ PATH

  3. добавьте это к вашему .bashrc:

    настройка источника $ HOME / bin / screen-helper

Теперь вы можете попытаться создать сеанс SCREEN внутри сеанса SSH, отсоединить, отключить, подключить и снова подключить, и, надеюсь, вы ssh-add -lдолжны правильно отобразить ваши ключи.

midenok
источник
Обратите внимание, что постоянный ssh-agentдемон (как предложено здесь superuser.com/a/412052/376867 ) не страдает от состояния гонки, но страдает от несвежего набора ключей. И что более важно, не очень безопасно оставлять все свои ключи на удаленном хосте вместе с сеансом экрана (или даже дольше до перезагрузки в случае упомянутого поста).
Миденок
0

Я пролистал другие ответы и не смог найти свой. Вот что я использую. Создайте файл ~/.screenrc-wrapperсо следующим содержимым:

escape ^xx
bindkey ^Ad detach

И добавьте это к себе ~/.bashrc(или, ~/.zshrcесли вы используете это):

  if echo $TERM | grep -v 'screen' && ! screen -x -SU wrapper; then
      if echo $TERM | grep -v 'screen' && ! screen -x -SU main; then
      screen -c ~/.screenrc-wrapper -SU wrapper ssh-agent screen -SU main
      fi
  fi

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

Вы можете найти эту функцию в контексте в моих точечных файлах .

d33tah
источник