Cron 无法运行 bash 脚本

Posted

技术标签:

【中文标题】Cron 无法运行 bash 脚本【英文标题】:Cron fails to run bash script 【发布时间】:2011-08-10 04:19:35 【问题描述】:

我有 bash 脚本

#!/bin/sh

DTFILE=/etc/daytime.addr
DTPORT=13
DAYTIME_ERROR=/tmp/dtm.err

function daytime_error()
    if [[ -z $1 ]]
    then 
    exit 1
    fi
    if [[ -e $DAYTIME_ERROR ]]
    then
    echo "Error already reported"
    else
    logger "$1"
    touch $DAYTIME_ERROR
    fi
    exit 1


if [[ -s $DTFILE ]]
then
    ADDR=$(head -n1 $DTFILE)
    DAYTIME=$(telnet $ADDR $DTPORT | time_conv.awk)
    if [[ -z $DAYTIME ]]
    then
    daytime_error "Daytime client: no connection to $ADDR"
    else
    date -s "$DAYTIME"
    hwclock -w
    rm $DAYTIME_ERROR
    fi

else
    daytime_error "Daytime client: no daytime server address in file $DTFILE"
fi

从命令行调用时它可以工作,但在 cron 调用它时会失败。特别是带有 telnet 命令的行给出了零字节的输出。 Telnet 有 755 掩码,所以每个用户都应该可以使用它。有什么想法吗?

更新,time_conv.awk的内容:

#! /usr/bin/awk -f

/[0-9]+:[0-9]+:[0-9]+/ 
    if ($2~/Jan/) $2=1;
    else if ($2~/Feb/) $2=2;
    else if ($2~/Mar/) $2=3;
    else if ($2~/Apr/) $2=4;
    else if ($2~/May/) $2=5;
    else if ($2~/Jun/) $2=6;
    else if ($2~/Jul/) $2=7;
    else if ($2~/Aug/) $2=8;
    else if ($2~/Sep/) $2=9;
    else if ($2~/Oct/) $2=10;
    else if ($2~/Nov/) $2=11;
    else if ($2~/Dec/) $2=12;
    print $5 "-" $2 "-" $3 " " $4

【问题讨论】:

你是如何运行它的?是bash <script> 还是sh <script> 还是./<script>。可能是因为您使用#!/bin/sh 而不是#!/bin/bash。尝试使用-x 键运行它。 time_conv.awk 的内容是什么? @Draco Alter 我尝试使用 /bin/bash 而不是 /bin/sh,结果相同。 @bmk #! /usr/bin/awk -f /[0-9]+:[0-9]+:[0-9]+/ if ($2~/Jan/) $2=1;否则如果 ($2~/Feb/) $2=2;否则 if ($2~/Mar/) $2=3;否则如果 ($2~/Apr/) $2=4;否则 if ($2~/May/) $2=5;否则 if ($2~/Jun/) $2=6;否则 if ($2~/Jul/) $2=7;否则 if ($2~/Aug/) $2=8;否则如果 ($2~/Sep/) $2=9;否则 if ($2~/Oct/) $2=10;否则 if ($2~/Nov/) $2=11;否则 if ($2~/Dec/) $2=12;打印 $5 "-" $2 "-" $3 " " $4 bash -x <script> 运行它怎么样?它应该打印一些调试信息。 【参考方案1】:

我猜有些路径丢失了...您是否尝试使用 /usr/bin/telnet 而不是 telnet?

要查找 telnet 的路径,您可以使用which telnet

【讨论】:

是的,我用 /usr/bin/telnet 代替了 telnet,它的行为是一样的。 这是一个简单的 awk 脚本,用于将白天服务器给出的时间格式转换为 yyyy-mm-dd hh:mm:ss。在脚本的调试版本中,我将bash脚本中的每个调用都分开了,唯一失败的是telnet,它甚至不输出错误(在这种情况下,我用telnet $ADDR $DTPORT调用它2>&1 | tee /tmp/garbage.tmp,从 cron 调用时给定文件为空,但从命令行调用时包含正常数据。 是的,你能不能试试那个文件的绝对路径? 是的,我有,还是一样。简而言之,我尝试使用绝对文件名调用此脚本中的所有程序,结果是一样的。【参考方案2】:

您应该提及您收到的具体错误消息。无论如何,既然你说 telnet 线路会导致错误,我假设以下常见陷阱:

您的脚本需要 Bash shell 才能正常运行。 您系统的默认外壳不是/bin/bash。看看/bin/sh 指的是什么,例如与ls -l /bin/sh 不过,您的帐户设置为将 /bin/bash 作为默认 shell(可能是在 /etc/passwd 或通过变量 $SHELL 为您的帐户设置的。

解决方案:

更改系统的默认 shell(取决于您的系统,不是我推荐的)。 让您的 cronjobs 使用 Bash 作为默认值:在 crontab 中设置 SHELL=/bin/bash。 更改脚本的第一行以明确提及 Bash:#!/bin/bash(我的建议)

【讨论】:

【参考方案3】:

好的。疯狂的猜测时间......

您使用的是.rhosts 文件吗?这样,当您远程登录时,您不必输入密码。你不能在 crontab 脚本中这样做。

如果是这个原因,你必须做三件事:

找出运行 crontab 的用户。 对于该用户,运行ssh-keygen 程序,并生成公钥和私钥。对远程机器执行相同操作。现在,在远程机器上创建一个 authorized_hosts 文件并添加您的公钥。 完成后,从 telnet 切换到 ssh。无论如何,SSH 更安全。

【讨论】:

以上是关于Cron 无法运行 bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章

使用 cron 每 5 分钟后无法运行 python 脚本

Docker容器crontab未运行[重复]

Cron作业无法执行写入文本文件的python脚本

Cron 作业无法加载 gem

根 crontab 无法正确运行,用户 cron 作业可以

bash & s3cmd 无法正常工作