I have a bash script that does ssh to a remote machine and executes a command there, like:
我有一个bash脚本,它对远程机器执行ssh并在那里执行命令,如:
ssh -nxv user@remotehost echo "hello world"
When I execute the command from a command line it works fine, but it fails when is being executed as a part of crontab (errorcode=255 - cannot establish SSH connection). Details:
当我从命令行执行命令时它工作正常,但是当作为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.
...
When executing locally I'm acting as a root, crontab works as root as well. Executing 'id' from crontab and command line gives exactly the same result:
在本地执行时,我充当root,crontab也以root身份运行。从crontab和命令行执行'id'会得到完全相同的结果:
$ id
> uid=0(root) gid=0(root) groups=0(root),...
I do ssh from some local machine to the machine running crond. I have ssh key and credentials to ssh to crond machine and any other machine that the scripts connects to.
我从一些本地机器ssh到运行crond的机器。我有ssh密钥和凭据ssh到crond机器和脚本连接到的任何其他机器。
PS. Please do not ask/complain/comment that executing anything as root is bad/wrong/etc - it is not the purpose of this question.
PS。请不要问/抱怨/评论以root身份执行任何错误/错误/等等 - 这不是这个问题的目的。
5 个解决方案
#1
I am guessing that normally when you ssh from your local machine to the machine running crond, your private key is loaded in ssh-agent and forwarded over the connection. So when you execute the command from the command line, it finds your private key in ssh-agent and uses it to log in to the remote machine.
我猜通常当你从本地机器ssh到运行crond的机器时,你的私钥被加载到ssh-agent中并通过连接转发。因此,当您从命令行执行命令时,它会在ssh-agent中找到您的私钥并使用它来登录远程计算机。
When crond executes the command, it does not have access to ssh-agent, so cannot use your private key.
当crond执行命令时,它无法访问ssh-agent,因此无法使用您的私钥。
You will have to create a new private key for root on the machine running crond, and copy the public part of it to the appropriate authorized_keys
file on the remote machine that you want crond to log in to.
您必须在运行crond的计算机上为root创建新的私钥,并将其公共部分复制到您希望crond登录的远程计算机上的相应authorized_keys文件中。
#2
keychain
solves this in a painless way. It's in the repos for Debian/Ubuntu:
以无痛的方式解决这个问题。它在Debian / Ubuntu的回购中:
sudo apt-get install keychain
and perhaps for many other distros (it looks like it originated from Gentoo).
也许对于许多其他发行版(看起来它起源于Gentoo)。
This program will start an ssh-agent
if none is running, and provide shell scripts that can be source
d and connect the current shell to this particular ssh-agent
.
如果没有运行,该程序将启动ssh-agent,并提供可以获取的shell脚本并将当前shell连接到此特定ssh-agent。
For bash
, with a private key named id_rsa
, add the following to your .profile
:
对于bash,使用名为id_rsa的私钥,将以下内容添加到.profile:
keychain --nogui id_rsa
This will start an ssh-agent
and add the id_rsa
key on the first login after reboot. If the key is passphrase-protected, it will also ask for the passphrase. No need to use unprotected keys anymore! For subsequent logins, it will recognize the agent and not ask for a passphrase again.
这将启动ssh-agent并在重新启动后首次登录时添加id_rsa密钥。如果密钥是密码保护的,它也会要求密码短语。无需再使用不受保护的密钥!对于后续登录,它将识别代理,而不是再次要求密码。
Also, add the following as a last line of your .bashrc
:
另外,添加以下内容作为.bashrc的最后一行:
. ~/.keychain/$HOSTNAME-sh
This will let the shell know where to reach the SSH agent managed by keychain
. Make sure that .bashrc
is sourced from .profile
.
这将让shell知道从keychain管理的SSH代理的到达位置。确保.bashrc来自.profile。
However, it seems that cron
jobs still don't see this. As a remedy, include the line above in the crontab
, just before your actual command:
但是,似乎cron的工作仍然没有看到这一点。作为补救措施,在crontab中包含上面的行,就在您的实际命令之前:
* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command
#3
Don't expose your SSH keys without passphrase. Use ssh-cron instead, which allows you to schedule tasks using SSH agents.
不要使用密码短语暴露您的SSH密钥。请改用ssh-cron,它允许您使用SSH代理安排任务。
#4
So I had a similar problem. I came here and saw various answers but with some experimentation here is how I got it work with sshkeys with passphrase, ssh-agent and cron.
所以我遇到了类似的问题。我来到这里并看到了各种答案,但在这里进行了一些实验,我是如何使用密码,ssh-agent和cron来使用sshkeys的。
First off, my ssh setup uses the following script in my bash init script.
首先,我的ssh安装程序在我的bash init脚本中使用以下脚本。
# 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
When I login, I enter my passphrase once and then from then on it will use ssh-agent to authenticate me automatically.
当我登录时,我输入一次密码,然后从那时起它将使用ssh-agent自动验证我。
The ssh-agent details are kept in .ssh/environment. Here is what that script will look like:
ssh-agent详细信息保存在.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;
Regarding cron, you can setup a job as a regular user in various ways. If you run crontab -e as root user it will setup a root user cron. If you run as crontab -u davis -e it will add a cron job as userid davis. Likewise, if you run as user davis and do crontab -e it will create a cron job which runs as userid davis. This can be verified with the following entry:
关于cron,您可以通过各种方式将作业设置为普通用户。如果以root用户身份运行crontab -e,它将设置root用户cron。如果你以crontab -u davis -e运行,它将添加一个cron作为userid davis。同样,如果您以用户davis身份运行并执行crontab -e,它将创建一个以userid davis身份运行的cron作业。这可以通过以下条目进行验证:
30 * * * * /usr/bin/whoami
This will mail the result of whoami every 30 minutes to user davis. (I did a crontabe -e as user davis.)
这将每30分钟将whoami的结果邮寄给用户davis。 (我做了一个crontabe -e作为用户davis。)
If you try to see what keys are used as user davis, do this:
如果您尝试查看用户davis使用的键,请执行以下操作:
36 * * * * /usr/bin/ssh-add -l
It will fail, the log sent by mail will say
它会失败,通过邮件发送的日志会说
To: davis@xxxx.net
Subject: Cron <davis@hostyyy> /usr/bin/ssh-add -l
Could not open a connection to your authentication agent.
The solution is to source the env script for ssh-agent above. Here is the resulting cron entry:
解决方案是为上面的ssh-agent提供env脚本。这是生成的cron条目:
55 10 * * * . /home/davis/.ssh/environment; /home/davis/bin/domythingwhichusesgit.sh
This will run the script at 10:55. Notice the leading . in the script. It says to run this script in my environment similar to what is in the .bash init script.
这将在10:55运行脚本。注意领先。在脚本中。它表示在我的环境中运行此脚本类似于.bash init脚本中的脚本。
#5
Yesterday I had similar problem...
昨天我遇到了类似的问题......
I have cron job on one server, which start some action on other server, using ssh... Problem was user permissions, and keys...
我在一台服务器上有cron作业,它使用ssh在其他服务器上启动一些操作...问题是用户权限和密钥......
in crontab I had
在crontab我有
* * * * * php /path/to/script/doSomeJob.php
And it simply didn't work ( didnt have permissions ). I tryed to run cron as specific user, which is connected to other server
它根本不起作用(没有权限)。我尝试将cron作为特定用户运行,该用户连接到其他服务器
* * * * * user php /path/to/script/doSomeJob.php
But with no effect.
但没有效果。
Finally, i navicate to script and then execute php file, and it worked..
最后,我导航到脚本然后执行php文件,它工作..
* * * * * cd /path/to/script/; php doSomeJob.php
#1
I am guessing that normally when you ssh from your local machine to the machine running crond, your private key is loaded in ssh-agent and forwarded over the connection. So when you execute the command from the command line, it finds your private key in ssh-agent and uses it to log in to the remote machine.
我猜通常当你从本地机器ssh到运行crond的机器时,你的私钥被加载到ssh-agent中并通过连接转发。因此,当您从命令行执行命令时,它会在ssh-agent中找到您的私钥并使用它来登录远程计算机。
When crond executes the command, it does not have access to ssh-agent, so cannot use your private key.
当crond执行命令时,它无法访问ssh-agent,因此无法使用您的私钥。
You will have to create a new private key for root on the machine running crond, and copy the public part of it to the appropriate authorized_keys
file on the remote machine that you want crond to log in to.
您必须在运行crond的计算机上为root创建新的私钥,并将其公共部分复制到您希望crond登录的远程计算机上的相应authorized_keys文件中。
#2
keychain
solves this in a painless way. It's in the repos for Debian/Ubuntu:
以无痛的方式解决这个问题。它在Debian / Ubuntu的回购中:
sudo apt-get install keychain
and perhaps for many other distros (it looks like it originated from Gentoo).
也许对于许多其他发行版(看起来它起源于Gentoo)。
This program will start an ssh-agent
if none is running, and provide shell scripts that can be source
d and connect the current shell to this particular ssh-agent
.
如果没有运行,该程序将启动ssh-agent,并提供可以获取的shell脚本并将当前shell连接到此特定ssh-agent。
For bash
, with a private key named id_rsa
, add the following to your .profile
:
对于bash,使用名为id_rsa的私钥,将以下内容添加到.profile:
keychain --nogui id_rsa
This will start an ssh-agent
and add the id_rsa
key on the first login after reboot. If the key is passphrase-protected, it will also ask for the passphrase. No need to use unprotected keys anymore! For subsequent logins, it will recognize the agent and not ask for a passphrase again.
这将启动ssh-agent并在重新启动后首次登录时添加id_rsa密钥。如果密钥是密码保护的,它也会要求密码短语。无需再使用不受保护的密钥!对于后续登录,它将识别代理,而不是再次要求密码。
Also, add the following as a last line of your .bashrc
:
另外,添加以下内容作为.bashrc的最后一行:
. ~/.keychain/$HOSTNAME-sh
This will let the shell know where to reach the SSH agent managed by keychain
. Make sure that .bashrc
is sourced from .profile
.
这将让shell知道从keychain管理的SSH代理的到达位置。确保.bashrc来自.profile。
However, it seems that cron
jobs still don't see this. As a remedy, include the line above in the crontab
, just before your actual command:
但是,似乎cron的工作仍然没有看到这一点。作为补救措施,在crontab中包含上面的行,就在您的实际命令之前:
* * * * * . ~/.keychain/$HOSTNAME-sh; your-actual-command
#3
Don't expose your SSH keys without passphrase. Use ssh-cron instead, which allows you to schedule tasks using SSH agents.
不要使用密码短语暴露您的SSH密钥。请改用ssh-cron,它允许您使用SSH代理安排任务。
#4
So I had a similar problem. I came here and saw various answers but with some experimentation here is how I got it work with sshkeys with passphrase, ssh-agent and cron.
所以我遇到了类似的问题。我来到这里并看到了各种答案,但在这里进行了一些实验,我是如何使用密码,ssh-agent和cron来使用sshkeys的。
First off, my ssh setup uses the following script in my bash init script.
首先,我的ssh安装程序在我的bash init脚本中使用以下脚本。
# 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
When I login, I enter my passphrase once and then from then on it will use ssh-agent to authenticate me automatically.
当我登录时,我输入一次密码,然后从那时起它将使用ssh-agent自动验证我。
The ssh-agent details are kept in .ssh/environment. Here is what that script will look like:
ssh-agent详细信息保存在.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;
Regarding cron, you can setup a job as a regular user in various ways. If you run crontab -e as root user it will setup a root user cron. If you run as crontab -u davis -e it will add a cron job as userid davis. Likewise, if you run as user davis and do crontab -e it will create a cron job which runs as userid davis. This can be verified with the following entry:
关于cron,您可以通过各种方式将作业设置为普通用户。如果以root用户身份运行crontab -e,它将设置root用户cron。如果你以crontab -u davis -e运行,它将添加一个cron作为userid davis。同样,如果您以用户davis身份运行并执行crontab -e,它将创建一个以userid davis身份运行的cron作业。这可以通过以下条目进行验证:
30 * * * * /usr/bin/whoami
This will mail the result of whoami every 30 minutes to user davis. (I did a crontabe -e as user davis.)
这将每30分钟将whoami的结果邮寄给用户davis。 (我做了一个crontabe -e作为用户davis。)
If you try to see what keys are used as user davis, do this:
如果您尝试查看用户davis使用的键,请执行以下操作:
36 * * * * /usr/bin/ssh-add -l
It will fail, the log sent by mail will say
它会失败,通过邮件发送的日志会说
To: davis@xxxx.net
Subject: Cron <davis@hostyyy> /usr/bin/ssh-add -l
Could not open a connection to your authentication agent.
The solution is to source the env script for ssh-agent above. Here is the resulting cron entry:
解决方案是为上面的ssh-agent提供env脚本。这是生成的cron条目:
55 10 * * * . /home/davis/.ssh/environment; /home/davis/bin/domythingwhichusesgit.sh
This will run the script at 10:55. Notice the leading . in the script. It says to run this script in my environment similar to what is in the .bash init script.
这将在10:55运行脚本。注意领先。在脚本中。它表示在我的环境中运行此脚本类似于.bash init脚本中的脚本。
#5
Yesterday I had similar problem...
昨天我遇到了类似的问题......
I have cron job on one server, which start some action on other server, using ssh... Problem was user permissions, and keys...
我在一台服务器上有cron作业,它使用ssh在其他服务器上启动一些操作...问题是用户权限和密钥......
in crontab I had
在crontab我有
* * * * * php /path/to/script/doSomeJob.php
And it simply didn't work ( didnt have permissions ). I tryed to run cron as specific user, which is connected to other server
它根本不起作用(没有权限)。我尝试将cron作为特定用户运行,该用户连接到其他服务器
* * * * * user php /path/to/script/doSomeJob.php
But with no effect.
但没有效果。
Finally, i navicate to script and then execute php file, and it worked..
最后,我导航到脚本然后执行php文件,它工作..
* * * * * cd /path/to/script/; php doSomeJob.php