【问题标题】:Script not working properly in crontab, but works when I run manually脚本在 crontab 中无法正常工作,但在我手动运行时工作
【发布时间】:2014-06-12 15:53:00
【问题描述】:

我在 crontab 上设置了这个脚本,每 15 分钟运行一次。它用相应的消息正确地向我发送邮件,但是当服务器崩溃时,重新启动命令(/usr/share/tomcat5.5/bin/startup.sh)不会重新启动 Tomcat,但是如果我手动运行此脚本,它重启!

*/15 * * * * /root/is_site_alive

#!/bin/bash
s=$(curl -o /dev/null --silent --head --write-out '%{http_code}\n' 'http://www.nononono.com')
if [ $s == "200" ]; then
   echo 'java is UP' | mail -s "java  is UP" mail@mail.com
else
   /usr/share/tomcat5.5/bin/startup.sh
   echo 'java is down - Restarting' | mail -s "Restarting" mail@mail.com
fi

编辑

当我从 crontab 记录运行的输出时,它会显示:

Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
At least one of these environment variable is needed to run this program

但是当我手动运行脚本时:

Using CATALINA_BASE:   /usr/share/tomcat5.5
Using CATALINA_HOME:   /usr/share/tomcat5.5
Using CATALINA_TMPDIR: /usr/share/tomcat5.5/temp
Using JRE_HOME:        /usr/lib/jvm/java-6-sun/jre

似乎运行 crontab 的用户不了解 Java 路径。为什么会这样?

【问题讨论】:

  • 查看stackoverflow.com/tags/crontab/info中的典型调试问题
  • 重启你的服务器并把 2>/dev/yourlogfile.txt 放在命令之后 ../../.startup.sh .. 在同一行,看看日志里有什么,也看看 catalina .out 文件看看为什么。
  • @ArunSangal,你说这个? /usr/share/tomcat5.5/bin/startup.sh 2>/dev/yourlogfile.txt
  • 是的,另见“tail -f /usr/share/tomcat5.5/logs/catalina.log”
  • @ArunSangal,我按照你的建议做了,并对我的帖子进行了编辑。谢谢,如果你能帮助我更多

标签: bash tomcat crontab


【解决方案1】:

问题是 cron 作业不会像您通过终端登录时那样以您的用户身份运行。这是因为当您以实际用户身份登录时,您的用户 shell 配置文件(存储在 .profile.bash_profilebashrc 中)作为登录过程的一部分加载。因此,用户设置(例如系统路径)会加载到您的会话中,您甚至可能都不知道。

因此,当涉及到 cron 作业时,您的路径信息会丢失,因为 cron 任务实际上并未以您的身份登录,而只是以您的用户身份运行该进程。

因此,当您的 cron 作业明确指向此处的文件时:

/root/is_site_alive

登录时系统路径中包含的库、二进制文件和其他项目丢失。因此,您的 bash 文件中的进程基本上会丢失并且无法找到它们需要运行的项目。

解决此问题的快速而肮脏的方法是执行以下操作。首先从终端获取您的$PATH

echo $PATH

输出应该是这样的:

/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

现在,在您的 bash 脚本中(并且就在 #!/bin/bash 行之后)将 $PATH 信息作为如下广告:

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
s=$(curl -o /dev/null --silent --head --write-out '%{http_code}\n' 'http://www.nononono.com')
if [ $s == "200" ]; then
   echo 'java is UP' | mail -s "java  is UP" mail@mail.com
else
   /usr/share/tomcat5.5/bin/startup.sh
   echo 'java is down - Restarting' | mail -s "Restarting" mail@mail.com
fi

现在,当您运行该 bash 脚本时,您的预期路径值将就位。并且脚本应该按预期运行。

【讨论】:

    【解决方案2】:

    这个问题是 crontab 的经典问题。当您登录到类似 unix 的系统时,您的 shell 至少会读取您的配置文件和/或系统配置文件,并且取决于 shell 的其他 init 文件。这些初始化文件通常设置 PATH 和各种环境字符串。

    但是当通过 crontab 启动 shell 时,这些初始化都不会发生。所以你必须:

    • 任何一个源适当的初始化文件(不是很推荐,但可以是一种快速的解决方法)
    • 或仔细设置所有相关的环境变量,并为 /bin 和 /usr/bin 之外的所有命令使用绝对路径(通过变量)

    例子:

    #! /bin/sh
    JAVA_HOME=/path/to/java/home
    JAVA=/path/to/java/bin/java
    
    $(JAVA) -jar app.jar param1 param2
    

    【讨论】:

      【解决方案3】:

      另一种有效的解决方案

      如果你的用户有一个主目录并且有一些环境变量,例如 /homedir/user1/ 那么你可以应用这个

      #!/bin/ash
      source $HOME/.bash_profile
      

      或者它取决于发行版,也许你必须添加它:

      #!/bin/ash
      source $HOME/.profile
      

      通过“源”行,您可以访问用户的环境变量。

      或者您可以在 cron 文件中指定它:

      */15 * * * * source $HOME/.bash_profile; /root/is_site_alive
      

      最重要的一点是通过复制一些环境变量来避免错误。

      HOME 是 POSIX 标准,即使通过 cron 作业执行脚本也会设置。 LOGNAME 也是一个 posix 标准,应该用来代替 USER。

      【讨论】:

        猜你喜欢
        • 2018-05-06
        • 1970-01-01
        • 2012-03-10
        • 2023-03-04
        • 1970-01-01
        • 2021-10-18
        • 1970-01-01
        • 2012-12-15
        • 1970-01-01
        相关资源
        最近更新 更多