Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
itsme
V2EX  ›  Linux

还是 crontab 定时执行问题,真被搞败了

  •  
  •   itsme · Jan 23, 2016 · 9693 views
    This topic created in 3791 days ago, the information mentioned may be changed or developed.
    https://www.v2ex.com/t/252709 我之前发了个贴,得到大家帮助,解决了。

    我后来又重新写了个其他脚本 sh 文件,设置 crontab 自行。脚本里面全部用完整的绝对路径,除了 echo touch rm 这样的命令没用路径开头(这些不用吧)。

    自己手工运行,一切正常; crontab 定时就不执行。

    另外用的是 debian 系统,没发现哪里有 crontab 的记录,只在 syslog 里面有看到执行时间,是否成功失败没日志。

    网络上搜索了下,所谓的开启 cron 的日志功能,也都是 ubantu centos 的,确认都符合我用的 debian 7 系统。

    有没有谁能说下 crontab 里面设定执行还有那些方面要注意?
    42 replies    2018-01-22 12:44:05 +08:00
    Devin
        1
    Devin  
       Jan 23, 2016 via iPhone
    Ubuntu 下可以注意下执行时间,比如原本是这样
    0 6 * * * /etc/test.sh
    改成这样
    00 06 * * * /etc/test.sh

    还有注意 chmod +x /etc/test.sh
    itsme
        2
    itsme  
    OP
       Jan 23, 2016
    谢谢楼上,不过我用的是 debian 7.x
    脚本手工输入自行也是正常的。

    准备稍后去 man cron 看看。
    Tink
        3
    Tink  
    PRO
       Jan 23, 2016
    把脚本和 crontab 内容贴出来啊
    Devin
        4
    Devin  
       Jan 23, 2016 via iPhone
    @itsme debian7 用上面的那个格式应该是没问题的 0 6 * * * /etc/test.sh
    补充下,还有系统时间,美国服务器时间与北京时间约有 12 小时差别,另外建议发下日志
    Busy
        5
    Busy  
       Jan 23, 2016
    不执行总有日志吧,执行错误?还是找不到 sh 文件?
    你的 sh 脚本是 bash 的还是?

    这样运行呢? sh /path/test.sh
    zander
        6
    zander  
       Jan 23, 2016
    可能是时区的问题。注意 crontab 调用的时区和你 timezone 看到的时区不一样。
    just1
        7
    just1  
       Jan 23, 2016 via Android
    rm 也要绝对路径吧
    skydiver
        8
    skydiver  
       Jan 23, 2016   ❤️ 1
    不把脚本和 crontab 内容贴出来,说别的都是耍流氓
    47jm9ozp
        9
    47jm9ozp  
       Jan 23, 2016
    /var/mail/{设定 cron 的用户名}
    47jm9ozp
        10
    47jm9ozp  
       Jan 23, 2016
    补贴代码和错误提示的求助都是耍流氓
    zdhxiong
        11
    zdhxiong  
       Jan 23, 2016
    估计还是路径没弄好。在 sh 文件里先用 cd $(dirname $0) || exit 1 切换到脚本所在目录,然后统一用相对路径吧。
    venster
        12
    venster  
       Jan 23, 2016
    反正我的 crontab 里面连 cp 都是 /bin/cp
    xuboying
        13
    xuboying  
       Jan 23, 2016
    把你的脚本写成这样的开头 #!/bin/sh -x ,命名为 /etc/foo.sh
    再写 /etc/bar.sh 脚本,内容为:
    #!/bin/sh
    /etc/foo.sh >> /var/log/foo.log

    在 crontabl 里写

    X X X ... /etc/bar.sh

    X 是你原来设定的时间,为了调试,可以先设置成 1 分钟执行一次
    观察 /var/log/foo.log
    itsme
        14
    itsme  
    OP
       Jan 23, 2016
    终于 ok 了

    之前在 crontab 里面是这样写:
    */15 * * * * /usr/bin/txt2html.sh

    自动执行不成功;手工运行这个 sh 是完全正常。

    现在这个 vps 改成这样:*/15 * * * * /bin/bash /usr/bin/txt2html.sh 才正常。

    但是我其他 vps 上的脚本文件,例如 myreboot.sh (每天重启之前删除下一些不用的文件)都是采用的第一种写法,也都正常。

    另外: debian 7 的 cron 日志开启是这样的(网络上搜索的都不靠谱):

    cron -L 15

    这样就是所有的 cron 日子都记录,包括正常和错误。
    yumijie
        15
    yumijie  
       Jan 23, 2016
    弱弱地问下楼主,查下 crontab -u yourusername -e 是撒样子,能看到设置的任务吗?

    我以前刚学的时候发现设置的任务,用户没有权限执行.

    这里我只看到你说的命令,所以我想是不是权限问题
    iyaozhen
        16
    iyaozhen  
       Jan 23, 2016
    @itsme 额,一般为了保险都是: sh /usr/bin/txt2html.sh ,或者避免程序执行的路径问题可以: cd /usr/bin/;sh ./txt2html.sh
    itsme
        17
    itsme  
    OP
       Jan 23, 2016
    @Havee 看来和 sh 有关。我还 bash 后正常。
    刚刚看到你的回复我试了下 sh /usr/bin/txt2html.sh
    /usr/bin/txt2html.sh: 18: /usr/bin/txt2html.sh: Syntax error: "(" unexpected

    同样 bash /usr/bin/txt2html.sh 不会报错。

    这个 txt2html 的脚本是网上找的。原本功能部分我没改动,就是改了 txt 和 html 文件名。

    附脚本(挺长)

    # !/bin/sh

    file_input='txt.log'
    file_output='txt2html.html'

    td_str=''

    function create_html_head(){
    echo -e "<html>
    <head>
    <meta http-equiv="Content-Type" >
    <body>
    <h1>$file_input</h1>"
    }

    function create_table_head(){
    echo -e "<table border="1">"
    }

    function create_td(){
    # if [ -e ./"$1" ]; then
    echo $1
    td_str=`echo $1 | awk 'BEGIN{FS="|"}''{i=1; while(i<=NF) {print "<td>"$i"</td>";i++}}'`
    echo $td_str
    # fi
    }

    function create_tr(){
    create_td "$1"
    echo -e "<tr>
    $td_str
    </tr>" >> $file_output
    }

    function create_table_end(){
    echo -e "</table>"
    }

    function create_html_end(){
    echo -e "</body></html>"
    }


    function create_html(){
    rm -rf $file_output
    touch $file_output

    create_html_head >> $file_output
    create_table_head >> $file_output

    while read line
    do
    echo $line
    create_tr "$line"
    done < $file_input

    create_table_end >> $file_output
    create_html_end >> $file_output
    }

    create_html
    itsme
        18
    itsme  
    OP
       Jan 23, 2016
    @iyaozhen 好的,以后 crontab 里面是完全不能省,就像楼上说的 cp 命令都要写成 /bin/cp 保险。 sh 文件前面也加上 sh 或者 bash
    Valyrian
        19
    Valyrian  
       Jan 23, 2016 via iPad
    不写解释器能给你执行就怪了= =…
    另外 sh 和 bash 的区别: http://stackoverflow.com/questions/5725296/difference-between-sh-and-bash
    julyclyde
        20
    julyclyde  
       Jan 23, 2016
    1 系统 cron 和用户 cron 的格式不同
    2 bash 和 dash 的语法不同
    3 bash xx.sh 和 /path/to/xx.sh 使用的 shell 有可能不同
    4 cron 调用和命令行调用的环境变量不同

    你提问太缺乏精确描述了
    vivisidea
        21
    vivisidea  
       Jan 23, 2016
    # !/bin/sh --> #!/bin/bash
    xuboying
        22
    xuboying  
       Jan 23, 2016 via Android
    xuboying
        23
    xuboying  
       Jan 23, 2016 via Android
    shebang 写错了
    xuboying
        24
    xuboying  
       Jan 23, 2016 via Android
    多了空格
    wangleineo
        25
    wangleineo  
       Jan 23, 2016
    是不是用 source abc.sh 执行的脚本?
    itsme
        26
    itsme  
    OP
       Jan 23, 2016
    @Valyrian
    debian 我看了 确实是把 sh 连接到 dash

    我用的那个脚本估计对 dash 兼容性问题,应该是 bash 兼容,所以脚本原本的解析器#/bin/sh 在 debian 上用 dash 解析报错;换 bash 后正常。

    这个应该就是问题所在了。

    谢谢。
    itsme
        27
    itsme  
    OP
       Jan 23, 2016
    @julyclyde 是你提到的 2 和 3 的原因。
    谢谢了。
    jimmy66
        28
    jimmy66  
       Jan 23, 2016
    还有就是创建文件的用户和执行 crontab 的用户最好一致,我踩过这样的坑,还有安装 crontab 后没有开启 cron 服务的坑
    qiaoxin
        30
    qiaoxin  
       Jan 23, 2016
    环境变量的坑,脚本里面最好加上 source /etc/profile
    #!/bin/sh
    source /etc/profile
    或者这样
    * * * * * source /etc/profile && /your/shell/path.sh
    qiaoxin
        31
    qiaoxin  
       Jan 23, 2016
    还有记得把输出重定向
    * * * * * /your/path.sh >/dev/null 2>&1
    或者* * * * * /your/path.sh >>/your/path.log 2>>&1
    yuchting
        32
    yuchting  
       Jan 23, 2016
    我来几个大坑。我都踩过。
    1 、重定向放在 crontab -e 中啊,别放在 sh 中,除非 sh 自己有重定向。类似:
    0 4 * * 0 /root/frame/restart_weekly.sh >> restart_weekly.log 2>&1

    2 、 crontab -e 之前如果修改过 timezone ( cp -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 这种),编辑 crontab 之后,一定要重启 crond 服务哇, service crond restart. 不然他是按照之前的时区执行的哇。

    3 、 sh 一定要加上 export 全路径, sh 一定要加上 export 全路径, sh 一定要加上 export 全路径,重要的事情要说 3 遍, crond 不是 ssh 登陆上起自带路径导入,如果没有事先 export ,貌似好像连 cd ls cp 都找不到滴。
    例子:

    #!/bin/sh
    PATH=/root/jdk1.6.0_45/bin:/usr/local/nginx/sbin:/root/ncftp-3.2.5/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/root/info/
    export PATH

    pkill -9 java
    cd /root/frame
    #./backup.sh
    ./clearAccount.sh
    ./runServer.sh
    skydiver
        33
    skydiver  
       Jan 23, 2016
    @yuchting 直接 crontab 里写上 PATH 就行了
    xmgit
        34
    xmgit  
       Jan 24, 2016
    $(/usr/bin/which command)
    不是更好?当然,除了自定义的路径
    uuspider
        35
    uuspider  
       Jan 24, 2016
    #!/bin/bash
    # 脚本说明
    IFS=
    uuspider
        36
    uuspider  
       Jan 24, 2016
    一个健壮的脚本,一开始就应该把 shebang 、 IFS 、 PATH 设置好:

    #!/bin/bash
    # 脚本说明
    IFS='
    '
    PATH=/bin:/usr/bin:...
    export PATH
    steveneo
        37
    steveneo  
       Jan 24, 2016
    没看到你的脚本,但我知道 Ubuntu 有个 Bug ,就是必须 Cron 文件最后一定要有空行, 有空行,有空行!!!!
    datocp
        38
    datocp  
       Jan 25, 2016 via Android
    在 debian 只遇到 path 问题,似乎命令写全路径甚至 cd 到脚本路径也无效,至于是 sh 还是 bash 这在脚本的第一行就该定义了

    #!/bin/sh
    PATH=/bin:/usr/bin:/sbin:/usr/sbin

    echo "`(date +"%m/%d/%Y %T")` `free | grep "Mem" | awk 'BEGIN{ORS=""}{ print "Memory Space : Total "$2 " KB";print " Used "$3" KB";print " Free "$4" KB\012";}'`" >> /tmp/log
    huobazi
        39
    huobazi  
       Jan 25, 2016
    xbaofeng
        40
    xbaofeng  
       Jan 25, 2016
    试试换一个 crontab -e 编辑器
    vim 的话试试 zz 保存
    qiaoxin
        41
    qiaoxin  
       Jan 26, 2016
    环境变量的问题可以这样, cronrab -e,最上面加上一行, PATH=/bin:/sbin:/usr/bin:/usr/local/bin 还有其它的就继续添加
    chanssl
        42
    chanssl  
       Jan 22, 2018
    @iyaozhen #16 今天也遇到了这个问题,最后用你的方法解决了,感谢。
    不过你的命令有点错误,套用后无法执行改为:cd /usr/bin/;txt2html.sh 就可以了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1104 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 97ms · UTC 18:13 · PVG 02:13 · LAX 11:13 · JFK 14:13
    ♥ Do have faith in what you're doing.