crontab 定时检测 Tomcat 状态并拉起脚本实现及注意事项

背景

Jenkins 所在的 Tomcat 总是莫名挂掉,虽然任务配置了 NOKILLME 参数,而且并不是总是发生在编译完成后才挂的。怀疑是机器资源不足导致的,没有依据。最简单的办法是创建一个定时任务,检测 Tomcat 状态,不见了就拉起它。

本文记录这个简单的过程,很简单的一个脚本,里面确包含着 Linux shell 的几个基本知识点,一起温故一下。

拉起脚本

编写拉起脚本,平时写了很多 stop.sh 脚本,随便找到一个参考,拷贝过来的,命名为 pull-tomcat.sh。 Tomcat 的特殊关键字是进程启动的 class 类名称 Bootstrap ,编写完整脚本如下:

powershell 复制代码
#!/bin/sh
basePath=$(cd `dirname $0`; pwd)
scriptName=$(basename "$0")
cd $basePath
cd ..
dataDir=`pwd`
date=`echo $(date "+%m%d%H%M%S")`
tomcatInfo=`ps -ef|grep -w Bootstrap|grep -v grep|grep -v "$scriptName"|awk '{print $2}'`
echo $date","$tomcatInfo

if [ "$tomcatInfo" == "" ]; then
    echo 'Tomcat is missing and start it.'
    cd /opt/apache-tomcat-9.0.82/bin
    sh startup.sh
fi

脚本很简单,但是有几个关键点:

  1. 第一行脚本编辑器设置必须正确,区分不同操作系统默认生成的 shell 文件该行不一样。
  2. 使用 ps 查看进程时,需要考虑脚本的执行方式,为了保证过滤结果正确,需要过滤掉当前脚本自己 grep -v "$scriptName"
  3. crontab 定时器执行时依赖环境变量和直接执行脚本或者在命令行执行命令不一样,所以不能环境变量 PATH 路径下的命令,如 jps ,否则会导致 crontab 命令执行失败。
  4. if 分支如果编写 else 分支,则该分支里面必须包含语句,否则会报错。这点跟 Java 不一样,Java 可以包含空分支的。

脚本解释器问题

MacOs 下用 IDEA 创建 .sh 后缀的文件时,自动会在第一行加上解释器信息为:

powershell 复制代码
#!/sh

但是当放到 Linux 系统下,通过 ./文件名的方式执行时,会报错误:

powershell 复制代码
-bash: ./test.sh: /sh: 坏的解释器: 没有那个文件或目录

注意事项:

  1. ./文件名的方式执行时,必须有执行权限,否则会报"权限不够"的错误,执行失败;且会以开头第一行设置的 Shell 解释器进行执行。Mac 下默认的解释器是 #!/sh,在 Linux 下应该设置为 #!/bin/bash
  2. sh 文件名的方式,即使没有执行权限,也能执行。通过子进程的方式执行,而子进程的执行路径字段为当前脚本文件路径,且会被 grep 过滤器留下,因此得到的结果不准确。

上图是目标主机上在脚本中执行 ps -ef|grep -w Bootstrap|grep -v grep 的结果,里面包含了当前脚本名称。诡异的是,这种情况还跟机器有关,以前都没有碰到过这种情况。可能跟 shell 解释器的什么特殊配置有关吧。

cron 环境变量问题

jps 命令,当 crontab 定时执行时,报异常,命令不存在。脚本中最初想用 jps 命令查找 Bootstrap 进程的,但是定时调度时总是报命令不存在。

猜测是 /root/.bash_profile 里面没有配置 JAVA_HOME/binPATH,但是配置后,定时任务执行时依旧报这个错误。

编写定时任务,执行 crontab -e 添加一条每隔 10分钟执行一次的脚本,并将脚本输出内容写入某文件:

bash 复制代码
*/10 * * * * /home/pull-tomcat.sh >> /home/pull-tomcat.log

启示录

最后再汇总一下 Shell 的基本知识:

  1. 以后编写 stop 脚本时,用 ps 查找目标进程时,需要考虑过滤掉当前脚本名称。
  2. 第一行的脚本默认解释器,当使用 ./文件名执行时会生效,所以必须保证对应系统中存在指定的解释器。
  3. 环境变量问题,搞不清楚环境变量,使用命令时写全路径。
  4. crontab 定时任务添加时,可以追加命令执行结果到某个文件,便于查看任务执行情况。cron 自身的调度日志只能看到调度过程,而看不到脚本执行内容。Linux 下 cron 语法是 「分 时 日 月 周」五部分,跟 Quartz 的调度表达式少了头尾的 分和年。
  5. crontab 服务名称是 crond ,修改定时任务后,任务配置自动生效。
相关推荐
AI人H哥会Java18 分钟前
【Spring】基于XML的Spring容器配置——<bean>标签与属性解析
java·开发语言·spring boot·后端·架构
计算机学长felix21 分钟前
基于SpringBoot的“大学生社团活动平台”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·后端
sin220122 分钟前
springboot数据校验报错
spring boot·后端·python
程序员大阳1 小时前
闲谭Scala(1)--简介
开发语言·后端·scala·特点·简介
直裾1 小时前
scala图书借阅系统完整代码
开发语言·后端·scala
大大怪将军~~~~2 小时前
SpringBoot 入门
java·spring boot·后端
凡人的AI工具箱2 小时前
每天40分玩转Django:Django缓存
数据库·人工智能·后端·python·缓存·django
安然望川海2 小时前
springboot 使用注解设置缓存时效
spring boot·后端·缓存