Запустіть ssh-агент під час входу


262

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

Я вручну запускаю ssh-агент:

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-агент, і якщо він не зможе його знайти, запустить його і збереже налаштування, щоб вони були корисні наступного разу, коли ви запустите a оболонки.


8
Перезапуск машини не потрібен. Ви можете просто перезавантажити .bash_profileза допомогою source ~/.bash_profileсвого поточного сеансу оболонки. Перезапуск машини також буде працювати, оскільки це все одно завантажить нову конфігурацію.
Лакмус

11
Використання SSH_ENV="$HOME/.ssh/env"(тобто просто не / середовище) Чому? sshd використовує ~ / .ssh / середовище (див. сторінку людини: PermitUserEnvironment). Github також рекомендує це у своєму рішенні - help.github.com/articles/…
Ендрю Мерфі

7
Цей скрипт працював для мене, коли я поміщав його у свій файл ~ / .bashrc (не мій ~ / .profile чи ~ / .bash_profile). Перший раз, коли я відкриваю локальну консоль, на якій пропонується ввести парольну фразу, з цього моменту все працює без подальшого запиту. Ура.
андрю паштет

3
Якщо додати команду ssh-agentstart у .bashrc, scpкоманда не працює.
Дзанву

5
Все ще дратує ... ви повинні робити це кожного разу, коли ви входите в систему ... навіть якщо ви не використовуєте ssh. Потрібно вимикати цей пожежу щоразу, коли викликається ssh ... і в ідеалі ви повинні мати можливість налаштувати, які хости викликають, які ключі завантажувати.
Ерік Аронесті

97

В 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

Оболонка установки, щоб мати змінну середовища для 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-клієнту завжди додавати ключ до запущеного агента, тому не потрібно заздалегідь додавати його.


3
Я знайшов цей коментар, намагаючись зробити це в Ubuntu. Здається, грати набагато приємніше із вбудованими системами, ніж щось злому в сценарії запуску, принаймні з огляду на мої знання про те, як система повинна працювати.
xiterion

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

Ви також можете використовувати Type = простий . wiki.archlinux.org/index.php/…
Ганс-Дж. Шмід

2
так це рішення в основному встановлення / налаштування системної служби (але тільки для користувача)?
Тревор Бойд Сміт

Це не встановить 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-агента.
Джеймс

2
Це правильне і просте рішення. Якщо ви не хочете бачити журнал, коли виконується команда keychain, ви можете додати -qопцію для тихого режиму. Більше інформації про Keychain: funtoo.org/Keychain
Ananta

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


У мене є ключі SSH в каталозі поза $ HOME в Windows 10, використовуючи Git Bash. Змінення шляху до RSA було все, що мені потрібно було зробити, щоб це працювало. TYVM!
kayleeFrye_onDeck

7
Я б заперечував, що "Якщо ваші ключі не вимагають вводити пароль", це майже рівнозначно залишати ключ у запаленні.
Бруно Броноський

Принаймні, це на власному хості, а не десь у мережі.
midenok

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

Так. Я вважаю, що ви можете просто додати імена файлів до самого кінця останнього рядка, якщо це потрібно
Collin Anderson

Але ви все ще не можете автоматизувати скрипт, чи витягуєте git речі, наприклад, не вводячи пароль вручну? Як цього уникнути?
траїноз

7

Тому я використовував описані вище підходи, але я вважаю за краще, щоб агент помер, коли закінчується мій останній сеанс баш. Це трохи довше, ніж інші рішення, але це мій переважний підхід. Основна ідея полягає в тому, що перший сеанс bash запускає ssh-агент. Потім кожен додатковий сеанс bash перевіряє наявність файлу config ( ~/.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 config, тому ключі будуть автоматично додані при використанні
  • не пропонує вам вводити будь-які паролі під час входу (знову ж, одноразове введення парольної фрази відбувається при першому використанні)
  • мовчки запускає 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-агент, якщо він не працює для поточного користувача, або повторно встановлює параметр ssh-agent env при запуску.


Дякуємо, що сказали, як сказати, якщо агент вже працює!
Майк Максвелл

Як 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-ident

З його man-сторінки :

ssh-ident - запускайте та використовуйте ssh-агент та завантажуйте ідентичності за необхідності.


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.