V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
itsme
V2EX  ›  Linux

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

  •  
  •   itsme · 2016-01-23 12:29:08 +08:00 · 8690 次点击
    这是一个创建于 3228 天前的主题,其中的信息可能已经有所发展或是发生改变。
    https://www.v2ex.com/t/252709 我之前发了个贴,得到大家帮助,解决了。

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

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

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

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

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

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

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

    这样运行呢? sh /path/test.sh
    zander
        6
    zander  
       2016-01-23 13:19:33 +08:00
    可能是时区的问题。注意 crontab 调用的时区和你 timezone 看到的时区不一样。
    just1
        7
    just1  
       2016-01-23 13:21:53 +08:00 via Android
    rm 也要绝对路径吧
    skydiver
        8
    skydiver  
       2016-01-23 13:22:57 +08:00   ❤️ 1
    不把脚本和 crontab 内容贴出来,说别的都是耍流氓
    ooxxcc
        9
    ooxxcc  
       2016-01-23 13:30:13 +08:00
    /var/mail/{设定 cron 的用户名}
    ooxxcc
        10
    ooxxcc  
       2016-01-23 13:30:33 +08:00
    补贴代码和错误提示的求助都是耍流氓
    zdhxiong
        11
    zdhxiong  
       2016-01-23 13:32:07 +08:00
    估计还是路径没弄好。在 sh 文件里先用 cd $(dirname $0) || exit 1 切换到脚本所在目录,然后统一用相对路径吧。
    venster
        12
    venster  
       2016-01-23 13:32:27 +08:00
    反正我的 crontab 里面连 cp 都是 /bin/cp
    xuboying
        13
    xuboying  
       2016-01-23 13:43:53 +08:00
    把你的脚本写成这样的开头 #!/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
       2016-01-23 14:31:01 +08:00
    终于 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  
       2016-01-23 14:34:18 +08:00
    弱弱地问下楼主,查下 crontab -u yourusername -e 是撒样子,能看到设置的任务吗?

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

    这里我只看到你说的命令,所以我想是不是权限问题
    iyaozhen
        16
    iyaozhen  
       2016-01-23 14:34:31 +08:00
    @itsme 额,一般为了保险都是: sh /usr/bin/txt2html.sh ,或者避免程序执行的路径问题可以: cd /usr/bin/;sh ./txt2html.sh
    itsme
        17
    itsme  
    OP
       2016-01-23 14:39:47 +08:00
    @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
       2016-01-23 14:41:43 +08:00
    @iyaozhen 好的,以后 crontab 里面是完全不能省,就像楼上说的 cp 命令都要写成 /bin/cp 保险。 sh 文件前面也加上 sh 或者 bash
    Valyrian
        19
    Valyrian  
       2016-01-23 15:03:51 +08:00 via iPad
    不写解释器能给你执行就怪了= =…
    另外 sh 和 bash 的区别: http://stackoverflow.com/questions/5725296/difference-between-sh-and-bash
    julyclyde
        20
    julyclyde  
       2016-01-23 15:04:33 +08:00
    1 系统 cron 和用户 cron 的格式不同
    2 bash 和 dash 的语法不同
    3 bash xx.sh 和 /path/to/xx.sh 使用的 shell 有可能不同
    4 cron 调用和命令行调用的环境变量不同

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

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

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

    谢谢。
    itsme
        27
    itsme  
    OP
       2016-01-23 16:04:43 +08:00
    @julyclyde 是你提到的 2 和 3 的原因。
    谢谢了。
    jimmy66
        28
    jimmy66  
       2016-01-23 17:16:35 +08:00
    还有就是创建文件的用户和执行 crontab 的用户最好一致,我踩过这样的坑,还有安装 crontab 后没有开启 cron 服务的坑
    jimmy66
        29
    jimmy66  
       2016-01-23 17:16:41 +08:00
    qiaoxin
        30
    qiaoxin  
       2016-01-23 18:30:28 +08:00
    环境变量的坑,脚本里面最好加上 source /etc/profile
    #!/bin/sh
    source /etc/profile
    或者这样
    * * * * * source /etc/profile && /your/shell/path.sh
    qiaoxin
        31
    qiaoxin  
       2016-01-23 18:36:02 +08:00
    还有记得把输出重定向
    * * * * * /your/path.sh >/dev/null 2>&1
    或者* * * * * /your/path.sh >>/your/path.log 2>>&1
    yuchting
        32
    yuchting  
       2016-01-23 18:48:52 +08:00
    我来几个大坑。我都踩过。
    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  
       2016-01-23 18:51:02 +08:00
    @yuchting 直接 crontab 里写上 PATH 就行了
    Bardon
        34
    Bardon  
       2016-01-24 00:00:11 +08:00
    $(/usr/bin/which command)
    不是更好?当然,除了自定义的路径
    uuspider
        35
    uuspider  
       2016-01-24 02:06:09 +08:00
    #!/bin/bash
    # 脚本说明
    IFS=
    uuspider
        36
    uuspider  
       2016-01-24 02:09:40 +08:00
    一个健壮的脚本,一开始就应该把 shebang 、 IFS 、 PATH 设置好:

    #!/bin/bash
    # 脚本说明
    IFS='
    '
    PATH=/bin:/usr/bin:...
    export PATH
    steveneo
        37
    steveneo  
       2016-01-24 06:32:51 +08:00
    没看到你的脚本,但我知道 Ubuntu 有个 Bug ,就是必须 Cron 文件最后一定要有空行, 有空行,有空行!!!!
    datocp
        38
    datocp  
       2016-01-25 08:24:31 +08:00 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  
       2016-01-25 11:09:44 +08:00
    xbaofeng
        40
    xbaofeng  
       2016-01-25 13:46:34 +08:00
    试试换一个 crontab -e 编辑器
    vim 的话试试 zz 保存
    qiaoxin
        41
    qiaoxin  
       2016-01-26 20:37:16 +08:00
    环境变量的问题可以这样, cronrab -e,最上面加上一行, PATH=/bin:/sbin:/usr/bin:/usr/local/bin 还有其它的就继续添加
    chanssl
        42
    chanssl  
       2018-01-22 12:44:05 +08:00
    @iyaozhen #16 今天也遇到了这个问题,最后用你的方法解决了,感谢。
    不过你的命令有点错误,套用后无法执行改为:cd /usr/bin/;txt2html.sh 就可以了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   861 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 21:56 · PVG 05:56 · LAX 13:56 · JFK 16:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.