在 Linux 系统管理中,监控内存使用情况至关重要。我们开发了一个强大的 shell 脚本用于收集系统内存信息。
该脚本以 /bin/bash
为解释器,首先创建 /var/log/meminfo_collector.log
日志文件,若创建失败则记录错误并终止,以方便后续追踪调试。
接着根据当前日期在 /root/kylin_shell
下创建存储目录,形如 /root/kylin_shell/meminfos_<日期>
。然后切换到 /tmp
并创建临时信息目录。
脚本会检查 ps
、top
等关键命令是否存在,若不存在则记录错误并终止。
信息收集是核心,它从 /proc
文件系统读取多类信息,如 /proc/vmstat
等,还添加了 /proc/swaps
、/proc/buddyinfo
以深入了解内存使用情况。使用 ps
命令多种选项收集进程信息,包括进程树及资源使用,对内存使用量前 10 的进程,会深入 /proc/<PID>/status
获取详细状态。
同时,利用 top
、pidstat
、sar
等命令从不同角度收集系统性能数据,如 top -b -n 1
提供实时进程信息,pidstat -u -p ALL 1 2
按 1 秒间隔采样进程 CPU 使用率,sar
命令收集不同性能指标,free -h
以可读格式展示内存使用,vmstat 1 2
提供虚拟内存统计。
收集完成后,将临时信息目录打包成包含系统运行和当前时间的压缩文件,移动到存储目录并删除临时目录。最后设置存储目录 755 权限。
该脚本可通过 crontab
定时执行,例如 */1 * * * * /path/to/save_meminfos.sh > /dev/null 2>&1
,将输出重定向到 /dev/null
,仅将重要信息存于日志文件。
使用时,将脚本保存为 save_meminfos.sh
,添加执行权限并运行,也可按上述方式添加到 crontab
。此脚本有助于系统管理员监控管理内存,分析数据优化性能,保障系统稳定运行,其日志方便问题排查。
#!/bin/bash
# 定义日志文件
LOG_FILE="/var/log/meminfo_collector.log"
# 检查并创建日志文件
touch $LOG_FILE
if [ $? -ne 0 ]; then
echo "无法创建日志文件 $LOG_FILE" >> $LOG_FILE
exit 1
fi
# 检查并创建存储目录
DATE=$(date +%Y%m%d)
SAVE_DIR="/root/kylin_shell/meminfos_${DATE}"
if [! -d $SAVE_DIR ]; then
mkdir -p $SAVE_DIR >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法创建存储目录 $SAVE_DIR" >> $LOG_FILE
exit 1
fi
else
echo "目录 $SAVE_DIR 已经存在" >> $LOG_FILE
fi
# 切换到 /tmp 目录
pushd /tmp >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法切换到 /tmp 目录" >> $LOG_FILE
exit 1
fi
# 定义要收集的文件列表
FILES=("/proc/vmstat" "/proc/zoneinfo" "/proc/meminfo" "/proc/slabinfo" "/proc/pagetypeinfo" "/proc/swaps" "/proc/buddyinfo")
INFO_DIR="meminfos_$(date +%H%M%S)"
mkdir -p $INFO_DIR >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法创建信息目录 $INFO_DIR" >> $LOG_FILE
exit 1
fi
# 检查所需命令是否存在
COMMANDS=("ps" "top" "pidstat" "sar" "free" "vmstat")
for cmd in "${COMMANDS[@]}"; do
if! command -v $cmd >/dev/null 2>&1; then
echo "$cmd 命令不存在,无法完成信息收集" >> $LOG_FILE
exit 1
fi
done
# 收集 /proc 下的文件信息
for file in "${FILES[@]}"; do
filename=$(basename $file)
cat $file > $INFO_DIR/${filename} >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法将 $file 信息保存到 $INFO_DIR/${filename}" >> $LOG_FILE
exit 1
fi
done
# 收集 ps 信息
ps aux --sort=+rss > $INFO_DIR/ps_aux.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 ps aux 信息" >> $LOG_FILE
exit 1
fi
ps -eLo comm,pid,tid,psr,%cpu,%mem,rss,vsz,etimes > $INFO_DIR/ps_eLo.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 ps -eLo 信息" >> $LOG_FILE
exit 1
fi
ps axjf > $INFO_DIR/ps_axjf.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 ps axjf 信息" >> $LOG_FILE
exit 1
fi
# 收集 top 信息
top -b -n 1 > $INFO_DIR/top_info.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 top 信息" >> $LOG_FILE
exit 1
end
# 收集 pidstat 信息
pidstat -u -p ALL 1 2 > $INFO_DIR/pidstat_info.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 pidstat 信息" >> $LOG_FILE
exit 1
end
# 收集 sar 信息
sar -P ALL 1 2 > $INFO_DIR/sar_all_info.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 sar -P ALL 信息" >> $LOG_FILE
exit 1
end
sar -q 1 2 > $INFO_DIR/sar_q_info.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 sar -q 信息" >> $LOG_FILE
exit 1
end
# 收集 free 信息
free -h > $INFO_DIR/free_info.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 free 信息" >> $LOG_FILE
exit 1
end
# 收集 vmstat 信息
vmstat 1 2 > $INFO_DIR/vmstat_info.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存 vmstat 信息" >> $LOG_FILE
exit 1
end
# 收集进程信息
mkdir -p $INFO_DIR/process_top10 >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法创建进程信息目录 $INFO_DIR/process_top10" >> $LOG_FILE
exit 1
end
for i in $(ps aux --sort=+rss|tail -n 10|awk '{print $2}'); do
cat /proc/$i/status > $INFO_DIR/process_top10/proc_${i}_status.txt >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法保存进程 $i 的状态信息" >> $LOG_FILE
exit 1
end
end
# 打包文件
uptime_val=$(cat /proc/uptime | awk '{print $1}')
tar_filename="meminfos_${uptime_val}_$(date +%H%M%S).tar.gz"
tar zcvf $tar_filename $INFO_DIR >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法将 $INFO_DIR 打包为 $tar_filename" >> $LOG_FILE
exit 1
end
# 移动文件
mv $tar_filename $SAVE_DIR >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法将 $tar_filename 移动到 $SAVE_DIR" >> $LOG_FILE
exit 1
end
# 清理临时文件
rm -rf $INFO_DIR >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法删除临时目录 $INFO_DIR" >> $LOG_FILE
exit 1
end
# 设置存储目录权限
chmod -R 755 $SAVE_DIR >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法设置 $SAVE_DIR 权限" >> $LOG_FILE
exit 1
end
# 输出完成信息
echo "内存信息收集完成,存储在 $SAVE_DIR/$tar_filename" >> $LOG_FILE
# 回到原目录
popd >> $LOG_FILE 2>&1
if [ $? -ne 0 ]; then
echo "无法回到原目录" >> $LOG_FILE
exit 1
end
脚本功能解释
-
日志文件创建与错误处理
:
- 首先,脚本会尝试创建一个日志文件
/var/log/meminfo_collector.log
,用于记录脚本的操作和可能出现的错误。如果创建失败,会将错误信息写入该文件并退出脚本,以确保后续的操作可以被追踪和调试。
- 首先,脚本会尝试创建一个日志文件
-
存储目录操作
:
- 根据当前日期生成存储目录
SAVE_DIR
(例如/root/kylin_shell/meminfos_20250121
),如果该目录不存在,则创建它,同时将操作结果记录到日志文件中;如果目录已经存在,也会记录相应信息。
- 根据当前日期生成存储目录
-
切换目录与信息目录创建
:
- 切换到
/tmp
目录并创建一个以当前时分秒命名的信息目录INFO_DIR
(例如meminfos_123456
),用于临时存储收集到的信息。任何操作失败都会记录到日志文件并退出脚本。
- 切换到
-
命令检查
:
- 检查
ps
、top
、pidstat
、sar
、free
和vmstat
等命令是否存在,若不存在会记录错误信息并退出脚本,确保后续操作不会因缺少命令而中断。
- 检查
-
信息收集
:
-
从
/proc
文件系统收集多种信息:
-
从
/proc/vmstat
、/proc/zoneinfo
、/proc/meminfo
、/proc/slabinfo
、/proc/pagetypeinfo
、/proc/swaps
和/proc/buddyinfo
等文件中读取信息并存储到INFO_DIR
下的相应文件中。 -
使用
ps
命令收集进程信息:
ps aux --sort=+rss
按内存使用量对进程排序并保存结果。ps -eLo comm,pid,tid,psr,%cpu,%mem,rss,vsz,etimes
收集更详细的进程信息,包括进程的命令、进程 ID、线程 ID、处理器编号、CPU 使用率、内存使用率、实际内存使用、虚拟内存大小和进程运行时间等。ps axjf
输出进程树信息,有助于查看进程间的关系。
-
-
使用
top -b -n 1
以批处理模式运行一次top
命令,收集系统的实时进程信息。 -
使用
pidstat -u -p ALL 1 2
收集进程的 CPU 使用率信息,每 1 秒采样一次,共采样 2 次。 -
使用
sar -P ALL 1 2
收集每个 CPU 的性能数据,每 1 秒采样一次,共采样 2 次;sar -q 1 2
收集系统的平均负载信息,每 1 秒采样一次,共采样 2 次。 -
使用
free -h
以人类可读的格式显示系统的内存使用情况。 -
使用
vmstat 1 2
收集系统的虚拟内存统计信息,每 1 秒采样一次,共采样 2 次。 -
对于内存使用量最大的前 10 个进程,收集它们的
/proc/<PID>/status
信息并存储在process_top10
目录下。
-
-
文件打包、移动和清理
:
- 使用
tar
命令将INFO_DIR
目录打包成一个以系统运行时间和当前时间命名的压缩文件,例如meminfos_12345.123456.tar.gz
。 - 将打包文件移动到存储目录
SAVE_DIR
中,并将操作结果记录到日志文件。 - 删除临时的
INFO_DIR
目录,避免残留临时文件。
- 使用
-
权限设置和完成信息
:
- 为存储目录
SAVE_DIR
及其内容设置 755 权限,以确保文件的安全性和可访问性。 - 最后,将完成信息记录到日志文件中并回到原目录。
- 为存储目录
三、文章
《系统内存信息收集脚本的实现与优化》
在 Linux 系统管理和性能监控中,了解系统的内存使用情况是至关重要的。为了方便、全面且可靠地收集系统内存相关信息,我们开发了一个功能强大的 shell 脚本。这个脚本可以帮助系统管理员深入分析系统的内存使用模式、进程的内存消耗情况以及系统的性能表现,为性能优化和故障排除提供了有力的数据支持。
该脚本以 /bin/bash
为解释器,在开始时,它会尝试创建一个日志文件 /var/log/meminfo_collector.log
。这个日志文件是整个脚本的重要部分,它会记录脚本执行过程中的每一个重要步骤和可能出现的错误信息,方便后续的查看和分析。如果在创建日志文件时出现问题,脚本会立即终止并将错误信息记录在日志中,防止可能出现的错误操作被忽略。
接着,脚本会根据当前日期创建一个存储目录,存储目录位于 /root/kylin_shell
下,以 meminfos_<日期>
的形式命名,例如 /root/kylin_shell/meminfos_20250121
。这有助于将不同日期的信息分类存储,方便查找和对比。
然后,脚本会切换到 /tmp
目录并创建一个临时信息目录,该目录的名称包含当前的时分秒,确保其唯一性。在进行信息收集之前,会检查一些常用的系统命令,如 ps
、top
、pidstat
、sar
、free
和 vmstat
是否存在,若这些命令不存在,脚本会在日志中记录错误信息并终止,因为这些命令是收集关键信息所必需的。
信息收集是该脚本的核心部分。它会从 /proc
文件系统中读取众多信息,这些 /proc
文件包含了系统运行时的内核数据,如 /proc/vmstat
提供了系统的虚拟内存统计信息,/proc/zoneinfo
展示了内存区域的信息,/proc/meminfo
包含了系统内存使用的总体信息等。此外,还收集了 /proc/swaps
和 /proc/buddyinfo
这些额外的文件信息,/proc/swaps
可以让我们了解交换分区的使用情况,而 /proc/buddyinfo
则有助于我们查看内存碎片信息,这些信息对于理解系统的内存管理和性能优化都非常重要。
在进程信息收集方面,使用 ps
命令的多个选项,不仅能获取进程的常规信息,还能收集到进程的详细信息,包括进程的资源使用、线程信息以及进程树信息。例如,ps -eLo comm,pid,tid,psr,%cpu,%mem,rss,vsz,etimes
提供了进程的详细资源使用情况,ps axjf
展示了进程的层次结构,这对于分析进程之间的关系和资源分配非常有帮助。同时,对于内存使用量最高的前 10 个进程,会深入到它们的 /proc/<PID>/status
文件中,获取更详细的进程状态信息。
为了更全面地了解系统性能,使用 top
、pidstat
和 sar
命令进行多维度的信息收集。top -b -n 1
可以提供系统实时的进程信息,pidstat -u -p ALL 1 2
能够以 1 秒为间隔采样 2 次进程的 CPU 使用率,sar -P ALL 1 2
和 sar -q 1 2
分别从不同角度反映了系统的性能指标,而 free -h
以人类可读的方式展示系统的内存使用情况,vmstat 1 2
则从虚拟内存统计的角度提供系统性能数据。
收集完信息后,会将临时信息目录下的所有信息打包成一个压缩文件,文件名包含系统的运行时间和当前时间,确保每个打包文件都有独特的标识。随后将该压缩文件移动到存储目录中,并删除临时信息目录,避免占用 /tmp
空间。最后,为存储目录设置 755 权限,确保其内容可以被有权限的用户访问和管理。
该脚本还可以通过 crontab 进行定时执行,例如使用 */1 * * * * /path/to/save_meminfos.sh > /dev/null 2>&1
可以让脚本每分钟运行一次,这样系统管理员可以根据自己的需求设置不同的时间间隔,定期收集系统内存信息。通过将输出重定向到 /dev/null
,避免在执行过程中产生过多的终端输出,仅将重要信息存储在日志文件中。
总的来说,这个脚本是一个全面、可靠且易于维护的系统内存信息收集工具,通过不断优化和扩展,它可以满足不同场景下的系统监控需求,为系统管理员提供丰富的信息资源,帮助他们更好地维护系统的性能和稳定性。
使用说明:
- 将上述脚本保存为一个文件,例如
save_meminfos.sh
。 - 确保该脚本有执行权限,可以使用
chmod +x save_meminfos.sh
命令添加权限。 - 运行脚本可以直接使用
./save_meminfos.sh
。 - 可以将脚本添加到 crontab 中进行定时执行,将
/path/to/save_meminfos.sh
替换为实际脚本的存储路径,例如:
#crontab -e
*/1 * * * * /path/to/save_meminfos.sh > /dev/null 2>&1
标签:INFO,shell,LOG,收集,信息,内存,FILE,proc,DIR
From: https://blog.csdn.net/qq_40797754/article/details/145281481