Avviare ssh-agent all'accesso


262

Ho un sito come repository Git remoto che estrae da Bitbucket.com usando un alias SSH. Posso avviare manualmente ssh-agent sul mio server, ma devo farlo ogni volta che accedo tramite SSH.

Avvio manuale di ssh-agent:

eval ssh-agent $SHELL

Quindi aggiungo l'agente:

ssh-add ~/.ssh/bitbucket_id

Quindi viene visualizzato quando lo faccio:

ssh-add -l

E sono a posto. Esiste un modo per automatizzare questo processo, quindi non devo farlo ogni volta che eseguo l'accesso? Il server esegue RedHat 6.2 (Santiago).


2
Qualunque cosa tu voglia fare ogni volta che esegui il login, dovrebbe essere in .profile (login terminali) o .xinitrc (per accessi GUI).
Barmar,

1
Ah! Stavo usando .bash_profile ... Qual è la differenza tra .profile e .bash_profile?
Pathsofdesign,

1
Non so perché stai eseguendo il comando in quel modo in primo luogo. ssh-agent <command>viene eseguito <command>come sottoprocesso di ssh-agent, quindi stai avviando una nuova shell. Penso che tu voglia eval ssh-agent.
Barmar,

9
.bash_profileè specifico per bash, .profileè generico per tutte le shell POSIX. bashcercherà prima .bash_profile, poi di default .profile.
Barmar,

5
Il modo corretto di generare ssh-agentuna shell "standard" (compatibile con POSIX) è eval $(ssh-agent -s). Nota anche che devi assicurarti di sbarazzarti correttamente dell'agente quando ti disconnetti, quindi è anche consigliabile inserire il trap 'kill $SSH_AGENT_PID' EXITtuo .profileafter-line che avvia l'agente.
kostix,

Risposte:


368

Si prega di leggere questo articolo. Potresti trovare questo molto utile:

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

Nel caso in cui il link sopra svanisse un giorno, sto catturando il pezzo principale della soluzione di seguito:

Questa soluzione di Joseph M. Reagle tramite Daniel Starin:

Aggiungi questo seguito al tuo .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

Questa versione è particolarmente bella poiché vedrà se hai già avviato ssh-agent e, se non la trova, la avvierà e memorizzerà le impostazioni in modo che siano utilizzabili la prossima volta che avvii un conchiglia.


8
Il riavvio della macchina non è necessario. Puoi semplicemente ricaricare .bash_profileusando source ~/.bash_profilenella tua sessione di shell corrente. Il riavvio della macchina funzionerà anche perché caricherà comunque la nuova configurazione.
tornasole

11
Usa SSH_ENV="$HOME/.ssh/env"(es. Semplicemente / ambiente) Perché? sshd usa ~ / .ssh / environment (vedi la pagina man: PermitUserEnvironment). Github lo consiglia anche nella sua soluzione - help.github.com/articles/…
Andrew Murphy,

7
Questo script ha funzionato per me quando l'ho inserito nel mio file ~ / .bashrc (non nel mio ~ / .profile o ~ / .bash_profile). La prima volta che apro una console locale richiede la passphrase, tutto funziona da quel momento in poi senza ulteriori richieste. Saluti.
Andrew Pate,

3
Aggiungendo il ssh-agentcomando start in .bashrc il scpcomando non funzionerà.
Dzanvu,

5
Ancora fastidioso ... devi farlo ogni volta che accedi ... anche se non usi ssh. Devi spegnere questo fuoco ogni volta che viene chiamato ssh ... e idealmente, dovresti essere in grado di configurare quali host causano quali chiavi caricare.
Erik Aronesty,

99

Su Arch Linux, il seguente funziona davvero alla grande (dovrebbe funzionare su tutte le distribuzioni basate su systemd):

Creare un servizio utente systemd, mettendo quanto segue a ~/.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 di installazione per avere una variabile d'ambiente per socket ( .bash_profile, .zshrc, ...):

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

Abilita il servizio, quindi verrà avviato automaticamente all'accesso e avviarlo:

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

Aggiungi la seguente impostazione di configurazione al tuo file di configurazione ssh locale ~/.ssh/config(funziona da SSH 7.2):

AddKeysToAgent  yes

Questo indicherà al client ssh di aggiungere sempre la chiave a un agente in esecuzione, quindi non è necessario aggiungerlo in anticipo.


3
Ho trovato questo commento mentre cercavo di farlo in Ubuntu. Sembra giocare molto più bene con i sistemi integrati che hackerare qualcosa negli script di avvio, almeno data la mia conoscenza di come dovrebbe funzionare il sistema.
xiterion

Ho provato questo su Ubuntu 16.04 LTS. Sfortunatamente, ogni processo di shell vuole il suo ssh-agentprocesso individuale . Forse mi manca la conoscenza anche dopo aver letto i documenti.
Daisuke Aramaki,

Puoi anche usare Type = simple . wiki.archlinux.org/index.php/…
Hans-J. Schmid

2
quindi questa soluzione fondamentalmente sta installando / configurando un servizio systemd (ma solo per l'utente)?
Trevor Boyd Smith,

Questo non imposterà la SSH_AGENT_PIDvariabile d'ambiente, però :(
MrMeszaros

73

Vecchia domanda, ma mi sono imbattuto in una situazione simile. Non pensare che la risposta di cui sopra raggiunga pienamente ciò che è necessario. Il pezzo mancante è keychain; installalo se non lo è già.

sudo apt-get install keychain

Quindi aggiungi la seguente riga alla tua ~/.bashrc

eval $(keychain --eval id_rsa)

Questo avvierà ssh-agentse non è in esecuzione, connettersi ad esso se lo è, caricare le ssh-agentvariabili di ambiente nella shell e caricare la chiave ssh.

Passare id_rsaa qualsiasi chiave privata in cui ~/.sshsi desidera caricare.

Riferimento

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


il portachiavi non funziona per me secondo le istruzioni fornite. Ho aggiunto a .bash_profile e ssh chiede ancora ogni volta la password. l'ho provato più volte nella stessa shell. niente da fare. tornando all'approccio ssh-agent di base
javadba,

Aggiungi eval keychain --eval id_[yourid file]a .bashrc
xelber

4
Ho impiegato 20 minuti a cercare una soluzione grazie alla formattazione dei commenti StackOverflow. Per il commento di xelber sopra, la soluzione corretta è eval `keychain --eval id_[yourid file]`a .bashrc. Backtick richiesti per valutare le variabili di ambiente nella shell corrente per l'accesso allo ssh-agent in esecuzione.
James,

2
Questa è la soluzione corretta e semplice. Se non si desidera visualizzare il registro quando viene eseguito il comando portachiavi, è possibile aggiungere -qun'opzione per la modalità silenziosa. Maggiori informazioni su Portachiavi: funtoo.org/Keychain
Diki Ananta

4
Grazie, questa è di gran lunga la soluzione più elegante.
Greenspand,

37

La soluzione accettata presenta i seguenti svantaggi:

  • è complicato da mantenere;
  • valuta il file di archiviazione che può causare errori o violazioni della sicurezza;
  • avvia l'agente ma non lo ferma, il che equivale a lasciare la chiave in accensione.

Se le tue chiavi non richiedono di digitare la password, ti suggerisco la seguente soluzione. Aggiungi quanto segue alla tua .bash_profile fine (modifica l'elenco delle chiavi in ​​base alle tue esigenze):

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

Ha i seguenti vantaggi:

  • soluzione molto più semplice;
  • la sessione agent termina quando termina la sessione bash.

Ha possibili svantaggi:

  • il ssh-addcomando interattivo influenzerà solo una sessione, che in realtà è un problema solo in circostanze molto atipiche;
  • inutilizzabile se è richiesta la password di digitazione;
  • la shell avviata diventa non login (che non influenza nulla di AFAIK).

Si noti che diversi ssh-agentprocessi non rappresentano uno svantaggio, poiché non richiedono più tempo di memoria o CPU.


Ho le chiavi SSH in una directory fuori da $ HOME in Windows 10, usando Git Bash. Cambiare il percorso verso RSA era tutto ciò che dovevo fare per farlo funzionare. TYVM!
kayleeFrye_onDeck

7
Direi che "Se le tue chiavi non richiedono di digitare la password" è quasi equivalente a lasciare la chiave in accensione.
Bruno Bronosky,

Almeno, è sul tuo host, non da qualche parte sulla rete.
midenok

1
"Direi che" Se le tue chiavi non richiedono di digitare la password "è quasi equivalente a lasciare la chiave in accensione." <- Spiega come ?? Poiché le chiavi sono molto più flessibili delle password, molto più facili da revocare (cosa? Stai usando solo le chiavi per gli utenti sudo con accesso completo? Tsk tsk). Più set di chiavi per più profili di utenti. Se si desidera automatizzare qualsiasi cosa (come la distribuzione o i controlli end-to-end), allora buona fortuna digitando costantemente le password durante "l'orchestrazione".
Scott Prive,

2
Non farlo. Le chiavi senza password sono una cattiva pratica.
user48678,

26

Aggiungi questo al tuo ~/.bashrc, quindi disconnettiti e accedi nuovamente per rendere effettive.

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

Questo dovrebbe richiedere una password solo al primo accesso dopo ogni riavvio. Continuerà a riutilizzare lo stesso ssh-agentfinché rimane in esecuzione.


Cosa useremmo invece se avessimo più chiavi e non fossero state nominate ~/.ssh/id_rsa? Sembra che la ssh-addparte della risposta si aspetti nomi di file predefiniti per le chiavi.
Gabriel Staples,

Sì. Credo che puoi semplicemente aggiungere i nomi dei file fino alla fine dell'ultima riga, se necessario
Collin Anderson,

Ma non riesci ancora ad automatizzare uno script, ad esempio estraendo roba git senza inserire manualmente la password? Come evitarlo?
trainoasi,

7

Quindi usavo gli approcci descritti sopra, ma preferisco che l'agente muoia quando termina la mia ultima sessione di bash. Questo è un po 'più lungo rispetto alle altre soluzioni, ma è il mio approccio preferito. L'idea di base è che la prima sessione bash avvia l'agente ssh. Quindi ogni sessione bash aggiuntiva controlla il file config ( ~/.ssh/.agent_env). Se è presente e c'è una sessione in esecuzione, procurarsi l'ambiente e creare un collegamento reale al file socket /tmp(deve trovarsi sullo stesso filesystem del file socket originale). Mentre le sessioni di bash chiudono, ciascuna elimina il proprio hardlink. L'ultima sessione da chiudere troverà che gli hardlink hanno 2 collegamenti (l'hardlink e l'originale), la rimozione del proprio socket dei processi e l'uccisione del processo comporteranno 0, lasciando un ambiente pulito dopo la chiusura dell'ultima sessione 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 eseguiamo questo come uno script BASH all'accesso di qualsiasi altra shell (diversa da BASH), dovrebbe funzionare anche, giusto?
hoijui,

7

Solo per aggiungere un'altra soluzione: P, sono andato con una combinazione delle soluzioni di @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

Potrebbe essere un po 'più elegante ma è semplice e leggibile. Questa soluzione:

  • assicura che AddKeysToAgent yessia nella tua configurazione SSH, quindi le chiavi verranno automaticamente aggiunte al momento dell'uso
  • non richiede di inserire alcuna passphrase al momento dell'accesso (di nuovo, l'immissione della passphrase una tantum si verifica al primo utilizzo)
  • avvia silenziosamente un agente ssh se non ne ha già avviato uno

Commenti benvenuti :)


1
Ha funzionato perfettamente per me. Su Kubuntu l'ho messo in .profile.
Shai,

1
Buono a sapersi AddKeysToAgent yessull'impostazione. Grazie.
Collin Anderson,

3

L'ho risolto aggiungendo questo al / etc / profile - a livello di sistema (o all'utente .profile locale , o _.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

Questo avvia un nuovo ssh-agent se non è in esecuzione per l'utente corrente o reimposta il parametro env ssh-agent se in esecuzione.


Grazie per aver detto come dire se l'agente è già in esecuzione!
Mike Maxwell,

Come if pgrep -u $WHOAMI $SERVICE >/dev/nullfunziona
Josh Desmond,

3

Gli utenti del guscio di pesce possono usare questo script per fare la stessa cosa.

# 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

Uso ssh-ident strumento .

Dalla sua pagina man :

ssh-ident - Avvia e usa ssh-agent e carica le identità se necessario.


1

Ho provato soluzioni di coppia da molte fonti, ma sembravano tutti troppi problemi. Finalmente ho trovato il più semplice :)

Se non hai ancora familiarità con zsh e oh-my-zsh, installalo. Lo amerai :)

Quindi modifica .zshrc

vim ~/.zshrc

trova la pluginssezione e aggiornala per usarla in questo ssh-agentmodo:

plugins=(ssh-agent git)

E questo è tutto! Avrai ssh-agentinstallato e funzionante ogni volta che avvii la shell


1

Mi piacciono molto le tue risposte. Ha reso il lavoro dagli cygwin / linuxhost molto più semplice. Ho combinato le funzioni di inizio e fine per renderlo sicuro.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.