Запустіть 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.