咱们常常会经过crontab来执行定时任务,一般生产环境中在不一样主机直接进行登陆是经过ssh来链接的。好比咱们经过在备份服务器上设定定时任务,按期经过scp(使用SSH的远程拷贝命令)来拷贝远程服务器的数据到备份服务器上,这也是我遇到的一个事情。shell
环境描述:bash
脚本与定时任务:服务器
定时任务设置以下:
ssh
不管是否执行成功,都把信息输出到2222.txt中ide
脚本内容以下:
测试
我这里仅用ssh命令来测试,实际上这个命令若是能够正常执行的话,你执行scp命令也同样ui
#!/bin/bash ssh -v 192.168.50.135 'ls'
报错信息:spa
下图是crontab执行定时任务中的脚本的报错信息blog
你发现TCP链接是成功创建的,而后也在备份服务器上的~/.ssh/目录中的known_hosts文件中找到了host key。这个key是对方主机的公钥。在/etc/ssh/ssh_config中的 StrictHostKeyChecking 的值决定了是否把对方的公钥放在known_hosts文件中。若是是yes则表示不存放,若是是no则表示存放,若是是ask则表示询问。crontab
下图这个意思是说KEY找到了并且匹配,就是说备份服务器存的对方服务器的公钥和对方如今使用的公钥一致。
最后是尝试发送本身使用的公钥让对方去验证,这里尝试了几回,而且更换了几种验证方式均宣告失败,因此最后拒绝访问。
下图是单纯运行脚本的输出信息:也就是直接在终端中运行脚本
能够看到验证是经过的,不过你会发现它使用的是一个叫作id_dsa的公钥文件发送给服务器,而后对方接受了。但是我这个备份服务器本地的~/.ssh/目录中并无id_dsa的文件
我发现跳板机(Linux的跳板机,通常登陆IDC的机器都要登陆到跳板机,并且其余服务器也只接受来自跳板机的IP信息,你就算拨入了×××,若是不先链接到跳板机,你也是没法登陆服务器的,那可能有人问,我经过跳板机链接到了服务器,而后从这个服务器再SSH到另外的服务器是否能够呢?能够)的~/.ssh/目录中有id_dsa文件,因而我就拷贝到个人备份服务器上,测试后依然失败。
排查问题:
查看env
修改脚本:
修改~/.bashrc文件,也就是本地变量文件,在文件中增长以下内容,这些内容和也就是以前经过env查看到的
export SSH_CLIENT="192.168.90.58 14567 1314" export SSH_TTY=/dev/pts/2 export SSH_AUTH_SOCK=/tmp/ssh-cvRpw15068/agent.15068 export SSH_CONNECTION="192.168.90.58 14567 192.168.90.91 1314"
修改脚本
#!/bin/bash source $HOME/.bashrc ssh -v 192.168.50.135 'ls'
验证:
再次执行就成功了。
总结:
crontab执行脚本不成功一般都是环境变量致使的,由于crontab执行脚本属于非登式shell,针对这种它是不加载/etc/profiel和~/.bash_profile。它的会先加载~/.bashrc,而后加载/etc/bashrc,最后加载/etc/profile.d/下的变量。因此我在家目录中的bashrc中设置了和env中同样的变量,这样在脚本里面指定就能够了。若是你只是在basrc中写,而不在脚本中source初始化文件也不行。缘由我猜想多是跟crontab本身的环境变量有关,并且在/etc/rond的配置文件中设置环境变量不生效,不知道为何。
因此在crontab执行脚本,一般的建议是命令写全路径,另外还应该设置好环境变量
#!/bin/bash source /etc/profile source $HOME/.bashrc
若是是ssh这种远程执行,可使用-i参数指定公钥。