You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Memcached监控脚本控制台运行正常,crontab执行失败求助

问题描述

Memcached监控脚本以root身份在控制台运行正常,但通过crontab执行时失败,报错信息如下:

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
ValueError: could not convert string to float:
/root/bin/memcached_guard: line 33: [: ==: unary operator expected

该脚本用于检测Memcached的CPU使用率,超过阈值则重启服务,此前在另一服务器的crontab中运行正常。已尝试修改if语句的判断值为"1"、使用env命令运行脚本、对比两台服务器的cron环境(二者一致)、验证Python模块路径无问题,但均未解决。

脚本内容:

#!/bin/sh

# Max usage for memcached in percents
MEMCACHED_MAX_USAGE=70.0

# Where to send e-mail if there is a problem
MONITORING_EMAIL="xyz@xyz.com"

CURRENT_USAGE=$(top -bn 1 | grep -w memcached | awk '{print $9}')

#echo 'Currently using' $CURRENT_USAGE


# BASH does not support floating point numbers, so use Python
# Have to pass arguments as environment variables on same line so
# they are executed in same context as Python script
# Wrap into function for easier use

function check_usage {
MAX="$1" CUR="$2" python2 - <<END
import os
#import sys
#print "MAX Usage is " + os.environ['MAX']
#print "CUR Usage is " + os.environ['CUR']

if float(os.environ['MAX']) < float(os.environ['CUR']):
        print 1 
else:
        print 0 
END
}

if [ $(check_usage $MEMCACHED_MAX_USAGE $CURRENT_USAGE) == 1 ]
then
        echo "Memcached takes $CURRENT_USAGE% of CPU. Restarting" | mail -s "memcached problem detected" $MONITORING_EMAIL
        /sbin/service memcached restart
fi
故障原因
  • CURRENT_USAGE为空值:cron环境中top命令的输出格式可能与交互式终端不同,或者memcached进程短暂未被top捕获,导致grep -w memcached无匹配结果,最终CURRENT_USAGE为空字符串。
  • bash条件判断语法错误:当check_usage函数因CURRENT_USAGE为空触发Python错误后,函数返回空值,此时if [ == 1 ]会触发语法错误——因为条件左侧无有效值,bash将==识别为一元操作符,不符合语法规则。
解决办法

方案1:给CURRENT_USAGE设置默认值,避免空值

修改获取CURRENT_USAGE的代码,为空时默认赋值0:

CURRENT_USAGE=$(top -bn 1 | grep -w memcached | awk '{print $9}')
# 为空时默认设为0
CURRENT_USAGE=${CURRENT_USAGE:-0}

方案2:替换top为更可靠的pidstat命令(推荐)

top的输出列在不同环境可能有差异,改用pidstat获取CPU使用率更稳定:

# 先获取memcached的PID,再用pidstat获取CPU使用率
MEM_PID=$(pidof memcached)
if [ -n "$MEM_PID" ]; then
    # 采样1次,间隔1秒,取最后一行的CPU使用率
    CURRENT_USAGE=$(pidstat -p $MEM_PID 1 1 | tail -1 | awk '{print $8}')
else
    CURRENT_USAGE=0
fi

方案3:修复bash的if判断语法,添加引号防止空值

修改if语句,给命令替换的结果加引号,避免空值导致语法错误:

if [ "$(check_usage $MEMCACHED_MAX_USAGE $CURRENT_USAGE)" == "1" ]
then
        echo "Memcached takes $CURRENT_USAGE% of CPU. Restarting" | mail -s "memcached problem detected" $MONITORING_EMAIL
        /sbin/service memcached restart
fi

方案4:在Python脚本中处理空值情况

修改check_usage函数里的Python代码,主动处理CUR为空的场景:

import os

max_usage = float(os.environ['MAX'])
# 为空时默认设为0.0
cur_usage = float(os.environ['CUR'].strip()) if os.environ['CUR'].strip() else 0.0

if max_usage < cur_usage:
    print(1)
else:
    print(0)
验证方法
  1. 手动模拟CURRENT_USAGE为空的情况,执行脚本测试是否还报错:
CURRENT_USAGE='' ./memcached_guard
  1. 将脚本加入crontab后,查看cron日志(通常在/var/log/cron或/var/log/syslog)确认执行情况。

内容的提问来源于stack exchange,提问作者Rudolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 12:45:26