Почему ssh не работает из crontab, но завершается успешно при выполнении из командной строки?
Вопрос
У меня есть сценарий bash, который подключается по SSH к удаленному компьютеру и выполняет там команду, например:
ssh -nxv user@remotehost echo "hello world"
Когда я выполняю команду из командной строки, она работает нормально, но не работает, когда выполняется как часть crontab (код ошибки = 255 — невозможно установить SSH-соединение).Подробности:
...
Waiting for server public key.
Received server public key and host key.
Host 'remotehost' is known and matches the XXX host key.
...
Remote: Your host key cannot be verified: unknown or invalid host key.
Server refused our host key.
Trying XXX authentication with key '...'
Server refused our key.
...
При локальном выполнении я действую как root, crontab также работает как root.Выполнение «id» из crontab и командной строки дает точно такой же результат:
$ id
> uid=0(root) gid=0(root) groups=0(root),...
Я использую SSH с какой-то локальной машины на машину, на которой работает crond.У меня есть ключ SSH и учетные данные для SSH-компьютера crond и любого другого компьютера, к которому подключаются сценарии.
ПС.Пожалуйста, не спрашивайте/жалуйтесь/комментируйте, что выполнение чего-либо от имени пользователя root является плохим/неправильным/и т. д. — это не цель этого вопроса.
Решение
Я предполагаю, что обычно, когда вы подключаетесь по ssh с вашего локального компьютера на компьютер, на котором работает crond, ваш закрытый ключ загружается в ssh-агент и пересылается по соединению.Поэтому, когда вы выполняете команду из командной строки, она находит ваш закрытый ключ в ssh-агенте и использует его для входа на удаленный компьютер.
Когда crond выполняет команду, он не имеет доступа к ssh-агенту, поэтому не может использовать ваш закрытый ключ.
Вам нужно будет создать новый закрытый ключ для root на компьютере, на котором запущен crond, и скопировать его открытую часть в соответствующую папку. authorized_keys
файл на удаленном компьютере, на котором вы хотите войти в систему crond.
Другие советы
keychain
решает эту проблему безболезненно.Он находится в репозиториях Debian/Ubuntu:
sudo apt-get install keychain
и, возможно, для многих других дистрибутивов (похоже, что он произошел от Gentoo).
Эта программа запустит ssh-agent
если ни один из них не запущен, и предоставить сценарии оболочки, которые можно source
d и подключим текущую оболочку к этому конкретному ssh-agent
.
Для bash
, с закрытым ключом с именем id_rsa
, добавьте следующее в свой .profile
:
keychain --nogui id_rsa
Это запустит ssh-agent
и добавьте id_rsa
ключ при первом входе в систему после перезагрузки.Если ключ защищен парольной фразой, он также запросит парольную фразу. Больше не нужно использовать незащищенные ключи! При последующих входах в систему он распознает агента и больше не запрашивает парольную фразу.
Кроме того, добавьте следующую строку в качестве последней строки вашего .bashrc
:
. ~/.keychain/$HOSTNAME-sh
Это позволит оболочке узнать, где можно связаться с агентом SSH, управляемым keychain
.Убедись в том, что .bashrc
получен из .profile
.
Однако кажется, что cron
рабочие места до сих пор этого не видят.В качестве исправления включите приведенную выше строку в crontab
, непосредственно перед вашей фактической командой:
* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command
Не раскрывайте свои ключи SSH без парольной фразы.Использовать ssh-cron вместо этого это позволяет вам планировать задачи с помощью агентов SSH.
Итак, у меня была аналогичная проблема.Я пришел сюда и увидел разные ответы, но, поэкспериментировав, вот как мне удалось заставить его работать с sshkeys с парольной фразой, ssh-агентом и cron.
Во-первых, моя настройка ssh использует следующий сценарий в моем сценарии инициализации bash.
# JFD Added this for ssh
SSH_ENV=$HOME/.ssh/environment
# start the ssh-agent
function start_agent {
echo "Initializing new SSH agent..."
# spawn 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
}
if [ -f "${SSH_ENV}" ]; then
. "${SSH_ENV}" > /dev/null
ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
start_agent;
}
else
start_agent;
fi
Когда я вхожу в систему, я ввожу свою парольную фразу один раз, и с этого момента он будет использовать ssh-агент для автоматической аутентификации.
Детали ssh-агента хранятся в .ssh/environment.Вот как будет выглядеть этот скрипт:
SSH_AUTH_SOCK=/tmp/ssh-v3Tbd2Hjw3n9/agent.2089; export SSH_AUTH_SOCK;
SSH_AGENT_PID=2091; export SSH_AGENT_PID;
#echo Agent pid 2091;
Что касается cron, вы можете настроить работу обычного пользователя различными способами.Если вы запустите crontab -e от имени пользователя root, он настроит cron пользователя root.Если вы запустите как crontab -u davis -e, оно добавит задание cron с идентификатором пользователя davis.Аналогично, если вы запустите от имени пользователя davis и выполните crontab -e, будет создано задание cron, которое запускается от имени пользователя davis.Это можно проверить с помощью следующей записи:
30 * * * * /usr/bin/whoami
Результат whoami будет отправляться пользователю davis каждые 30 минут.(Я выполнил crontabe -e от имени пользователя davis.)
Если вы попытаетесь посмотреть, какие клавиши используются в качестве пользователя davis, сделайте следующее:
36 * * * * /usr/bin/ssh-add -l
Не получится, в журнале, отправленном по почте, будет написано
To: davis@xxxx.net
Subject: Cron <davis@hostyyy> /usr/bin/ssh-add -l
Could not open a connection to your authentication agent.
Решение состоит в том, чтобы использовать сценарий env для ssh-агента, указанный выше.Вот результирующая запись cron:
55 10 * * * . /home/davis/.ssh/environment; /home/davis/bin/domythingwhichusesgit.sh
Это запустит сценарий в 10:55.Обратите внимание на ведущее.в сценарии.В нем говорится, что этот сценарий нужно запустить в моей среде, аналогично тому, что находится в сценарии инициализации .bash.
Вчера у меня была похожая проблема...
У меня есть задание cron на одном сервере, которое запускает некоторые действия на другом сервере, используя ssh...Проблема заключалась в правах пользователя и ключах...
в кронтабе у меня было
* * * * * php /path/to/script/doSomeJob.php
И это просто не работало (не было разрешений).Я попытался запустить cron от имени конкретного пользователя, который подключен к другому серверу.
* * * * * user php /path/to/script/doSomeJob.php
Но без эффекта.
Наконец, я перешел к сценарию, а затем выполнил php-файл, и это сработало..
* * * * * cd /path/to/script/; php doSomeJob.php