问下 shell 大佬们, crontab 定时任务执行 shell 脚本和自己手动执行 shell 脚本 为何结果不一致?

2019-07-17 17:32:14 +08:00
 skypyb

定时任务:

*/1 * * * * bash /opt/rocket/bin/monitor.sh

shell 脚本代码如下:

#!bin/bash
source ~/.bash_profile

LOG_FILE='/opt/rocket/bin/logs/monitor_sh.log'

# 打印日志,传一个参数($1 日志体)
function log() {
  local time=$(date "+%Y-%m-%d %H:%M:%S")
  echo "[$time] $0 : $1 " >> ${LOG_FILE}
}

# 用来搜进程有几条,没有就返回 0
# $1 : 进程名
function checkProcess() {
    if [ -z $1 ];
    then
        log "Input parameter is empty."
        return 0
    fi

    pid=`ps -ef | grep "rocket" | grep -v grep | awk '{print $2}'`
    echo $pid
}


declare -i pid #声明变量为整形
pName="rocket" #要查看的进程名

pid=`checkProcess ${pName}`
if [ $pid -eq 0 ]
then
    log "No specified ${pName} service starts."
    bash start.sh
else
    log "The specified service ${pName} has been started, pid=${pid}."
fi

日志文件(部分)如下:

shell 脚本用途是检测 java 进程是否存在,若不存在就执行另一个启动脚本,此处场景是存在的,即我手动执行时打印的 15460 号

看日志打印的文件名, 只有文件名 monitor.sh 的是我手动执行的,绝对路径是定时任务执行的。
那么问题来了,这是个什么情况? 如何解决?

5104 次点击
所在节点    Linux
20 条回复
skypyb
2019-07-17 17:36:35 +08:00
写 shell 脚本不多 , 也不知道是不是我写的代码有问题?
vcheckzen
2019-07-17 17:48:03 +08:00
start.sh 也用绝对路径看看
skypyb
2019-07-17 17:51:07 +08:00
@vcheckzen
按照逻辑来说进入这个能执行 start.sh 的代码块就已经错误了 = =
正常情况应该是进 else 的,毕竟已经有对应进程在执行了
hell0v2
2019-07-17 17:53:29 +08:00
看看环境变量是否有影响,cron 用户执行的环境变量不一致可能会导致失败,在定时任务里直接加. /etc/profile 或. ~/.bash_profile 试试呢
ant2017
2019-07-17 17:59:28 +08:00
checkProcess()这个函数查询 pid 的时候有问题吧,这样只 grep rocket 不是会查询到多个 pid 吗?
skypyb
2019-07-17 18:00:03 +08:00
@hell0v2 代码第二行就是呀,没有作用。。
reticentfat
2019-07-17 18:01:27 +08:00
环境变量不一致
omph
2019-07-17 18:10:36 +08:00
为何不用 pgrep ?
vcheckzen
2019-07-17 18:20:29 +08:00
把 checkProcess 里的 pid 打到 log 看看
newtype0092
2019-07-17 18:22:21 +08:00
sudo -u xxx /bin/bash /opt/rocket/bin/monitor.sh
skypyb
2019-07-17 18:24:45 +08:00
@ant2017 一般不会,这服务器里包含这个名字的就他一个 jar 包。有可能查出多个话,那我也不知道该用什么命令了= =

@omph 因为我没有听过呢...

@reticentfat 如果是环境变量的锅,我应该如何设置呢? 是不是我代码第二行书写错误。
newtype0092
2019-07-17 18:25:36 +08:00
你先用你的账号,比如说 xxx,试下是否正常,所有的命令都用全路径,比如 /bin/bash
crontab 里执行的时候也用 sudo -u 切换到你的 xxx 用户,保证环境变量完全一致
Alphabetcn
2019-07-17 18:27:04 +08:00
set -ex & crontab 输出从定向到某个文件看看
aocif23
2019-07-17 18:30:08 +08:00
看到了相对路径,想起了以前踩过的坑。。。cron 执行的脚本里全换成绝对路径,包括安装的程序。
ant2017
2019-07-17 18:31:50 +08:00
@skypyb 绝对路径里面有 rocket,你手动绝对路径拉一下
epicSoldier
2019-07-17 18:38:25 +08:00
应该是环境变量的问题,可以看一下 /var/mail/user 里的日志会打印 cron 执行时的环境变量
zheng5200
2019-07-17 18:57:26 +08:00
在 crontab 执行中最好用服务器的绝对路径,我以前就被这个坑过。。。
oneisall8955
2019-07-17 19:06:48 +08:00
crontab 里面用绝对路径 /bin/bash 执行,并把 crontab 里面加上重定向日志,看看执行有没有错误。最后监控脚本林也用绝对路径执行 start.sh 试试?
hell0v2
2019-07-19 09:24:18 +08:00
@skypyb 是 cron 行里加入,不是脚本里加
zydrsnuo
2019-12-14 02:33:01 +08:00
5 楼是对的,原因确实是获取到了多个 pid。
手动执行是用相对路径,进程列表里会有 rocket.jar 和 monitor.sh ,grep 匹配出来的只有一个 rocket.jar 的进程 id。cron 执行是用绝对路径,进程列表里会有 rocket.jar 和 /opt/rocket/bin/monitor.sh ,这两个进程都有关键字 rocket,grep 匹配出两个进程 id。
而脚本声明 pid 变量为整形,所以函数 checkProcess 里 pid 赋值那一步就报错了,这个函数的标准输出是空白。函数外边 pid=`checkProcess ${pName}` 这一句就是把空白值赋给 pid,等价与把 0 赋给 pid。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/583868

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX