Prometheus 通过node_exporter监控服务进程

✍️Auth:运维笔记       Date:2025/04/15       Cat:Linux服务器       👁️:20 次浏览

Prometheus 可以监控某个具体的进程,但需要配合适当的 exporter 来暴露该进程的指标信息。Prometheus 本身不会直接“监控进程”,而是通过访问一个 HTTP endpoint 来抓取指标数据(例如:http://localhost:9100/metrics)。

方案一:使用 node_exporter + process-exporter

process-exporter专门用来监控特定进程的 Exporter,可以根据进程名、cmdline 等来筛选监控的进程。

方案二:使用 node_exporter + Shell 脚本自定义指标

不想在服务器安装过多的软件,这里介绍方案二。

1,安装node_exporter启动collector.textfile.directory

安装并添加系统服务,步骤参考以前文章:Prometheus节点node_exporter监控添加至system系统服务启动

关键一点,在服务参数ExecStart加上启动参数启用了 --collector.textfile.directory 文件路径可自定义。

ubuntu@ubuntu$ cat /etc/systemd/system/node_exporter.service 
[Unit]
Description=Node Exporter
After=network.target
​
[Service]
User=node_exporter
Group=node_exporter
Type=simple
#ExecStart=/usr/local/bin/node_exporter
ExecStart=/usr/local/bin/node_exporter --collector.textfile.directory=/opt/logs/node_exporter/textfile_collector
​
[Install]
WantedBy=multi-user.target

以上配置Prometheus 会收集/opt/logs/node_exporter/textfile_collector目录下所有.prom 文件中的指标。

2,检测单进程shell脚本

检测进程命令pgrep -f PROCESS_NAME 匹配。

pgrep命令 : 检索进程PID号码,-f 匹配进程名。如检测redis进程是否存在。

ubuntu@ubuntu$ pgrep -f redis
24408

检测进程是否存在,存在写入1,不存在写入0。

注:指标名只能用小写字母、数字和下划线,不能有其他符号。

#!/bin/bash
​
METRIC_DIR="/opt/logs/node_exporter/textfile_collector"
PROCESS_NAME="redis-server"
​
#你需要把 - 替换成 _,合法指标
SAFE_NAME=$(echo "$PROCESS_NAME" | tr '-' '_')
METRIC_FILE="$METRIC_DIR/${SAFE_NAME}_up.prom"
​
# 创建目录(如果不存在)
[ ! -d "$METRIC_DIR" ] && mkdir -p "$METRIC_DIR"
​
# 判断进程是否存在,并写入指标
if pgrep -f "$PROCESS_NAME" > /dev/null; then
    echo "${SAFE_NAME}_up 1" > "$METRIC_FILE"
else
    echo "${SAFE_NAME}_up 0" > "$METRIC_FILE"
fi

简单的单进程检测就可以了。

3,测试验证

如脚本路径 /opt/logs/check_process.sh

#执行脚本
bash /opt/logs/check_process.sh
​
#查看文件指标是否写入
ubuntu@ubuntu$ cat /opt/logs/node_exporter/textfile_collector/redis_server_up.prom 
redis_server_up 1

已经写入,访问节点metrics看是否有此参数,可以浏览器访问,也可以curl测试。

命令访问,有此参数

ubuntu@ubuntu$ curl http://localhost:9100/metrics |grep redis_server_up
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0node_textfile_mtime_seconds{file="/opt/logs/node_exporter/textfile_collector/redis_server_up.prom"} 1.744629504e+09
100  106k    0  106k    0     0  8906k      0 --:--:-- --:--:-- --:--:-- 8906k
# HELP redis_server_up Metric read from /opt/logs/node_exporter/textfile_collector/redis_server_up.prom
# TYPE redis_server_up untyped
redis_server_up 1

浏览器访问也有,说明已经成功获取指标。

这时在grafana探索功能,也可以查询此参数了,后续可以根据此值设置告警通知了。

告警通知查看文章:Grafana 配置Prometheus告警并发送至telegram群组

最后设置定时任务(crontab),就可以了,每分钟执行一次。

* * * * * bash /opt/logs/check_process.sh

4,多进程检测shell脚本

如果需要检测多个进程,也可以升级下脚本,如下,只需要将进程名称加入到PROCESS_NAMES

#!/bin/bash
​
# 指标输出目录
METRIC_DIR="/opt/logs/node_exporter/textfile_collector"
​
# 要监控的进程列表(多个用空格分隔)
PROCESS_NAMES=("redis-server" "nginx" "mysqld")
​
# 如果目录不存在,则创建
[ ! -d "$METRIC_DIR" ] && mkdir -p "$METRIC_DIR"
​
# 遍历每个进程名
for PROCESS_NAME in "${PROCESS_NAMES[@]}"; do
    # 把 - 替换成 _ 以符合 Prometheus 格式
    SAFE_NAME=$(echo "$PROCESS_NAME" | tr '-' '_')
    METRIC_FILE="$METRIC_DIR/${SAFE_NAME}_up.prom"
​
    if pgrep -f "$PROCESS_NAME" > /dev/null; then
        echo "${SAFE_NAME}_up 1" > "$METRIC_FILE"
    else
        echo "${SAFE_NAME}_up 0" > "$METRIC_FILE"
    fi
done
​

每个进程都有独立的指标。redis_server_up, nginx_up, mysqld_up

5,检测进程后尝试重启服务

既然已经用脚本了,同样可以将服务重启功能加入。

检测进程如果不存在,尝试重启进程,在发送指标。

#!/bin/bash
​
METRIC_DIR="/opt/logs/node_exporter/textfile_collector"
LOG_FILE="/opt/logs/node_exporter/process_monitor.log"
​
# 定义进程名和启动命令:格式为 "进程名::启动命令"
declare -a PROCESS_LIST=(
  "redis-server::/opt/redis/bin/redis-server /opt/redis/conf/redis.conf"
  "nginx::systemctl start nginx"
  "mysqld::systemctl start mysql"
)
​
[ ! -d "$METRIC_DIR" ] && mkdir -p "$METRIC_DIR"
​
log() {
    echo "[$(date '+%F %T')] $1" >> "$LOG_FILE"
}
​
for ITEM in "${PROCESS_LIST[@]}"; do
    PROCESS_NAME="${ITEM%%::*}"                   # 拆出进程名
    START_CMD="${ITEM##*::}"                      # 拆出启动命令
    SAFE_NAME=$(echo "$PROCESS_NAME" | tr '-' '_')
    METRIC_FILE="$METRIC_DIR/${SAFE_NAME}_up.prom"
​
    if pgrep -f "$PROCESS_NAME" > /dev/null; then
        echo "${SAFE_NAME}_up 1" > "$METRIC_FILE"
    else
        echo "${SAFE_NAME}_up 0" > "$METRIC_FILE"
        log "[$PROCESS_NAME] not running. Attempting to start: $START_CMD"
​
        # 尝试启动
        eval "$START_CMD"
        sleep 5
​
        # 检查启动结果
        if pgrep -f "$PROCESS_NAME" > /dev/null; then
            echo "${SAFE_NAME}_up 1" > "$METRIC_FILE"
            log "[$PROCESS_NAME] started successfully."
        else
            echo "${SAFE_NAME}_up 0" > "$METRIC_FILE"
            log "[$PROCESS_NAME] failed to start."
        fi
    fi
done
​

配置格式:"进程名::启动命令",可扩展添加任意进程

启动失败会记录在 /opt/logs/node_exporter/process_monitor.log,可以用 tail -f 来实时查看。

测试,kill redis进程,和关闭mysql服务,运行脚本测试,查看日志和进程已成功启动。

#查看日志
ubuntu@ubuntu$ cat /opt/logs/node_exporter/process_monitor.log 
[2025-04-15 13:32:53] [mysqld] not running. Attempting to start: systemctl start mysql
[2025-04-15 13:32:56] [mysqld] started successfully.
[2025-04-15 13:33:52] [redis-server] not running. Attempting to start: /opt/redis/bin/redis-server /opt/redis/conf/redis.conf
[2025-04-15 13:33:54] [redis-server] started successfully.

#查看进程
ubuntu@ubuntu$ ps -ef|grep redis
root       25471       1  0 13:33 ?        00:00:00 /opt/redis/bin/redis-server 0.0.0.0:7001 [cluster]
ubuntu     25500   18162  0 13:35 pts/2    00:00:00 grep --color=auto redis

打赏作者

发表评论