Почему ssh не работает из crontab, но выполняется при выполнении из командной строки?
У меня есть bash script, который делает ssh на удаленном компьютере и выполняет там команду:
ssh -nxv [email protected] echo "hello world"
Когда я выполняю команду из командной строки, она работает нормально, но она не работает, когда выполняется как часть crontab (errorcode = 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.
...
При выполнении локально я выступаю в качестве корня, crontab также работает как root.
Выполнение 'id' из crontab и командной строки дает точно такой же результат:
$ id
> uid=0(root) gid=0(root) groups=0(root),...
Я делаю ssh с некоторой локальной машины на машину, работающую с комом. У меня есть ssh-ключ и учетные данные для ssh для машины с crond и любой другой машины, к которой подключаются скрипты.
PS. Пожалуйста, не спрашивайте/не комментируйте/не комментируйте, что выполнение чего-либо из-за неправильного/неправильного пользователя root/etc - это не цель этого вопроса.
Ответы
Ответ 1
Я предполагаю, что обычно, когда вы ssh от вашего локального компьютера до машины, работающей на crond, ваш закрытый ключ загружается в ssh-agent и перенаправляется по соединению. Поэтому, когда вы выполняете команду из командной строки, она находит ваш закрытый ключ в ssh-agent и использует его для входа на удаленную машину.
Когда crond выполняет команду, он не имеет доступа к ssh-agent, поэтому не может использовать ваш закрытый ключ.
Вам нужно будет создать новый закрытый ключ для root на компьютере, на котором запущен crond, и скопировать его публичную часть в соответствующий файл authorized_keys
на удаленном компьютере, на который вы хотите, чтобы клон подключился к.
Ответ 2
решает это безболезненно. Он в репозиториях для 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
Ответ 3
Не подвергайте свои SSH-ключи без кодовой фразы. Вместо этого используйте ssh-cron, что позволяет планировать задачи с использованием агентов SSH.
Ответ 4
Итак, у меня была аналогичная проблема. Я пришел сюда и увидел разные ответы, но с некоторыми экспериментами вот как я получил его работу с sshkeys с помощью passphrase, ssh-agent и cron.
Во-первых, моя настройка ssh использует script в моем bash init script.
# 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-agent для автоматической авторизации меня.
Детали ssh-agent хранятся в .ssh/environment. Вот что будет выглядеть script:
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, он настроит root cron. Если вы запустите crontab -u davis -e, он добавит задание cron как userid davis. Аналогично, если вы запустите как пользователь davis и сделаете crontab -e, он создаст задание cron, которое будет работать как userid davis. Это можно проверить со следующей записью:
30 * * * * /usr/bin/whoami
Это будет отправлять результат whoami каждые 30 минут пользователю davis. (Я сделал crontabe -e как пользователь davis.)
Если вы попытаетесь увидеть, какие ключи используются в качестве пользователя davis, сделайте следующее:
36 * * * * /usr/bin/ssh-add -l
Это не удастся, журнал, отправленный по почте, скажет
To: [email protected]
Subject: Cron <[email protected]> /usr/bin/ssh-add -l
Could not open a connection to your authentication agent.
Решение заключается в источнике env script для ssh-agent выше. Вот результат записи cron:
55 10 * * * . /home/davis/.ssh/environment; /home/davis/bin/domythingwhichusesgit.sh
Это запустит script в 10:55. Обратите внимание на лидерство. в script. Он говорит, чтобы запустить этот script в моей среде, подобный тому, что находится в .bash init script.
Ответ 5
Вчера у меня была схожая проблема...
У меня есть задание cron на одном сервере, которое запускает некоторые действия на другом сервере, используя ssh... Проблема заключалась в разрешениях пользователя и ключах...
в crontab у меня был
* * * * * php /path/to/script/doSomeJob.php
И он просто не работал (у него не было прав).
Я попытался запустить cron в качестве конкретного пользователя, который подключен к другому серверу
* * * * * user php /path/to/script/doSomeJob.php
Но без эффекта.
Наконец, я нахожусь в script, а затем выполняю файл php, и он сработал.
* * * * * cd /path/to/script/; php doSomeJob.php