Запустите ssh-agent при входе в систему


262

У меня есть сайт в качестве удаленного репозитория Git, извлекаемого из Bitbucket.com с использованием псевдонима SSH. Я могу вручную запустить ssh-agent на моем сервере, но я должен делать это каждый раз, когда я вхожу через SSH.

Я вручную запускаю ssh-agent:

eval ssh-agent $SHELL

Затем я добавляю агента:

ssh-add ~/.ssh/bitbucket_id

Тогда это появляется, когда я делаю:

ssh-add -l

И мне хорошо идти. Есть ли способ автоматизировать этот процесс, чтобы мне не приходилось делать это каждый раз, когда я вхожу в систему? Сервер работает RedHat 6.2 (Сантьяго).


2
Все, что вы хотите делать при каждом входе в систему, должно быть в .profile (входы в систему с терминала) или .xinitrc (для входа в систему через GUI).
Бармар

1
Ах! Я использовал .bash_profile ... В чем разница между .profile и .bash_profile?
Pathsofdesign

1
Не уверен, почему вы запускаете команду именно таким образом. ssh-agent <command>выполняется <command>как подпроцесс ssh-agent, поэтому вы запускаете новую оболочку. Я думаю, что вы хотите eval ssh-agent.
Бармар

9
.bash_profileспецифичен для bash, .profileуниверсален для всех оболочек POSIX. bashбудет искать сначала .bash_profile, затем по умолчанию .profile.
Бармар

5
Правильный путь к икре ssh-agentдля «стандартного» (POSIX-совместимой) оболочки eval $(ssh-agent -s). Отметим также , что вы должны убедиться , что вы правильно избавиться от агента при входе в систему, так что это также желательно , чтобы положить trap 'kill $SSH_AGENT_PID' EXITв вашем .profileпосле строки , которая запускает агент.
kostix

Ответы:


368

Пожалуйста, просмотрите эту статью. Вы можете найти это очень полезным:

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

На случай, если однажды приведенная ссылка исчезнет однажды, я перехватываю основную часть решения ниже:

Это решение от Джозефа М. Рейгла с помощью Даниэля Старина:

Добавьте это следующее к вашему .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в вашей текущей сессии оболочки. Перезагрузка машины также будет работать, потому что это все равно загрузит новый конфиг.
Лакмус

11
Использовать SSH_ENV="$HOME/.ssh/env"(то есть просто нет / среда) Почему? sshd использует ~ / .ssh / environment (см. справочную страницу: PermitUserEnvironment). Github также рекомендует это в своем решении - help.github.com/articles/…
Эндрю Мерфи

7
Этот скрипт сработал для меня, когда я поместил его в мой файл ~ / .bashrc (не мой ~ / .profile или ~ / .bash_profile). Когда я в первый раз открываю локальную консоль, она запрашивает парольную фразу, с этого момента все работает без дальнейших запросов. Приветствия.
Эндрю Пэйт

3
Добавление команды ssh-agentзапуска в .bashrc приведет к тому, что scpкоманда не будет работать.
Дзанву

5
Все еще раздражает ... вы должны делать это каждый раз, когда вы входите в систему ... даже если вы не используете ssh. Необходимо выключать этот огонь каждый раз, когда вызывается ssh ... и в идеале вы должны быть в состоянии настроить, какие хосты вызывают какие ключи загружать.
Эрик Аронесты

99

В Arch Linux следующие функции работают очень хорошо (должны работать на всех системных дистрибутивах):

Создайте службу пользователя systemd, добавив следующее ~/.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

Настройте оболочку, чтобы иметь переменную окружения для socket ( .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.


3
Я нашел этот комментарий, пытаясь сделать это в Ubuntu. Похоже, что играть со встроенными системами гораздо приятнее, чем взламывать что-то в скриптах запуска, по крайней мере, учитывая мои знания о том, как должна работать система.
xiterion

Я попробовал это на Ubuntu 16.04 LTS. К сожалению, каждый процесс оболочки требует своего отдельного ssh-agentпроцесса. Возможно, мне не хватает знаний даже после прочтения документации.
Дайсуке Арамаки

Вы также можете использовать Type = simple . wiki.archlinux.org/index.php/…
Hans-J. Шмид

2
так это решение в основном устанавливает / настраивает службу systemd (но только для пользователя)?
Тревор Бойд Смит

Это не будет устанавливать 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

Добавьте eval keychain --eval id_[yourid file]в .bashrc
xelber,

4
Я потратил 20 минут на поиски решения из-за форматирования комментариев StackOverflow. Согласно приведенному выше комментарию xelber, правильное решение - eval `keychain --eval id_[yourid file]`это .bashrc. Обратные пометки необходимы для оценки переменных среды в текущей оболочке для доступа к запущенному ssh-agent.
Джеймс

2
Это правильное и простое решение. Если вы не хотите видеть журнал при выполнении команды цепочки для ключей, вы можете добавить -qопцию для тихого режима. Больше информации о связке ключей: funtoo.org/Keychain
Дики Ананта

4
Спасибо, это, безусловно, самое элегантное решение.
Гринспенд

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процессы не являются недостатком, поскольку они не занимают больше памяти или процессорного времени.


У меня есть ключи SSH в каталоге за пределами $ HOME в Windows 10 с использованием Git Bash. Мне нужно было изменить путь к RSA, чтобы это работало. TYVM!
kayleeFrye_onDeck

7
Я бы сказал, что «если ваши ключи не требуют ввода пароля» - это почти то же самое, что оставить ключ в замке зажигания.
Бруно Броноски

По крайней мере, это на вашем собственном хосте, а не где-то в сети.
Миденок

1
«Я бы сказал, что« Если ваши ключи не требуют ввода пароля », это почти равносильно тому, чтобы оставить ключ в замке зажигания». <- Объясните, как это так ?? Поскольку ключи гораздо более гибкие, чем пароли, их гораздо легче отозвать (что? Вы используете ключи только для пользователей sudo с полным доступом? Tsk tsk). Несколько наборов ключей для нескольких профилей пользователей. Если вы хотите автоматизировать что-либо (например, развертывание или сквозные проверки), тогда удачи вам постоянно вводить пароли во время «оркестровки».
Скотт Прайв

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часть вашего ответа ожидает имена файлов по умолчанию для ключей.
Габриэль Стейплз

Ага. Я считаю, что вы можете просто добавить имена файлов в самый конец последней строки, если это необходимо
Коллин Андерсон

Но вы все еще не можете автоматизировать сценарий, например, использовать git, не вводя пароль вручную? Как этого избежать?
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

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
Это отлично сработало для меня. На Kubuntu я положил его в .profile.
Шай

1
Полезно знать об AddKeysToAgent yesобстановке. Спасибо.
Коллин Андерсон

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, если он не запущен для текущего пользователя, или переустанавливает параметр env ssh-agent, если работает.


Спасибо, что сказали, как определить, запущен ли агент!
Майк Максвелл

Как if pgrep -u $WHOAMI $SERVICE >/dev/nullработает?
Джош Десмонд

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 для этого.

С его man- страницы:

ssh-ident - Запустите и используйте ssh-agent и загружайте удостоверения по мере необходимости.


1

Пробовал пару решений из многих источников, но все казалось слишком большим количеством проблем. Наконец я нашел самый простой :)

Если вы еще не знакомы с zsh и oh-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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.