Як у вас з’являється екран для автоматичного підключення до поточного ssh-агента при повторному приєднанні до існуючого екрану?


48

Якщо ви запускаєте сеанс на екрані під час запуску ssh-агента (від пересилання ssh -A агента), доступ до ssh-агента працює нормально. Однак, якщо ви відключитеся від цього сеансу, вийдете з системи, увійдіть знову (за допомогою переадресації ssh-агента) та повторно приєднайтеся до свого сеансу на екрані, доступ до ssh-агента не працює.

Як це можна виправити?

Відповіді:


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-агентом (тобто ви не маєте 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 - це синтаксис екрану, а не оболонка.

Спочатку рішення, адаптоване з цієї публікації , не працює, але має правильну ідею.


Це передбачає, що ви спочатку увійдете, а потім запустіть екран. Правильно?
innaM

1
Як це може бути будь-яким іншим способом? Як би ви запустили екран без входу?

1
Ти правий. Питання було сформульовано тупо. Але вам потрібно увійти, запустити оболонку і звідти запустити екран? Я часто роблю щось на кшталт "ssh -t some.machine screen -R".
innaM

1
Ну, тоді добре. Ну, я просто спробував це, і він не працює (тобто ssh-агент не підключений). Я думаю, що ssh не встановлює відповідні розетки, коли використовується таким чином. Може, ще якийсь аргумент-foo міг би це очистити?

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означає, що "якщо це socket ( -S), а не символічне посилання ( ! -h), створіть нове символічне посилання за відомим контуром. У всіх випадках повторно визначте, SSH_AUTH_SOCKщоб вказати на відомий шлях.

У ! -hуникає створення циклічної посилання , якщо ви запустите це кілька разів.

Крім того, якщо ви користуєтесь byobu, це робиться автоматично, без редагування будь-яких конфігураційних файлів.

Єдиний помилка, яку я знайшов у цьому ( byobuвін теж є), це якщо ви відкриєте другий ssh -Aабо ForwardAgentз'єднаєте, він замінить перший сокет, і якщо ви закриєте друге з'єднання до першого, ви втратите свій єдиний хороший сокет.


1
Це також працює tmux.
Dag Høidahl

Відмінно працює, але ламається при використанні віддалених домашніх папок. У такому випадку використовуйте ~/.ssh/ssh_auth_sock_"$(hostname)"для свого симпосилання. Він буде зберігати окремі розетки для кожного хоста.
Кібер

4

"ssh -t some.machine screen -R" не запустить bash і, отже, не запустить сценарій .bash_profile, де створено символьне посилання.

Ви можете спробувати: ssh -t some.machine bash -c "екран -R"

(якщо ви звичайно використовуєте bash як оболонку)

Редагувати: ця "відповідь" - це фактично коментар до першої відповіді, наведеної вище :)


"Перша відповідь, надана вище", нічого не означає, як відповіді змінюють порядок, оскільки вони проголосуються тощо.
rjmunro

3

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

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

це основи ... Я розробив сценарій lil для автоматизації процесу в моєму .screenrc для даного хоста. (також здійснює моє переадресація ssh, тому у всіх цих різних місцях я можу тунелювати з'єднання через мої сервери)

у дистрибутиві автоматичного пошуку має бути програма, яка називається 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 / screen

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


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 таким же чином.

Застереження щодо мого методу: все може піти не так, якщо на комп’ютері працює інша команда " екран ".


-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на одному сервері.


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 не підтримують кодові блоки.


Чому б не завжди symlink і завжди експортувати?
Колін Андерсон

@CollinAnderson Дві різні форми поведінки. один у оболонці екрана та один у оболонці звичайного входу. змінна середовище в оболонці входу задається ssh, а отже, і симпосилання. якщо ми це зробимо в межах екранного сеансу, тоді ми викличемо цикл символьного посилання.
Сандіп Бхаттачарія

Ага, правильно. Вам потрібно буде посилатися лише тоді, коли $ SSH_AUTH_SOCK ще не є посиланням. Дивіться моє повідомлення superuser.com/a/424588/134212
Collin Anderson

0

Я спробував цей простий вкладиш, як було запропоновано в « Давайте зробимо друзів з екрана та ssh-агента», і він працює для мене.

Перший час входу в 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

0

Це все справді хороші відповіді, я це роблю трохи інакше. Після того, як я запускаю новий ssh ​​сеанс і повторне вкладення екрана, я скидаю SSH_AUTH_SOCKзмінну середовища на основі вмісту кореневого середовища bash. Мені потрібен доступ до ssh-агента лише час від часу, коли я використовую 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"

0

Усі рішення, що перераховані вище, страждають від перегонових умов (або в декількох сеансах SCREEN, або в декількох з'єднаннях SSH). Єдине універсальне рішення, про яке я можу придумати, - спочатку натиснути SSH_AUTH_SOCK на серверний екран SCREEN, screen -rа потім перетягнути його всередину сесії BASH перед кожною інтерактивною невбудованою командою. На жаль, SCREEN і BASH були розроблені без усвідомлення подібних проблем, тому їх досить важко реалізувати (хоча опублікувати запити на функції в обох проектах ніколи не пізно). Моя спроба була зроблена для подолання цього питання для сесій BASH, які можна знайти тут:

Щоб встановити:

  1. помістити обидва сценарії $HOME/bin, додати виконавчий біт;
  2. переконайтеся, що це $HOME/binраніше /usr/binу PATH:

    PATH = $ ДОМА / кошик: $ PATH

  3. додайте це до своїх .bashrc:

    джерело $ HOME / налаштування бін / помічник екрана

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


Зауважте, що постійний ssh-agentдемон (як тут пропонується superuser.com/a/412052/376867 ) не страждає від перегонів, але страждає від несвіжих брелоків. І що ще важливіше, це не дуже безпечно залишати всі свої ключі на віддаленому хості разом із сеансом на екрані (або навіть довше до перезавантаження у випадку згаданої публікації).
midenok

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-агент. Ще одна приємна особливість полягає в тому, що вона запам'ятає налаштування вашого вікна - якщо ви використовуєте розділені вікна, це може бути дуже зручно.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.