로그인시 ssh-agent 시작


262

SSH 별칭을 사용하여 Bitbucket.com에서 원격 Git 저장소로 사이트를 가져 왔습니다. 서버에서 ssh-agent를 수동으로 시작할 수 있지만 SSH를 통해 로그인 할 때마다이 작업을 수행해야합니다.

ssh-agent를 수동으로 시작합니다.

eval ssh-agent $SHELL

그런 다음 에이전트를 추가합니다.

ssh-add ~/.ssh/bitbucket_id

그런 다음 내가 할 때 나타납니다.

ssh-add -l

그리고 나는 가야 해요. 로그인 할 때마다이 프로세스를 자동화 할 수있는 방법이 있습니까? 서버가 RedHat 6.2 (Santiago)를 실행 중입니다.


2
로그인 할 때마다 수행 할 작업은 .profile (터미널 로그인) 또는 .xinitrc (GUI 로그인의 경우)에 있어야합니다.
Barmar

1
아! .bash_profile을 사용하고 있습니다 ... .profile과 .bash_profile의 차이점은 무엇입니까?
Pathsofdesign

1
처음에 왜 그런 식으로 명령을 실행하는지 모르겠습니다. 의 하위 프로세스로 ssh-agent <command>실행 되므로 새 셸을 시작합니다. 당신이 원하는 것 같아요 . <command>ssh-agenteval ssh-agent
Barmar

9
.bash_profilebash에만 해당되며 .profile모든 POSIX 셸에 일반적입니다. bash을 먼저 .bash_profile찾은 다음 기본값을으로 설정합니다 .profile.
Barmar

5
ssh-agent"표준"(POSIX 호환) 쉘 을 생성하는 올바른 방법 은 eval $(ssh-agent -s)입니다. 사용자가 로그 아웃 할 때 넣어도 좋습니다 그래서 당신은, 당신이 적절하게 에이전트를 제거 할 필요가 있음을 유의하십시오 trap 'kill $SSH_AGENT_PID' EXIT당신의 .profile에이전트를 시작하는 줄 끝.
kostix

답변:


368

이 기사를 살펴보십시오. 이것이 매우 유용하다는 것을 알 수 있습니다.

http://mah.everybody.org/docs/ssh

위의 링크가 언젠가 사라지는 경우를 대비하여 아래 솔루션의 주요 부분을 캡처하고 있습니다.

Daniel Starin을 통해 Joseph M. Reagle의 솔루션 :

이 다음을 귀하의 .bash_profile

SSH_ENV="$HOME/.ssh/agent-environment"

function start_agent {
    echo "Initialising new SSH agent..."
    /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
    echo succeeded
    chmod 600 "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    #ps ${SSH_AGENT_PID} doesn't work under cywgin
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

이 버전은 이미 ssh-agent를 시작했는지 확인하고 찾을 수없는 경우 시작하여 다음에 시작할 때 사용할 수 있도록 설정을 저장하기 때문에 특히 좋습니다. 껍질.


8
기계를 다시 시작할 필요는 없습니다. 현재 쉘 세션에서 .bash_profile사용하여 다시로드 할 수 있습니다 source ~/.bash_profile. 어쨌든 새로운 설정을로드하기 때문에 머신 재시작도 작동합니다.
Litmus

11
사용 SSH_ENV="$HOME/.ssh/env"(즉, 환경이 아닌) 이유는 무엇입니까? sshd는 ~ / .ssh / environment를 사용합니다 (Man page : PermitUserEnvironment 참조). - Github에서 또한 그들의 솔루션이 추천 help.github.com/articles/...을
앤드류 머피에게

7
이 스크립트는 ~ / .bashrc 파일 (~ / .profile 또는 ~ / .bash_profile이 아님)에 넣었을 때 효과적이었습니다. 로컬 콘솔을 처음 열면 암호 문구를 묻는 메시지가 표시되며 추가 프롬프트없이 해당 시점부터 모든 것이 작동합니다. 건배.
앤드류 페이트

3
ssh-agent.bashrc에 시작 명령을 추가하면 scp명령이 작동하지 않습니다.
Dzanvu

5
여전히 성가신 ... 로그인 할 때마다 ... ssh를 사용하지 않더라도이 작업을 수행해야합니다. ssh가 호출 될 때마다이 기능을 해제해야합니다. 이상적으로는 어떤 호스트가 어떤 키를로드하는지 구성 할 수 있어야합니다.
Erik Aronesty

98

Arch Linux에서 다음은 실제로 훌륭하게 작동합니다 (모든 시스템 기반 배포판에서 작동해야 함).

다음을 넣어 시스템 사용자 서비스를 작성하십시오 ~/.config/systemd/user/ssh-agent.service.

[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

소켓 ( .bash_profile, .zshrc, ...)에 대한 환경 변수를 갖도록 설정 쉘 :

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

서비스를 활성화하면 로그인시 자동으로 시작되고 시작됩니다.

systemctl --user enable ssh-agent
systemctl --user start ssh-agent

로컬 ssh 구성 파일에 다음 구성 설정을 추가하십시오 ~/.ssh/config(SSH 7.2부터 작동 함).

AddKeysToAgent  yes

이렇게하면 ssh 클라이언트가 항상 실행중인 에이전트에 키를 추가하도록 지시하므로 미리 ssh-add 할 필요가 없습니다.


3
우분투 에서이 작업을 수행하는 동안이 의견을 찾았습니다. 적어도 시스템이 어떻게 작동 해야하는지에 대한 지식을 감안할 때 시작 스크립트에 무언가를 해킹하는 것보다 내장 시스템에서 훨씬 더 잘 작동하는 것 같습니다.
xiterion

우분투 16.04 LTS에서 이것을 시도했습니다. 불행히도 모든 쉘 프로세스는 개별 ssh-agent프로세스를 원합니다 . 아마도 나는 문서를 읽은 후에도 지식이 부족할 것입니다.
다이스케 아라 마키

Type = simple을 사용할 수도 있습니다 . wiki.archlinux.org/index.php/…
Hans-J. Schmid

2
이 솔루션은 기본적으로 시스템 서비스를 설치 / 구성합니까 (사용자 전용)?
Trevor Boyd Smith

그러나 이것은 SSH_AGENT_PID환경 변수를 설정하지 않을 것입니다 :(
MrMeszaros

73

오래된 질문이지만 비슷한 상황을 겪었습니다. 위의 답변이 필요한 것을 완전히 달성했다고 생각하지 마십시오. 빠진 조각은 keychain; 아직 설치하지 않았다면 설치하십시오.

sudo apt-get install keychain

그런 다음 다음 줄을 ~/.bashrc

eval $(keychain --eval id_rsa)

이것은 ssh-agent실행 중이 아닌 경우 시작하고 , 실행 중이면 연결하고, ssh-agent환경 변수를 쉘에로드하고 ssh 키를로드합니다.

로드하려는 id_rsa개인 키로 변경하십시오 ~/.ssh.

참고

/unix/90853/how-can-i-run-ssh-add-automatically-without-password-prompt


주어진 지침에 따라 키 체인이 작동하지 않습니다. .bash_profile에 추가했는데 ssh는 여전히 암호를 묻습니다. 나는 같은 껍질에서 여러 번 시도했다. 주사위가 없습니다. 기본 ssh-agent 접근 방식으로 돌아 가기
javadba

keychain --eval id_[yourid file]
xelber에 평가판

4
StackOverflow 주석 형식으로 인해 솔루션을 연구하는 데 20 분이 걸렸습니다. 위의 xelber의 코멘트 당, 올바른 솔루션입니다 eval `keychain --eval id_[yourid file]`.bashrc. 실행중인 ssh-agent에 액세스하기 위해 현재 쉘에 대한 환경 변수를 평가하는 데 필요한 백틱입니다.
James

2
이것이 정확하고 간단한 해결책입니다. 키 체인 명령이 실행될 때 로그를 보지 않으려면 자동 -q모드 옵션을 추가 할 수 있습니다 . 키 체인에 대한 자세한 정보 : funtoo.org/Keychain
Ananta

4
Thx, 이것은 지금까지 가장 우아한 솔루션입니다.
greenspand

37

허용되는 솔루션에는 다음과 같은 단점이 있습니다.

  • 유지하기가 복잡합니다.
  • 오류 또는 보안 위반으로 이어질 수있는 저장 파일을 평가합니다.
  • 에이전트를 시작하지만 키를 점화 상태로 두는 것과 거의 비슷한 에이전트를 중지하지 않습니다.

키에 비밀번호를 입력하지 않아도되는 경우 다음 해결 방법을 제안합니다. .bash_profile 맨 끝에 다음을 추가 하십시오 (필요에 따라 키 목록 편집).

exec ssh-agent $BASH -s 10<&0 << EOF
    ssh-add ~/.ssh/your_key1.rsa \
            ~/.ssh/your_key2.rsa &> /dev/null
    exec $BASH <&10-
EOF

다음과 같은 장점이 있습니다.

  • 훨씬 간단한 해결책;
  • bash 세션이 종료되면 에이전트 세션이 종료됩니다.

가능한 단점이 있습니다.

  • 대화식 ssh-add명령은 하나의 세션에만 영향을 미치며 실제로는 매우 비정형적인 상황에서만 문제가됩니다.
  • 암호를 입력해야하는 경우 사용할 수 없습니다.
  • 시작된 쉘은 비 로그인이됩니다 (AFAIK에 영향을 미치지 않음).

ssh-agent메모리 나 CPU 시간이 더 걸리지 않기 때문에 여러 프로세스가 불리하지는 않습니다.


Git Bash를 사용하여 Windows 10의 $ HOME 외부 디렉토리에 SSH 키가 있습니다. RSA로가는 길을 바꾸는 것이이 작업을 수행하기 위해해야 ​​할 전부였습니다. TYVM!
kayleeFrye_onDeck

7
나는 그 주장 의 "키 암호를 입력하도록 요구하지 않는 경우" 점화에 키를두고 가까이 상당입니다.
Bruno Bronosky

적어도 네트워크 어딘가가 아닌 자체 호스트에 있습니다.
midenok

1
"키에 암호를 입력 할 필요가없는 경우"는 키를 시동 상태로 두는 것과 거의 비슷하다고 주장합니다. "<-어떻게 그렇게 설명합니까 ?? 키는 암호보다 훨씬 유연하기 때문에 훨씬 쉽게 취소 할 수 있습니다 (무엇입니까? 전체 액세스 권한을 가진 sudo 사용자에게만 키를 사용하고 있습니까? tsk tsk). 여러 사용자 프로필을위한 여러 키 집합. 배포 또는 엔드 투 엔드 검사와 같은 것을 자동화하려면 "오케스트레이션"중에 지속적으로 암호를 입력하십시오.
Scott Prive

2
하지마 암호가없는 키는 나쁜 습관입니다.
user48678

26

이것을에 추가 ~/.bashrc한 다음 로그 아웃했다가 다시 적용하십시오.

if [ ! -S ~/.ssh/ssh_auth_sock ]; then
  eval `ssh-agent`
  ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add

재부팅 할 때마다 처음 로그인 할 때만 암호를 묻는 메시지가 표시됩니다. ssh-agent계속 실행되는 한 계속 재사용 됩니다.


여러 키가 있고 이름이 지정되지 않은 경우 대신 무엇을 사용 ~/.ssh/id_rsa합니까? ssh-add답 의 일부에는 키의 기본 파일 이름이 필요합니다.
Gabriel Staples

예. 나는 필요한 경우 당신은 단지 마지막 줄의 끝까지에 파일 이름을 추가 할 수 있다고 생각
콜린 앤더슨

그러나 여전히 수동으로 암호를 입력하지 않고 스크립트를 자동화 할 수 없습니까? 그것을 피하는 방법?
trainoasis

7

따라서 위에서 설명한 접근 방식을 사용했지만 마지막 bash 세션이 끝나면 에이전트가 죽는 것을 선호합니다. 이것은 다른 솔루션보다 약간 길지만 선호하는 방법입니다. 기본 아이디어는 첫 번째 bash 세션이 ssh-agent를 시작한다는 것입니다. 그런 다음 각 추가 bash 세션은 구성 파일 ( ~/.ssh/.agent_env)을 확인합니다. 그것이 있고 세션이 실행 중이면 환경을 소싱하고 소켓 파일에 대한 하드 링크를 만듭니다 /tmp(원래 소켓 파일과 동일한 파일 시스템에 있어야 함). bash 세션이 종료되면 각각 자체 하드 링크가 삭제됩니다. 마지막 세션을 종료하면 하드 링크에 2 개의 링크 (하드 링크 및 원본)가 있고 프로세스 자체 소켓이 제거되고 프로세스가 종료되면 0이 발생하여 마지막 bash 세션이 종료 된 후 깨끗한 환경이 유지됩니다.

# Start ssh-agent to keep you logged in with keys, use `ssh-add` to log in
agent=`pgrep ssh-agent -u $USER` # get only your agents           
if [[ "$agent" == "" || ! -e ~/.ssh/.agent_env ]]; then
    # if no agents or environment file is missing create a new one
    # remove old agents / environment variable files
    kill $agent running
    rm ~/.ssh/.agent_env 

    # restart
    eval `ssh-agent` 
    echo 'export SSH_AUTH_SOCK'=$SSH_AUTH_SOCK >> ~/.ssh/.agent_env             
    echo 'export SSH_AGENT_PID'=$SSH_AGENT_PID >> ~/.ssh/.agent_env             
fi

# create our own hardlink to the socket (with random name)           
source ~/.ssh/.agent_env                                                    
MYSOCK=/tmp/ssh_agent.${RANDOM}.sock                                        
ln -T $SSH_AUTH_SOCK $MYSOCK                                                
export SSH_AUTH_SOCK=$MYSOCK                                                

end_agent()                                                                     
{
    # if we are the last holder of a hardlink, then kill the agent
    nhard=`ls -l $SSH_AUTH_SOCK | awk '{print $2}'`                             
    if [[ "$nhard" -eq 2 ]]; then                                               
        rm ~/.ssh/.agent_env                                                    
        ssh-agent -k                                                            
    fi                                                                          
    rm $SSH_AUTH_SOCK                                                           
}                                                                               
trap end_agent EXIT                                                             
set +x              

다른 쉘 (BASH 이외의 다른)의 로그인시 이것을 BASH 스크립트로 실행하면 작동합니까?
hoijui 2018

7

또 다른 솔루션을 추가하기 위해 : P, @spheenik과 @ collin-anderson의 솔루션을 함께 사용했습니다.

 # Ensure that we have an ssh config with AddKeysToAgent set to true
 if [ ! -f ~/.ssh/config ] || ! cat ~/.ssh/config | grep AddKeysToAgent | grep yes > /dev/null; then
     echo "AddKeysToAgent  yes" >> ~/.ssh/config
 fi
 # Ensure a ssh-agent is running so you only have to enter keys once
 if [ ! -S ~/.ssh/ssh_auth_sock ]; then
   eval `ssh-agent`
   ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
 fi
 export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

좀 더 우아하지만 간단하고 읽기 쉬울 수 있습니다. 이 솔루션 :

  • 보장하지만은 AddKeysToAgent yes키가 자동으로 사용에 추가됩니다 귀하의 ssh 설정에
  • 로그인시 비밀번호 문구를 입력하라는 메시지가 표시되지 않습니다 (다시 한번 비밀번호 문구 입력은 처음 사용할 때 발생 함)
  • ssh 에이전트가 아직 시작되지 않은 경우 자동으로 시작합니다.

댓글 환영합니다 :)


1
이것은 나를 위해 완벽하게 작동했습니다. 쿠분투에서는 .profile에 넣었습니다.
Shai

1
AddKeysToAgent yes설정 에 대해 잘 알고 있습니다. 감사.
Collin Anderson

3

이것을 / etc / profile- 시스템 전체 (또는 사용자 로컬 .profile 또는 _.bash_profile_) 에 추가하여 해결했습니다 .

# SSH-AGENT 
#!/usr/bin/env bash
SERVICE='ssh-agent'
WHOAMI=`who am i |awk '{print $1}'`

if pgrep -u $WHOAMI $SERVICE >/dev/null
then
    echo $SERVICE running.
else
    echo $SERVICE not running.
    echo starting
    ssh-agent > ~/.ssh/agent_env
fi
. ~/.ssh/agent_env

현재 사용자에 대해 실행 중이 아닌 경우 새 ssh-agent를 시작하거나 실행중인 경우 ssh-agent env 매개 변수를 재설정합니다.


에이전트가 이미 실행 중인지 확인하는 방법에 대해 감사합니다!
Mike Maxwell

어떻게 if pgrep -u $WHOAMI $SERVICE >/dev/null작동합니까?
Josh Desmond

3

피쉬 쉘 사용자는 이 스크립트 를 사용 하여 동일한 작업을 수행 할 수 있습니다 .

# content has to be in .config/fish/config.fish
# if it does not exist, create the file
setenv SSH_ENV $HOME/.ssh/environment

function start_agent                                                                                                                                                                    
    echo "Initializing new SSH agent ..."
    ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV
    echo "succeeded"
    chmod 600 $SSH_ENV 
    . $SSH_ENV > /dev/null
    ssh-add
end

function test_identities                                                                                                                                                                
    ssh-add -l | grep "The agent has no identities" > /dev/null
    if [ $status -eq 0 ]
        ssh-add
        if [ $status -eq 2 ]
            start_agent
        end
    end
end

if [ -n "$SSH_AGENT_PID" ] 
    ps -ef | grep $SSH_AGENT_PID | grep ssh-agent > /dev/null
    if [ $status -eq 0 ]
        test_identities
    end  
else
    if [ -f $SSH_ENV ]
        . $SSH_ENV > /dev/null
    end  
    ps -ef | grep $SSH_AGENT_PID | grep -v grep | grep ssh-agent > /dev/null
    if [ $status -eq 0 ]
        test_identities
    else 
        start_agent
    end  
end

2

이를 위해 ssh-ident 도구를 사용합니다.

자사에서 남자 -page :

ssh-ident-필요에 따라 ssh-agent를 시작하고 사용합니다.


1

많은 출처의 커플 솔루션을 시도했지만 모두 너무 많은 문제로 보였습니다. 마지막으로 가장 쉬운 것을 발견했습니다 :)

아직 zshoh-my-zsh에 익숙하지 않은 경우 설치하십시오. 당신은 이것을 좋아하게 될 것이다 :)

그런 다음 편집 .zshrc

vim ~/.zshrc

plugins섹션을 찾아서 다음 과 ssh-agent같이 사용하도록 업데이트하십시오 .

plugins=(ssh-agent git)

그리고 그게 전부입니다! 당신은해야 ssh-agent당신이 당신의 쉘을 시작하고 실행 할 때마다


1

나는 당신의 대답을 많이 좋아합니다. cygwin / linux호스트 작업 이 훨씬 쉬워졌습니다. 시작 기능과 끝 기능을 결합하여 안전하게 만들었습니다.

SSH_ENV="$HOME/.ssh/.agent_env"

function start_agent {
    echo "Initialising new SSH agent..."

    eval `/usr/bin/ssh-agent`
    echo 'export SSH_AUTH_SOCK'=$SSH_AUTH_SOCK >> ${SSH_ENV}
    echo 'export SSH_AGENT_PID'=$SSH_AGENT_PID >> ${SSH_ENV}

    echo succeeded
    chmod 600 "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    /usr/bin/ssh-add;
}

# Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    #ps ${SSH_AGENT_PID} doesn't work under cywgin
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

# create our own hardlink to the socket (with random name)
MYSOCK=/tmp/ssh_agent.${RANDOM}.sock
ln -T $SSH_AUTH_SOCK $MYSOCK
export SSH_AUTH_SOCK=$MYSOCK

end_agent()
{
    # if we are the last holder of a hardlink, then kill the agent
    nhard=`ls -l $SSH_AUTH_SOCK | awk '{print $2}'`
    if [[ "$nhard" -eq 2 ]]; then
        rm ${SSH_ENV}
        /usr/bin/ssh-agent -k
    fi
    rm $SSH_AUTH_SOCK
}
trap end_agent EXIT
set +x
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.