기존 tmux 세션에 연결할 때 SSH 에이전트 환경 변수를 자동 업데이트하는 방법


79

연결이 끊긴 tmux 세션을 다시 연결할 때 SSH 에이전트를 복원하는 좋은 방법을 찾으려고합니다.

원인은 SSH 에이전트 세션이 변경되었지만 tmux 세션의 환경 변수가 업데이트되지 않았기 때문인 것 같습니다.

세션 자체를 연결하기 전에 어떻게 자동화 할 수 있습니까? 내가 연결하는 세션에 항상 bash 프롬프트가있는 것은 아니기 때문에 그 안에 무언가를 입력 할 여유가 없습니다. tmux 세션을 생성하거나 연결하기 전에 실행해야합니다.

내가 실행중인 코드의 예는 https://gist.github.com/ssbarnea/8646491 에 있습니다. tmux를 사용하여 persistem ssh 연결을 만드는 작은 ssh 래퍼입니다. 이것은 꽤 잘 작동하지만 때때로 ssh 에이전트가 작동을 멈춰서 더 이상 다른 호스트에 연결하는 데 사용할 수 없습니다.


아마도 pymkin의 응답을 답으로 표시해야 할 것입니다.
David Sanders

답변:


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으로 업데이트되지 않습니다. 원래 세션을 생성 한 것과 유지되므로 작동하지 않습니다. 어떤 아이디어?
Bret

6
set -g update-environment -r이 프로세스가 작동하려면 .tmux에 a를 추가 해야했습니다. 또한 소켓 링크 생성에 몇 가지 네임 스페이스를 추가했습니다. gist.github.com/bcomnes/e756624dc1d126ba2eb6
Bret

1
이전 GIST의 오류 수정 : .screenrc 및 .tmux.conf 파일에서 $ (hostname)을 $ HOSTNAME로 변경했습니다
Bret

2
@Bret tmux 세션에서 분리 한 다음 SSH 연결을 닫으면 솔루션이 제대로 작동합니다. 그러나 tmux 세션에 연결되어있는 상태에서 ssh 연결을 강제로 닫으면 작동하지 않습니다 (예 : 갑자기 네트워크 연결이 끊어지고 [Shift ~] [Enter]로 SSH 연결을 닫을 때.이 문제를 해결할 수있는 아이디어가 있습니까?
안드리 Yurchuk

2
아니, 포기했다 미안하다.
Bret

39

기본적으로 변수를 tmux 업데이트 하는 동안 SSH다음을 수행 할 필요가 없습니다.

  • 소켓 경로 변경 / 추가
  • SSH_AUTH_SOCKET변수 변경

기능을 추가하기 위해 변경 한 Chris Down 의 솔루션이 마음에 듭니다.

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 변수를 업데이트하는 동안"무슨 말입니까? (나는 당신의 링크 앵커가 지금은 존재하지 않는 것으로 판단됩니다.
브루노 Bronosky

1
@BrunoBronosky 나는 그의 링크를 수정했습니다. 당신이 옳았습니다 : 닻이 더 이상 존재하지 않았습니다. 이제 안정된 형태로 보입니다.
overthink

이것이 최고의 답변이어야합니다. 새 임시 파일을 만들 필요가 없습니다.
sjy

24

다음 SSH_AUTH_SOCKtmux창 내부에서 업데이트하는 데 사용하는 것입니다 (Hans Ginzel의 스크립트를 기반으로 함).

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)원격이 아닌 로컬에서 실행 되는 것처럼 보입니다 !
acgtyrant

나는 이것을 원격 (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. 현재 사용자와 일치하는 사용자 ID를 가진 결과로만 결과를 제한합니다.
  6. 모든 (권한 등) 오류 침묵
  7. 여러 개가있는 경우 마지막 결과 만 가져옵니다.

결과가 1 개 뿐이고 stderr 쓰레기에 대해 신경 쓰지 않는다면 6과 7을 생략 할 수 있습니다.


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입니다.


이것이 당신을 위해 작동한다고 확신합니까? -gI의 오래된 가치를 얻을 $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를 통해 액세스되는 git remotes를 업데이트하는 것과 마찬가지로 잘 작동 ssh-add -l하더라도 같은 명령은 오류를 생성합니다 ssh user@host.

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_sockbash 셸 ~/.bash_profile또는 ssh 연결 을 초기화하는 대신 tmux 시작 / 연결시 링크를 덮어 쓰기 때문에 약간 더 탄력적 입니다.~/.ssh/rc

이 마지막 경쟁 조건을 다루기 위해 키 바인딩을 추가하여 (Ctrl-b r)키 시퀀스로 tmux 구성을 다시로드 할 수 있습니다 .

# ~/.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

tmux 세션이 연결될 원격 zshrc에 다음 코드를 삽입합니다.

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-agent를 가져옵니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.