Starten Sie ssh-agent beim Login


262

Ich habe eine Site als Remote-Git-Repo, die mit einem SSH-Alias ​​von Bitbucket.com abgerufen wird. Ich kann den ssh-agent manuell auf meinem Server starten, muss dies jedoch jedes Mal tun, wenn ich mich über SSH anmelde.

Ich starte den ssh-agent manuell:

eval ssh-agent $SHELL

Dann füge ich den Agenten hinzu:

ssh-add ~/.ssh/bitbucket_id

Dann zeigt es sich, wenn ich es tue:

ssh-add -l

Und ich bin gut zu gehen. Gibt es eine Möglichkeit, diesen Prozess zu automatisieren, damit ich ihn nicht jedes Mal ausführen muss, wenn ich mich anmelde? Auf dem Server wird RedHat 6.2 (Santiago) ausgeführt.


2
Alles, was Sie bei jeder Anmeldung tun möchten, sollte in .profile (Terminal-Anmeldungen) oder .xinitrc (für GUI-Anmeldungen) erfolgen.
Barmar

1
Ah! Ich habe .bash_profile verwendet ... Was ist der Unterschied zwischen .profile und .bash_profile?
Pathsofdesign

1
Ich bin mir nicht sicher, warum Sie den Befehl überhaupt so ausführen. ssh-agent <command>Wird <command>als Unterprozess von ausgeführt ssh-agent, sodass Sie eine neue Shell starten. Ich denke du willst eval ssh-agent.
Barmar

9
.bash_profileist spezifisch für Bash, .profileist generisch für alle POSIX-Shells. bashsucht zuerst nach .bash_profile, dann standardmäßig nach .profile.
Barmar

5
Der richtige Weg, um ssh-agentfür eine "Standard" -Shell (POSIX-kompatibel) zu spawnen, ist eval $(ssh-agent -s). Beachten Sie auch, dass Sie sicherstellen müssen, dass Sie den Agenten ordnungsgemäß entfernen, wenn Sie sich abmelden. Daher ist es auch ratsam, nach der Zeile, in der der Agent gestartet wird, einen trap 'kill $SSH_AGENT_PID' EXITEintrag .profileeinzugeben.
Kostix

Antworten:


368

Bitte gehen Sie diesen Artikel durch. Sie können dies sehr nützlich finden:

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

Für den Fall, dass der obige Link eines Tages verschwindet, fasse ich das Hauptelement der folgenden Lösung zusammen:

Diese Lösung von Joseph M. Reagle über Daniel Starin:

Fügen Sie dies Ihrem hinzu .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

Diese Version ist besonders schön, da sie anzeigt, ob Sie ssh-agent bereits gestartet haben. Wenn es nicht gefunden wird, wird es gestartet und die Einstellungen werden gespeichert, damit sie beim nächsten Start von a verwendet werden können Schale.


8
Ein Neustart der Maschine ist nicht erforderlich. Sie können einfach nachladen .bash_profilemit source ~/.bash_profilein der aktuellen Shell - Sitzung. Der Neustart des Computers funktioniert auch, da dadurch die neue Konfiguration trotzdem geladen wird.
Lackmus

11
Verwenden Sie SSH_ENV="$HOME/.ssh/env"(dh nur nicht / Umgebung) Warum? sshd verwendet ~ / .ssh / environment (siehe Manpage: PermitUserEnvironment). Github empfiehlt dies auch in ihrer Lösung - help.github.com/articles/…
Andrew Murphy

7
Dieses Skript hat bei mir funktioniert, als ich es in meine ~ / .bashrc-Datei eingefügt habe (nicht in mein ~ / .profile oder ~ / .bash_profile). Wenn ich zum ersten Mal eine lokale Konsole öffne, die zur Eingabe der Passphrase auffordert, funktioniert ab diesem Zeitpunkt alles ohne weitere Aufforderung. Prost.
Andrew Pate

3
Durch Hinzufügen des ssh-agentStartbefehls in .bashrc funktioniert der scpBefehl nicht.
Dzanvu

5
Immer noch ärgerlich ... Sie müssen dies jedes Mal tun, wenn Sie sich anmelden ... auch wenn Sie ssh nicht verwenden. Sie müssen dieses Feuer jedes Mal ausschalten, wenn ssh aufgerufen wird ... und im Idealfall sollten Sie in der Lage sein, zu konfigurieren, welche Hosts welche Schlüssel laden.
Erik Aronesty

98

Unter Arch Linux funktioniert Folgendes wirklich gut (sollte auf allen systemd-basierten Distributionen funktionieren):

Erstellen Sie einen systemd-Benutzerdienst, indem Sie Folgendes auf Folgendes setzen ~/.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

Setup-Shell mit einer Umgebungsvariablen für den Socket ( .bash_profile, .zshrc, ...):

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

Aktivieren Sie den Dienst, damit er beim Anmelden automatisch gestartet wird, und starten Sie ihn:

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

Fügen Sie Ihrer lokalen ~/.ssh/configSSH- Konfigurationsdatei die folgende Konfigurationseinstellung hinzu (dies funktioniert seit SSH 7.2):

AddKeysToAgent  yes

Dadurch wird der ssh-Client angewiesen, den Schlüssel immer einem laufenden Agenten hinzuzufügen, sodass es nicht erforderlich ist, ihn vorher ssh-hinzuzufügen.


3
Ich habe diesen Kommentar gefunden, als ich versucht habe, dies in Ubuntu zu tun. Es scheint viel besser mit den eingebauten Systemen zu spielen, als etwas in die Startskripte zu hacken, zumindest angesichts meines Wissens darüber, wie das System funktionieren sollte.
Xiterion

Ich habe dies unter Ubuntu 16.04 LTS versucht. Leider will jeder Shell-Prozess seinen individuellen ssh-agentProzess. Vielleicht fehlt mir das Wissen auch nach dem Lesen der Dokumente.
Daisuke Aramaki

Sie können auch Type = simple verwenden . wiki.archlinux.org/index.php/…
Hans-J. Schmid

2
Ist diese Lösung also im Grunde genommen die Installation / Konfiguration eines systemd-Dienstes (aber nur für den Benutzer)?
Trevor Boyd Smith

Dies wird jedoch nicht die SSH_AGENT_PIDUmgebungsvariable setzen :(
MrMeszaros

73

Alte Frage, aber ich bin auf eine ähnliche Situation gestoßen. Denken Sie nicht, dass die obige Antwort das erreicht, was benötigt wird. Das fehlende Stück ist keychain; Installieren Sie es, wenn es noch nicht geschehen ist.

sudo apt-get install keychain

Fügen Sie dann die folgende Zeile zu Ihrem hinzu ~/.bashrc

eval $(keychain --eval id_rsa)

Dadurch wird das gestartet, ssh-agentwenn es nicht ausgeführt wird, eine Verbindung hergestellt, wenn dies der Fall ist, die ssh-agentUmgebungsvariablen in Ihre Shell geladen und der SSH-Schlüssel geladen.

Wechseln Sie id_rsazu dem privaten Schlüssel, den ~/.sshSie laden möchten.

Referenz

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


Schlüsselbund funktioniert bei mir nicht gemäß den gegebenen Anweisungen. Ich habe zu .bash_profile hinzugefügt und ssh fragt immer noch jedes Mal nach dem Passwort. Ich habe es mehrmals in derselben Shell versucht. kein Würfel. Zurück zum grundlegenden SSH-Agent-Ansatz
Javadba

Fügen Sie eval keychain --eval id_[yourid file]zu .bashrc
xelber

4
Aufgrund der Formatierung der StackOverflow-Kommentare habe ich 20 Minuten lang nach einer Lösung gesucht. Gemäß dem obigen Kommentar von xelber ist die richtige Lösung eval `keychain --eval id_[yourid file]`zu .bashrc. Backticks erforderlich, um die Umgebungsvariablen für den Zugriff auf den laufenden ssh-agent in der aktuellen Shell auszuwerten.
James

2
Dies ist die richtige und einfache Lösung. Wenn Sie das Protokoll nicht sehen möchten, wenn der Schlüsselbundbefehl ausgeführt wird, können Sie eine -qOption für den stillen Modus hinzufügen . Weitere Informationen über Schlüsselbund: funtoo.org/Keychain
Diki Ananta

4
Thx, das ist bei weitem die eleganteste Lösung.
Greenspand

37

Die akzeptierte Lösung hat folgende Nachteile:

  • es ist kompliziert zu pflegen;
  • Es wertet die Speicherdatei aus, die zu Fehlern oder Sicherheitsverletzungen führen kann.
  • Es startet den Agenten, stoppt ihn jedoch nicht. Dies entspricht in etwa dem Verlassen des Zündschlüssels.

Wenn für Ihre Schlüssel kein Kennwort eingegeben werden muss, empfehle ich die folgende Lösung. Fügen Sie Ihrem .bash_profile Ende Folgendes hinzu (bearbeiten Sie die Schlüsselliste nach Ihren Wünschen):

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

Es hat folgende Vorteile:

  • viel einfachere Lösung;
  • Die Agentensitzung endet, wenn die Bash-Sitzung endet.

Es hat mögliche Nachteile:

  • Der interaktive ssh-addBefehl beeinflusst nur eine Sitzung, was in der Tat nur unter sehr untypischen Umständen ein Problem darstellt.
  • unbrauchbar, wenn die Eingabe eines Passworts erforderlich ist;
  • Die gestartete Shell wird nicht mehr angemeldet (was keinen Einfluss auf AFAIK hat).

Beachten Sie, dass mehrere ssh-agentProzesse kein Nachteil sind, da sie nicht mehr Speicher oder CPU-Zeit benötigen.


Ich habe SSH-Schlüssel in einem Verzeichnis außerhalb von $ HOME in Windows 10 mit Git Bash. Ich musste nur den Pfad zum RSA ändern, um dies zum Laufen zu bringen. TYVM!
KayleeFrye_onDeck

7
Ich würde argumentieren, dass "Wenn für Ihre Schlüssel kein Kennwort eingegeben werden muss" in etwa dem Belassen des Schlüssels in der Zündung entspricht.
Bruno Bronosky

Zumindest befindet es sich auf Ihrem eigenen Host, nicht irgendwo im Netzwerk.
Midenok

1
"Ich würde argumentieren, dass" Wenn für Ihre Schlüssel kein Kennwort eingegeben werden muss "fast gleichbedeutend damit ist, den Schlüssel in der Zündung zu lassen." <- Erklären Sie, wie das so ist? Da Schlüssel viel flexibler als Passwörter sind und viel einfacher zu widerrufen sind (was? Sie verwenden Schlüssel nur für Sudo-Benutzer mit vollem Zugriff? Tsk tsk). Mehrere Schlüsselsätze für mehrere Benutzerprofile. Wenn Sie etwas automatisieren möchten (z. B. Bereitstellung oder End-to-End-Überprüfungen), müssen Sie während der "Orchestrierung" ständig Passwörter eingeben.
Scott Prive

2
Tu das nicht. Passwortlose Schlüssel sind eine schlechte Praxis.
user48678

26

Fügen Sie dies zu Ihrem hinzu ~/.bashrc, melden Sie sich dann ab und wieder an, um wirksam zu werden.

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

Dies sollte nur bei der ersten Anmeldung nach jedem Neustart zur Eingabe eines Kennworts führen. Es wird ssh-agentso lange wiederverwendet, wie es läuft.


Was würden wir stattdessen verwenden, wenn wir mehrere Schlüssel hätten und diese nicht benannt würden ~/.ssh/id_rsa? Es scheint, dass der ssh-addTeil Ihrer Antwort Standarddateinamen für die Schlüssel erwartet.
Gabriel Staples

Jep. Ich glaube, Sie können die Dateinamen bei Bedarf einfach bis zum Ende der letzten Zeile einfügen
Collin Anderson

Aber Sie können ein Skript immer noch nicht automatisieren. Ziehen Sie beispielsweise Git-Sachen, ohne das Passwort manuell einzugeben? Wie vermeide ich das?
Trainoasis

7

Also habe ich die oben beschriebenen Ansätze verwendet, aber ich bevorzuge es, dass der Agent stirbt, wenn meine letzte Bash-Sitzung endet. Dies ist etwas länger als die anderen Lösungen, aber es ist mein bevorzugter Ansatz. Die Grundidee ist, dass die erste Bash-Sitzung den SSH-Agenten startet. Anschließend sucht jede weitere Bash-Sitzung nach der Konfigurationsdatei ( ~/.ssh/.agent_env). Wenn dies vorhanden ist und eine Sitzung ausgeführt wird, geben Sie die Umgebung als Quelle ein und erstellen Sie einen Hardlink zur Socket-Datei in /tmp(muss sich im selben Dateisystem wie die ursprüngliche Socket-Datei befinden). Beim Herunterfahren von Bash-Sitzungen löscht jeder seinen eigenen Hardlink. Die letzte Sitzung, die geschlossen werden soll, stellt fest, dass die Hardlinks über 2 Links verfügen (den Hardlink und das Original). Das Entfernen des prozesseigenen Sockets und das Beenden des Prozesses führen zu 0 und hinterlassen nach dem Schließen der letzten Bash-Sitzung eine saubere Umgebung.

# 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              

Wenn wir dies als BASH-Skript beim Anmelden einer anderen Shell (außer BASH) ausführen, sollte es auch funktionieren, oder?
Hoijui

7

Um noch eine weitere Lösung hinzuzufügen: P, ich habe mich für eine Kombination der Lösungen von @spheenik und @ collin-anderson entschieden.

 # 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

Könnte etwas eleganter sein, ist aber einfach und lesbar. Diese Lösung:

  • stellt sicher AddKeysToAgent yes es sich in Ihrer SSH-Konfiguration befindet, sodass Schlüssel bei Verwendung automatisch hinzugefügt werden
  • fordert Sie bei der Anmeldung nicht zur Eingabe von Passphrasen auf (erneut erfolgt die einmalige Eingabe von Passphrasen bei der ersten Verwendung).
  • Startet stillschweigend einen SSH-Agenten, falls er noch keinen gestartet hat

Kommentare willkommen :)


1
Das hat bei mir perfekt funktioniert. Auf Kubuntu habe ich es in .profile gesetzt.
Shai

1
Gut zu wissen über die AddKeysToAgent yesEinstellung. Vielen Dank.
Collin Anderson

3

Ich habe es gelöst, indem ich dies systemweit zum / etc / profile (oder zum lokalen .profile des Benutzers oder _.bash_profile_) hinzugefügt habe:

# 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

Dadurch wird ein neuer ssh-agent gestartet, wenn er nicht für den aktuellen Benutzer ausgeführt wird, oder der Parameter ssh-agent env wird zurückgesetzt, wenn er ausgeführt wird.


Vielen Dank, dass Sie gesagt haben, wie Sie feststellen können, ob der Agent bereits ausgeführt wird!
Mike Maxwell

Wie geht das if pgrep -u $WHOAMI $SERVICE >/dev/null ?
Josh Desmond

3

Benutzer der Fischschale können dieses Skript verwenden , um dasselbe zu tun.

# 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

Ich benutze die ssh-ident Tool.

Von ihrem Mann -page:

ssh-ident - Startet und verwendet ssh-agent und lädt Identitäten nach Bedarf.


1

Versuchte paar Lösungen aus vielen Quellen, aber alle schienen zu viel Mühe. Endlich habe ich den einfachsten gefunden :)

Wenn Sie mit zsh und oh-my-zsh noch nicht vertraut sind, installieren Sie es. Du wirst es lieben :)

Dann bearbeiten .zshrc

vim ~/.zshrc

Suchen Sie den pluginsAbschnitt und aktualisieren Sie ihn, um ihn ssh-agentwie folgt zu verwenden :

plugins=(ssh-agent git)

Und das ist alles! Sie müssen ssh-agentjedes Mal, wenn Sie Ihre Shell starten, einsatzbereit sein


1

Ich mag deine Antworten sehr. cygwin / linuxDies erleichterte die Arbeit von Hosts erheblich. Ich habe Start- und Endfunktionen kombiniert, um die Sicherheit zu gewährleisten.

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.