Iniciar ssh-agent no login


262

Eu tenho um site como um repositório Git remoto, retirando do Bitbucket.com usando um alias SSH. Posso iniciar manualmente o ssh-agent no meu servidor, mas preciso fazer isso toda vez que faço login via SSH.

Inicio manualmente o ssh-agent:

eval ssh-agent $SHELL

Então eu adiciono o agente:

ssh-add ~/.ssh/bitbucket_id

Então ele aparece quando eu faço:

ssh-add -l

E eu estou pronto para ir. Existe alguma maneira de automatizar esse processo para que eu não precise fazer isso toda vez que fizer login? O servidor está executando o RedHat 6.2 (Santiago).


2
Qualquer coisa que você queira fazer sempre que fizer login deve estar em .profile (logins de terminal) ou .xinitrc (para logins da GUI).
Barmar 18/09/2013

1
Ah! Eu estava usando .bash_profile ... Qual é a diferença entre .profile e .bash_profile?
Pathsofdesign 18/09/2013

1
Não sei por que você está executando o comando dessa maneira em primeiro lugar. ssh-agent <command>é executado <command>como um subprocesso de ssh-agent, então você está iniciando um novo shell. Eu acho que você quer eval ssh-agent.
Barmar 18/09/2013

9
.bash_profileé específico para bash, .profileé genérico para todos os shells POSIX. bashprocurará primeiro e .bash_profile, em seguida, usará como padrão .profile.
Barmar 18/09/2013

5
A maneira correta de gerar ssh-agentum shell "padrão" (compatível com POSIX) é eval $(ssh-agent -s). Observe também que você deve se livrar adequadamente do agente ao fazer logout, por isso também é aconselhável inserir trap 'kill $SSH_AGENT_PID' EXITsua .profileapós a linha que inicia o agente.
Kostix 19/09/2013

Respostas:


368

Por favor, leia este artigo. Você pode achar isso muito útil:

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

Caso o link acima desapareça algum dia, estou capturando a parte principal da solução abaixo:

Esta solução de Joseph M. Reagle por Daniel Starin:

Adicione o seguinte ao seu .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

Esta versão é especialmente interessante, pois ela verificará se você já iniciou o ssh-agent e, se não conseguir encontrá-la, iniciará e armazenará as configurações para que possam ser usadas na próxima vez que você iniciar um Concha.


8
A reinicialização da máquina não é necessária. Você pode apenas recarregar .bash_profileusando source ~/.bash_profilena sua sessão atual do shell. A reinicialização da máquina também funcionará porque isso carregará a nova configuração de qualquer maneira.
Litmus

11
Use SSH_ENV="$HOME/.ssh/env"(ou seja, não / ambiente) Por quê? O sshd usa ~ / .ssh / environment (consulte a página de manual: PermitUserEnvironment). O Github também recomenda isso em sua solução - help.github.com/articles/…
Andrew Murphy

7
Esse script funcionou para mim quando o coloquei no meu arquivo ~ / .bashrc (não no meu ~ / .profile ou ~ / .bash_profile). Na primeira vez que abro um console local, ele solicita a frase secreta, tudo funciona a partir desse ponto sem aviso adicional. Felicidades.
Andrew patê

3
Adicionar o ssh-agentcomando start no .bashrc fará com que o scpcomando não funcione.
Dzanvu

5
Ainda irritante ... você deve fazer isso toda vez que fizer login ... mesmo que não use o ssh. É necessário desativar esse recurso toda vez que o ssh for chamado ... e, idealmente, você poderá configurar quais hosts farão com que chaves sejam carregadas.
Erik Aronesty

99

No Arch Linux, o seguinte funciona muito bem (deve funcionar em todas as distribuições baseadas em systemd):

Crie um serviço de usuário systemd, colocando o seguinte em ~/.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

Shell de instalação para ter uma variável de ambiente para o soquete ( .bash_profile, .zshrc, ...):

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

Ative o serviço, para que ele seja iniciado automaticamente no login e inicie-o:

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

Adicione a seguinte configuração ao seu arquivo de configuração ssh local ~/.ssh/config(isso funciona desde o SSH 7.2):

AddKeysToAgent  yes

Isso instruirá o cliente ssh a sempre adicionar a chave a um agente em execução, portanto, não há necessidade de adicioná-la previamente.


3
Encontrei este comentário ao tentar fazer isso no Ubuntu. Parece jogar muito mais bem com os sistemas embutidos do que invadir algo nos scripts de inicialização, pelo menos considerando meu conhecimento de como o sistema deve funcionar.
xiterion

Eu tentei isso no Ubuntu 16.04 LTS. Infelizmente, todo processo shell deseja seu ssh-agentprocesso individual . Talvez eu não tenha conhecimento mesmo depois de ler os documentos.
Daisuke Aramaki

Você também pode usar Type = simple . wiki.archlinux.org/index.php/…
Hans-J. Schmid

2
Então, essa solução é basicamente instalar / configurar um serviço systemd (mas apenas para o usuário)?
Trevor Boyd Smith

SSH_AGENT_PIDPorém, isso não definirá a variável de ambiente :(
MrMeszaros 6/19/19

73

Pergunta antiga, mas me deparei com uma situação semelhante. Não pense que a resposta acima alcança completamente o que é necessário. A peça que falta é keychain; instale-o se ainda não estiver.

sudo apt-get install keychain

Em seguida, adicione a seguinte linha ao seu ~/.bashrc

eval $(keychain --eval id_rsa)

Isso iniciará ssh-agentse não estiver em execução, conecte-se a ele, carregue ossh-agent variáveis ​​de ambiente em seu shell e carregue sua chave ssh.

Altere id_rsapara a chave privada em~/.ssh você deseja carregar.

Referência

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


o chaveiro não funciona para mim de acordo com as instruções fornecidas. Eu adicionei ao .bash_profile e o ssh ainda solicita senha todas as vezes. Eu tentei várias vezes no mesmo shell. sem dados. voltando a abordagem básica ssh-agent
javadba

Adicionar eval keychain --eval id_[yourid file]ao .bashrc
xelber

4
Passei 20 minutos pesquisando uma solução por causa da formatação de comentários do StackOverflow. Por comentário do xelber acima, a solução correta é eval `keychain --eval id_[yourid file]`a .bashrc. Backticks necessários para avaliar as variáveis ​​de ambiente no shell atual para acesso ao ssh-agent em execução.
James

2
Esta é a solução correta e simples. Se você não quiser ver o log quando o comando keychain for executado, poderá adicionar a -qopção para o modo silencioso. Mais informações sobre Keychain: funtoo.org/Keychain
Diki Ananta

4
Thx, esta é de longe a solução mais elegante.
greenspand

37

A solução aceita possui as seguintes desvantagens:

  • é complicado de manter;
  • avalia o arquivo de armazenamento que pode levar a erros ou violação de segurança;
  • ele inicia o agente, mas não o interrompe, o que é equivalente a deixar a chave na ignição.

Se suas chaves não exigirem digitar a senha, sugiro a seguinte solução. Adicione o seguinte ao seu .bash_profile final (edite a lista de chaves de acordo com suas necessidades):

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

Tem as seguintes vantagens:

  • solução muito mais simples;
  • a sessão do agente termina quando a sessão do bash termina.

Tem possíveis desvantagens:

  • interativo ssh-add comando influenciará apenas uma sessão, o que é de fato um problema apenas em circunstâncias muito atípicas;
  • inutilizável se a digitação da senha for necessária;
  • O shell iniciado se torna não-login (o que não influencia em nada o AFAIK).

Observe que vários ssh-agentprocessos não são uma desvantagem, porque eles não levam mais memória ou tempo de CPU.


Eu tenho chaves SSH em um diretório fora de $ HOME no Windows 10, usando o Git Bash. Mudar o caminho para o RSA era tudo o que eu precisava fazer para que isso funcionasse. TYVM!
kayleeFrye_onDeck

7
Eu diria que "Se suas chaves não precisam digitar a senha" é quase o mesmo que deixar a chave na ignição.
de Bruno Bronosky

Pelo menos, está no seu próprio host, não em algum lugar da rede.
midenok

1
"Eu diria que" Se as suas chaves não precisam digitar a senha "é quase o mesmo que deixar a chave na ignição." <- Explique como sim? Como as chaves são muito mais flexíveis que as senhas, é muito mais fácil revogar (o quê? Você está usando chaves apenas para usuários sudo com acesso total? Tsk tsk). Vários conjuntos de chaves para vários perfis de usuários. Se você deseja automatizar qualquer coisa (como implantação ou verificações de ponta a ponta), boa sorte digitando constantemente as senhas durante a "orquestração".
101117 Scott Prive

2
Não faça isso. Chaves sem senha são uma má prática.
user48678

26

Adicione isso ao seu e ~/.bashrc, em seguida, efetue logout e entre novamente para entrar em vigor.

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

Isso deve solicitar apenas uma senha na primeira vez que você fizer login após cada reinicialização. Ele continuará reutilizando o mesmo ssh-agentenquanto permanecer em execução.


O que usaríamos se tivéssemos várias chaves e elas não fossem nomeadas ~/.ssh/id_rsa? Parece que a ssh-addparte da sua resposta espera nomes de arquivos padrão para as chaves.
Gabriel Staples

Sim. Eu acredito que você pode simplesmente adicionar os nomes dos arquivos até o final da última linha, se necessário #
Collin Anderson

Mas você ainda não pode automatizar um script, puxe coisas de git, por exemplo, sem digitar a senha manualmente? Como evitar isso?
trainoasis 9/08/19

7

Então, eu costumava usar as abordagens descritas acima, mas eu meio que prefiro que o agente morra quando minha última sessão do bash termina. Isso é um pouco mais longo que as outras soluções, mas é a minha abordagem preferida. A idéia básica é que a primeira sessão do bash inicie o ssh-agent. Em seguida, cada sessão bash adicional verifica o arquivo de configuração ( ~/.ssh/.agent_env). Se houver e houver uma sessão em execução, origine o ambiente e crie um hardlink para o arquivo de soquete /tmp(precisa estar no mesmo sistema de arquivos que o arquivo de soquete original). À medida que as sessões do bash são encerradas, cada uma exclui seu próprio hardlink. A última sessão a ser concluída constatará que os hardlinks possuem 2 links (o hardlink e o original), a remoção do soquete do próprio processo e a eliminação do processo resultarão em 0, deixando um ambiente limpo após o fechamento da última sessão do 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              

se executarmos isso como um script BASH no login de qualquer outro shell (além do BASH), ele também deve funcionar, certo?
91319 hoijui

7

Só para acrescentar mais uma solução: P, fui com uma combinação das soluções @spheenik e @ 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

Poderia ser um pouco mais elegante, mas é simples e legível. Esta solução:

  • garante que AddKeysToAgent yesestá em sua configuração ssh, para que as chaves sejam adicionadas automaticamente após o uso
  • não solicita a inserção de senhas no login (novamente, a inserção de senhas únicas ocorre no primeiro uso)
  • silenciosamente inicia um agente ssh se ele ainda não iniciou um

Comentários bem-vindos :)


1
Isso funcionou perfeitamente para mim. No Kubuntu, eu o coloquei em .profile.
Shai

1
É bom saber sobre a AddKeysToAgent yesconfiguração. Obrigado.
Collin Anderson

3

Eu o resolvi adicionando isso ao / etc / profile - em todo o sistema (ou ao usuário local .profile ou _.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

Isso inicia um novo ssh-agent se não estiver em execução para o usuário atual ou reconfigura o parâmetro env ssh-agent se estiver em execução.


Obrigado por dizer como saber se o agente já está em execução!
Mike Maxwell

Como funciona o if pgrep -u $WHOAMI $SERVICE >/dev/nulltrabalho?
Josh Desmond

3

Os usuários do shell de peixe podem usar esse script para fazer a mesma coisa.

# 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

Eu uso a ferramenta ssh-ident para isso.

De sua página de manual :

ssh-ident - Inicie e use o ssh-agent e carregue as identidades conforme necessário.


1

Tentei algumas soluções de várias fontes, mas tudo parecia demais. Finalmente eu encontrei o mais fácil :)

Se você ainda não está familiarizado com o zsh e o oh-my-zsh , instale-o. Você vai adorar :)

Então edite .zshrc

vim ~/.zshrc

encontre a pluginsseção e atualize-a para usar da seguinte ssh-agentmaneira:

plugins=(ssh-agent git)

E isso é tudo! Você estará ssh-agentem funcionamento toda vez que iniciar seu shell


1

Eu gosto muito das suas respostas. Tornou o trabalho dos cygwin / linuxhosts muito mais fácil. Combinei as funções de início e fim para torná-lo seguro.

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.