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

如何编写Shell监控程序并排查用户进程统计脚本无输出问题?

问题解决与Shell脚本实现

一、修复你的无输出脚本

你的脚本执行后无输出,常见原因有两个:一是who命令未返回有效登录用户(比如当前无其他登录用户,或处于单用户模式);二是ps命令统计时包含表头行,导致逻辑异常。以下是优化后的脚本,同时处理用户名去重(避免同一用户多次登录重复统计):

# 去重获取已连接用户列表
users=$(who | awk '{print $1}' | sort -u)
for user in $users; do
    # 排除ps的表头行,统计实际进程数量
    nrprocesses=$(ps -u "$user" --no-headers | wc -l)
    echo "User: $user, number of processes: $nrprocesses"
done

如果仍无输出,先执行who命令确认是否有登录用户,或检查脚本执行权限。

二、显示已连接用户及所有进程的Shell程序

下面的脚本会列出每个已连接用户的所有进程详情(进程ID、父进程ID、命令):

#!/bin/bash
# 获取去重的已连接用户
connected_users=$(who | awk '{print $1}' | sort -u)

echo "=== 当前已连接用户及进程列表 ==="
for user in $connected_users; do
    echo -e "\n* 用户: $user"
    echo "-----------------------------"
    # 显示该用户的所有进程,输出PID、PPID和命令
    ps -u "$user" -o pid,ppid,cmd --no-headers
done

三、新连接触发的系统监控程序

要实现"新用户连接时在对应终端打印活跃用户及进程数"的需求,有两种实现方式:

方式1:基于utmp文件监控(需安装inotify-tools)

利用inotifywait监控记录登录信息的/var/run/utmp文件,实时感知用户登录事件:

#!/bin/bash
# 先安装依赖(Debian/Ubuntu系)
# sudo apt install inotify-tools -y

# 初始化用户列表
prev_users=$(who | awk '{print $1}' | sort -u)

echo "=== 系统登录监控已启动 ==="
while true; do
    # 监控utmp文件修改事件(用户登录/登出触发)
    inotifywait -e modify /var/run/utmp > /dev/null 2>&1
    # 获取当前用户列表
    curr_users=$(who | awk '{print $1}' | sort -u)
    # 对比找出新登录的用户
    new_users=$(comm -13 <(echo "$prev_users") <(echo "$curr_users"))
    if [ -n "$new_users" ]; then
        echo -e "\n=== 新用户登录,当前活跃用户及进程数 ==="
        # 遍历所有活跃用户统计进程数
        for user in $curr_users; do
            nr_processes=$(ps -u "$user" --no-headers | wc -l)
            echo "User: $user, 进程数: $nr_processes"
        done
        # 更新用户列表
        prev_users=$curr_users
    fi
done

将脚本后台运行(nohup ./login_monitor.sh &),新用户登录时会自动触发提示。

方式2:定时对比用户列表(无额外依赖)

通过定时循环对比用户列表变化,实现监控:

#!/bin/bash
prev_users=$(who | awk '{print $1}' | sort -u)

echo "=== 系统登录监控已启动 ==="
while true; do
    sleep 2
    curr_users=$(who | awk '{print $1}' | sort -u)
    new_users=$(comm -13 <(echo "$prev_users") <(echo "$curr_users"))
    if [ -n "$new_users" ]; then
        echo -e "\n=== 新用户登录,当前活跃用户及进程数 ==="
        for user in $curr_users; do
            nr_processes=$(ps -u "$user" --no-headers | wc -l)
            echo "User: $user, 进程数: $nr_processes"
        done
        prev_users=$curr_users
    fi
done

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:17:44