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 ,修改定时任务后,任务配置自动生效。
相关推荐
菜鸟一皓几秒前
IDEA的lombok插件不生效了?!!
java·ide·intellij-idea
爱上语文4 分钟前
Java LeetCode每日一题
java·开发语言·leetcode
bug菌27 分钟前
Java GUI编程进阶:多线程与并发处理的实战指南
java·后端·java ee
程序猿小D39 分钟前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
极客先躯2 小时前
高级java每日一道面试题-2024年10月3日-分布式篇-分布式系统中的容错策略都有哪些?
java·分布式·版本控制·共识算法·超时重试·心跳检测·容错策略
夜月行者2 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm
程序猿小D2 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
潘多编程2 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
_阿伟_2 小时前
SpringMVC
java·spring
代码在改了3 小时前
springboot厨房达人美食分享平台(源码+文档+调试+答疑)
java·spring boot