Як автоматично оновити змінні середовища агента SSH при підключенні до існуючих сеансів tmux


79

Я намагаюся знайти хороший спосіб відновити агент SSH при повторному підключенні відключеного сеансу tmux.

Здається, причиною є те, що сеанс агента SSH змінюється, але змінна середовища із сеансу tmux не оновлюється.

Як я можу це автоматизувати, перш ніж приєднувати сам сеанс? Оскільки сеанс, до якого я приєднуюсь, не завжди має запит bash, тому я не можу дозволити собі щось ввести всередині нього. Це має бути щось для запуску перед створенням або приєднанням сеансу tmux.

Прикладом коду, який я запускаю, є https://gist.github.com/ssbarnea/8646491 - невелика обгортка ssh, яка використовує tmux для створення з'єднань ssh persistem. Це працює досить добре, але іноді агент ssh перестає працювати, тому я більше не можу використовувати його для підключення до інших хостів.


Ви, мабуть, повинні позначити відповідь Пимкіна як відповідь.
Девід Сандерс,

Відповіді:


79

Існує відмінна суть Martijn Vermaat, яка дуже глибоко вирішує вашу проблему, хоча вона призначена для користувачів екрану, тому я коригую її тут для tmux.

Узагальнити:

  1. створити, ~/.ssh/rcякщо він ще не існує, і додати наступний вміст:

    #!/bin/bash
    
    # Fix SSH auth socket location so agent forwarding works with tmux
    if test "$SSH_AUTH_SOCK" ; then
      ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
    fi
    
  2. Зробіть це в tmux, додайте це до свого ~/.tmux.conf:

    # fix ssh agent when tmux is detached
    setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
    

Щоб увімкнути переадресацію X11, потрібна додаткова робота, див. Суть .


1
При повторному підключенні до tmux він не оновлюється до найновішого ssh_auth_sock ... він залишається тим, який спочатку створив сеанс, тому це не працює. Будь-які ідеї?
Брет

6
Мені довелося додати set -g update-environment -r.tmux, щоб цей процес запрацював. Я також додав кілька просторів імен для створення посилання на сокет: gist.github.com/bcomnes/e756624dc1d126ba2eb6
Брет,

1
Виправлена ​​помилка з попереднім GIST: було змінено $ (ім'я хосту) на $ HOSTNAME у файлах .screenrc та .tmux.conf
Брет

2
@Bret Ваше рішення прекрасно працює, якщо ви від'єднаєтесь від сеансу tmux, а потім закриєте з'єднання SSH. Однак це не спрацьовує, якщо ви закриваєте ssh-з'єднання примусово, все ще приєднуючись до сеансу tmux (наприклад, коли ви раптово втрачаєте мережеве з'єднання та закриваєте з'єднання SSH за допомогою [Shift ~] [Enter]. Будь-які ідеї, що це може виправити?
Андрій Юрчук

2
Ні, я відмовився від вибачення.
Брет

39

Хоча за замовчуванням tmux оновлюються SSH змінні, немає необхідності

  • змінити / додати шлях до сокета
  • змінити SSH_AUTH_SOCKETзмінну

Мені подобається рішення Кріса Дауна, яке я змінив, щоб додати функцію

fixssh() {
    eval $(tmux show-env    \
        |sed -n 's/^\(SSH_[^=]*\)=\(.*\)/export \1="\2"/p')
}

в ~/.bashrc . Дзвінок fixsshпісля приєднання сесії або до ssh/ scp/ rsync.

Новіші версії tmux-s опції підтримки для show-env, тому лише

eval $(tmux show-env -s |grep '^SSH_')

можливо.


Велике спасибі, ось що мені вдалося! :) Однак одна невелика проблема: коли це робиться в повторно приєднаній панелі tmux, це не працює. Мені потрібно закрити стару панель та відкрити нову. Виправлення для цього полягає у від’єднанні tmux, показі $DISPLAYзмінної, повторному підключенні tmux та $DISPLAYправильному встановленні , у моєму випадку export DISPLAY=localhost:14.0, але число, схоже, змінюється під час кожного сеансу ssh.
PlasmaBinturong

"Поки tmux за замовчуванням оновлює змінні SSH" Про що ви говорите? (Я підозрюю, що якоря у вашому посиланні зараз не існує.
Бруно Броноскі,

1
@BrunoBronosky Я зафіксував його посилання. Ви мали рацію: якоря вже не існувало. Начебто зараз має стабільну форму.
передумати

Це має бути головною відповіддю. Не потрібно створювати новий тимчасовий файл.
sjy

24

Ось те, що я використовую для оновлення SSH_AUTH_SOCKвсередині tmuxвікна (на основі сценарію Ганса Гінцеля):

alias fixssh='eval $(tmux showenv -s SSH_AUTH_SOCK)'

Або для tmuxцього не має showenv -s:

alias fixssh='export $(tmux showenv SSH_AUTH_SOCK)'

6

Ось моє рішення, яке включає обидва підходи і не вимагає додаткового набору тексту при повторному підключенні до сеансу tmux

alias ssh='[ -n "$TMUX" ] && eval $(tmux showenv -s SSH_AUTH_SOCK); /usr/bin/ssh'

1
Схоже, він буде виконуватися eval $(tmux showenv -s SSH_AUTH_SOCK)локально, а не віддалено!
повірений

Я написав це на пульті дистанційного керування (працює tmux), і він працював, як я очікував. Дякую!
riywo

6

Тут є багато хороших відповідей. Але бувають випадки, коли tmux show-environmentне бачить SSH_AUTH_SOCK. У цьому випадку ви можете використовувати findйого для явного пошуку.

export SSH_AUTH_SOCK=$(find /tmp -path '*/ssh-*' -name 'agent*' -uid $(id -u) 2>/dev/null | tail -n1)

Це довго і складно, тому я розберу його ...

01  export SSH_AUTH_SOCK=$(
02    find /tmp \
03      -path '*/ssh-*'
04      -name 'agent*'
05      -uid $(id -u)
06      2>/dev/null
07    | tail -n1
08  )
  1. exportSSH_AUTH_SOCKнабір змінної середовища на виході з$() підстановки команд
  2. find файли, що починаються з /tmp
  3. обмежувати результати лише тими з /ssh- перебуває на шляху
  4. обмежувати результати лише тими, чиє ім’я починається з agent
  5. обмежити результати лише тими, у яких ідентифікатор користувача відповідає поточному користувачеві
  6. вимкнути всі помилки (дозволи тощо)
  7. беруть лише останній результат, якщо їх кілька

Можливо, вам вдасться зупинити 6 і 7, якщо ви знаєте, що буде лише 1 результат, і ви не дбаєте про сміття stderr.


2
З усіх перелічених тут рішень лише це працювало на mac.
SilentGuy

Приємно, але може знадобитися взяти лише ОСТАННІЙ сокет агента ssh. Для цього ми можемо додати сортування за find:find /tmp -path '*/ssh-*' -name 'agent*' -uid (id -u) -printf "%T+\t%p\n" 2>/dev/null | sort | tail -n1 | awk -F'\t' '{print $2 }'
ColCh

3

Я використовую різновид попередніх відповідей:

eval "export $(tmux show-environment -g SSH_AUTH_SOCK)"

припускаючи, що ви зробили агент ssh, який розпочався із зовнішнього середовища. Те саме стосується інших змінних середовища, таких як DISPLAY.


Ви впевнені, що це працює для вас? З -gя отримую несвіже значення $SSH_AUTH_SOCK. Залишаючи -gце робить трюк. Дивіться також інші відповіді.
feklee

2

Я вважаю за краще уникати налаштування TMUX (і т.д.) і тримати все чисто ~/.ssh/. На пульті системі:

Створити ~/.ssh/rc:

#!/bin/bash

# Fix SSH auth socket location so agent forwarding works within tmux
if test "$SSH_AUTH_SOCK" ; then
  ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

Додайте наступне, щоб ~/.ssh/configвоно більше не покладалося $SSH_AUTH_SOCK, що залишається застарілим в окремих терміналах:

Host *
  IdentityAgent ~/.ssh/ssh_auth_sock

Відомі обмеження

  • ssh-addне використовує ~/.ssh/configі тому не може спілкуватися з ssh-agent. Такі команди, як ssh-add -lвидавання помилок, хоч і ssh user@hostпрацюють нормально, як і оновлення пультів дистанційного керування git, доступ до яких здійснюється через SSH.

1

Можливо, я розробив рішення, яке повністю інкапсульовано у ~/.tmux.confфайлі конфігурації. Це інший підхід, ніж модифікація ~/.bash_profileі ~/.ssh/rc.

Рішення лише за допомогою ~/.tmux.conf

Просто виріжте та вставте наступний код у свій ~/.tmux.conf

# ~/.tmux.conf

# SSH agent forwarding
#
# Ensure that SSH-Agent forwarding will work when re-attaching to the tmux
#   session from a different SSH connection (after a dropped connection).
#   This code will run upon tmux create, tmux attach, or config reload.
#
# If there is an SSH_AUTH_SOCK originally defined:
#   1) Remove all SSH related env var names from update-environment.
#      Without this, setenv cannot override variables such as SSH_AUTH_SOCK.
#      Verify update-environment with: tmux show-option -g update-environment
#   2) Force-set SSH_AUTH_SOCK to be a known location
#      /tmp/ssh_auth_sock_tmux
#   3) Force-create a link of the first found ssh-agent socket at the known location
if-shell '[ -n $SSH_AUTH_SOCK ]' " \
  set-option -sg update-environment \"DISPLAY WINDOWID XAUTHORITY\"; \
  setenv -g SSH_AUTH_SOCK /tmp/ssh_auth_sock_tmux; \
  run-shell \"ln -sf $(find /tmp/ssh-* -type s -readable | head -n 1) /tmp/ssh_auth_sock_tmux\" \
"

Застереження

Вищевказане рішення разом з іншими рішеннями сприйнятливе до гоночного стану при ініціюванні декількох з'єднань до однієї машини. Розглянемо це:

  • Клієнт 1 Підключення: SSH до machineX, запуск / підключення tmux (запис ssh_auth_sockпосилання)
  • Клієнт 2 Підключення: SSH до machineX, запуск / підключення tmux (перезапис ssh_auth_sockпосилання)
  • Відключення клієнта 2: у клієнта 1 залишається застаріле ssh_auth_sockпосилання, таким чином порушуючисьssh-agent

Однак це рішення є трохи більш стійким, оскільки воно перезаписує ssh_auth_sockпосилання лише при запуску / приєднанні tmux, а не при ініціалізації оболонки bash ~/.bash_profileабо з'єднання ssh~/.ssh/rc

Щоб покрити цю останню умову гонки, можна додати прив’язку ключів для перезавантаження конфігурації tmux (Ctrl-b r)послідовністю ключів.

# ~/.tmux.conf

# reload config file
bind r source-file ~/.tmux.conf

Усередині активного сеансу tmux, виконуючи цю послідовність, коли ssh_auth_sockпосилання стає застарілим, оновиться з'єднання ssh-agent.


0

Наткнувшись на стільки пропозицій, я нарешті знайшов рішення, яке дозволяє TMUX оновити застарілий агент ssh після підключення. В основному, файли zshrc на локальній та віддаленій машинах повинні бути змінені.

Вставте наступні коди в локальний zshrc, який базується на цьому посиланні .

export SSH_AUTH_SOCK=~/.ssh/ssh-agent.$(hostname).sock
ssh-add -l 2>/dev/null >/dev/null
# The error of executing ssh-add command denotes a valid agent does not
# exist. 
if [ $? -ge 1 ]; then
  # remove the socket if it exists
  if [ -S "${SSH_AUTH_SOCK}" ]; then
    rm "${SSH_AUTH_SOCK}"
  fi
  ssh-agent -a "${SSH_AUTH_SOCK}" >/dev/null
  # one week life time
  ssh-add -t 1W path-to-private-rsa-file
fi

Вставте наступний код у віддалений zshrc, де буде приєднаний сеанс tmux.

alias fixssh='eval $(tmux showenv -s SSH_AUTH_SOCK)'

Потім ssh у віддалену машину. Необхідний параметр -A.

ssh -A username@hostname

Прикріпіть сеанс TMUX. Перевірте змінні середовища TMUX

# run this command in the shell
tmux showenv -s
# or run this command after prefix CTRL+A or CTRL+B
:show-environment

Запустіть fixsshу раніше існуючих областях, щоб оновити агент ssh. Якщо створено нову область, вона автоматично отримає новий ssh-агент.

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