MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Bash中的脚本与监控系统

2021-05-048.0k 阅读

Bash脚本基础

Bash脚本是一系列Bash命令的集合,这些命令按照顺序执行,能实现各种自动化任务。创建一个Bash脚本非常简单,只需创建一个文本文件,在文件开头指定Bash解释器路径,通常是#!/bin/bash,这一行被称为Shebang,它告诉系统使用哪个程序来执行脚本。

例如,创建一个简单的打印"Hello, World!"的脚本:

#!/bin/bash
echo "Hello, World!"

将上述内容保存为hello.sh文件,然后通过命令chmod +x hello.sh赋予其可执行权限,再执行./hello.sh,就能看到输出"Hello, World!"。

变量

在Bash脚本中,变量用于存储数据。定义变量很简单,例如:

name="John"
echo "My name is $name"

这里定义了变量name并赋值为"John",在echo语句中通过$name来引用变量的值。Bash中的变量不需要声明类型,并且变量名区分大小写。

除了自定义变量,Bash还有一些特殊变量。比如$0表示脚本本身的名称,$1$2等表示脚本的参数。例如:

#!/bin/bash
echo "Script name: $0"
echo "First argument: $1"
echo "Second argument: $2"

保存为args.sh,执行./args.sh apple banana,输出为:

Script name: ./args.sh
First argument: apple
Second argument: banana

条件语句

条件语句允许脚本根据不同的条件执行不同的代码块。Bash中常用的条件语句是if - then - else结构。例如:

#!/bin/bash
num=10
if [ $num -gt 5 ]; then
    echo "The number is greater than 5"
else
    echo "The number is less than or equal to 5"
fi

这里[ $num -gt 5 ]是条件判断,-gt表示大于。如果条件成立,执行then后的语句块,否则执行else后的语句块。fi表示if语句的结束。

还有一种if - elif - else结构,用于多个条件的判断。例如:

#!/bin/bash
score=75
if [ $score -ge 90 ]; then
    echo "A"
elif [ $score -ge 80 ]; then
    echo "B"
elif [ $score -ge 70 ]; then
    echo "C"
else
    echo "D"
fi

这里根据score的值来输出不同的等级。

循环语句

循环语句让脚本可以重复执行一段代码。常见的循环有for循环和while循环。

for循环用于遍历一个列表。例如:

#!/bin/bash
for fruit in apple banana cherry; do
    echo "I like $fruit"
done

这里for fruit in apple banana cherry表示fruit依次取值为applebananacherry,然后执行dodone之间的语句。

while循环则根据条件来决定是否继续循环。例如:

#!/bin/bash
count=1
while [ $count -le 5 ]; do
    echo "Count: $count"
    ((count++))
done

这里只要$count小于等于5,就会一直执行循环体,每次循环count的值增加1。

监控系统与Bash脚本的结合

监控系统旨在实时监测系统的各种指标,如CPU使用率、内存使用率、磁盘空间等,以便及时发现问题并采取措施。Bash脚本在构建简单高效的监控系统方面有着独特的优势。

系统资源监控

  1. CPU使用率监控 可以通过top命令获取系统的CPU使用信息,但top命令输出的是实时动态的信息,不利于脚本处理。我们可以使用mpstat命令,它能以更适合脚本解析的格式输出CPU统计信息。例如:
#!/bin/bash
cpu_usage=$(mpstat | grep "all" | awk '{print 100 - $12}')
echo "Current CPU usage: $cpu_usage%"
if (( $(echo "$cpu_usage > 80" | bc -l) )); then
    echo "CPU usage is too high!"
fi

上述脚本通过mpstat获取CPU的空闲率,然后计算出使用率。如果使用率超过80%,则输出提示信息。

  1. 内存使用率监控 free命令用于显示系统内存的使用情况。我们可以解析free命令的输出获取内存使用率。例如:
#!/bin/bash
total_mem=$(free -h | grep "Mem:" | awk '{print $2}')
used_mem=$(free -h | grep "Mem:" | awk '{print $3}')
mem_usage=$(echo "scale=2; ($used_mem / $total_mem) * 100" | bc -l)
echo "Current memory usage: $mem_usage%"
if (( $(echo "$mem_usage > 80" | bc -l) )); then
    echo "Memory usage is too high!"
fi

这里通过free -h获取内存的总量和已使用量,然后计算出使用率,并在使用率超过80%时输出提示。

  1. 磁盘空间监控 df命令用于查看文件系统的磁盘使用情况。我们可以监控特定分区的磁盘使用率。例如:
#!/bin/bash
disk_usage=$(df -h / | grep "/" | awk '{print $5}' | sed 's/%//')
echo "Disk usage of / partition: $disk_usage%"
if (( $(echo "$disk_usage > 80" | bc -l) )); then
    echo "Disk space is running low!"
fi

该脚本获取根分区/的磁盘使用率,并在使用率超过80%时发出警告。

服务状态监控

  1. 监控特定服务是否运行 对于基于Systemd的系统,可以使用systemctl命令来检查服务状态。例如监控nginx服务:
#!/bin/bash
service_status=$(systemctl is-active nginx)
if [ "$service_status" = "active" ]; then
    echo "Nginx is running"
else
    echo "Nginx is not running. Trying to start it..."
    systemctl start nginx
    new_status=$(systemctl is-active nginx)
    if [ "$new_status" = "active" ]; then
        echo "Nginx has been started successfully"
    else
        echo "Failed to start Nginx"
    fi
fi

此脚本先检查nginx服务是否处于活动状态,如果未运行,则尝试启动它,并再次检查启动是否成功。

  1. 通过端口监控服务 有些服务可能没有通过Systemd管理,我们可以通过监控服务所使用的端口来判断服务是否正常运行。例如监控MySQL服务(默认端口3306):
#!/bin/bash
port_status=$(netstat -tuln | grep ":3306" | wc -l)
if [ $port_status -gt 0 ]; then
    echo "MySQL is running"
else
    echo "MySQL is not running. Trying to start it..."
    service mysql start
    new_status=$(netstat -tuln | grep ":3306" | wc -l)
    if [ $new_status -gt 0 ]; then
        echo "MySQL has been started successfully"
    else
        echo "Failed to start MySQL"
    fi
fi

这里通过netstat命令检查3306端口是否被监听来判断MySQL服务是否运行,若未运行则尝试启动并再次确认。

监控结果的记录与报告

监控系统不仅要实时监测,还需要记录监控结果并生成报告,以便分析和追溯。

记录监控结果

  1. 日志文件记录 可以将监控结果写入日志文件。例如,对于CPU使用率监控脚本,可以修改为:
#!/bin/bash
cpu_usage=$(mpstat | grep "all" | awk '{print 100 - $12}')
echo "$(date): Current CPU usage: $cpu_usage%" >> cpu_monitor.log
if (( $(echo "$cpu_usage > 80" | bc -l) )); then
    echo "$(date): CPU usage is too high!" >> cpu_monitor.log
fi

这里通过>>将监控信息追加到cpu_monitor.log文件中,同时记录时间。

  1. 数据库记录 对于更复杂的监控系统,可能需要将监控数据记录到数据库中,以便进行数据分析和可视化。以MySQL数据库为例,首先要安装mysql - client,然后可以使用mysql命令行工具将数据插入数据库。例如:
#!/bin/bash
cpu_usage=$(mpstat | grep "all" | awk '{print 100 - $12}')
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
mysql -u username -ppassword -D monitoring_db -e "INSERT INTO cpu_usage (timestamp, usage) VALUES ('$timestamp', $cpu_usage)"

这里假设数据库中有一个monitoring_db数据库,表cpu_usagetimestampusage两个字段,将CPU使用率和时间记录到数据库中。

生成监控报告

  1. 简单文本报告 可以定期生成文本格式的监控报告。例如,每天生成一个包含前一天CPU、内存和磁盘使用情况的报告。
#!/bin/bash
# 生成CPU使用报告
cpu_report=$(grep "$(date -d "yesterday" +"%Y-%m-%d")" cpu_monitor.log)
# 生成内存使用报告
mem_report=$(grep "$(date -d "yesterday" +"%Y-%m-%d")" mem_monitor.log)
# 生成磁盘使用报告
disk_report=$(grep "$(date -d "yesterday" +"%Y-%m-%d")" disk_monitor.log)
echo "Yesterday's Monitoring Report" > daily_report.txt
echo "CPU Usage:" >> daily_report.txt
echo "$cpu_report" >> daily_report.txt
echo "Memory Usage:" >> daily_report.txt
echo "$mem_report" >> daily_report.txt
echo "Disk Usage:" >> daily_report.txt
echo "$disk_report" >> daily_report.txt

此脚本从各个监控日志文件中提取前一天的数据,并生成一个综合的文本报告daily_report.txt

  1. HTML报告 为了更直观地展示监控数据,可以生成HTML格式的报告。这需要使用一些工具来处理HTML模板和数据填充。例如,使用awksed等工具。
#!/bin/bash
# 读取HTML模板
template=$(cat report_template.html)
# 生成CPU使用数据表格
cpu_data=$(grep "$(date -d "yesterday" +"%Y-%m-%d")" cpu_monitor.log | awk -F': ' '{print "<tr><td>"$1"</td><td>"$3"</td></tr>"}')
# 生成内存使用数据表格
mem_data=$(grep "$(date -d "yesterday" +"%Y-%m-%d")" mem_monitor.log | awk -F': ' '{print "<tr><td>"$1"</td><td>"$3"</td></tr>"}')
# 生成磁盘使用数据表格
disk_data=$(grep "$(date -d "yesterday" +"%Y-%m-%d")" disk_monitor.log | awk -F': ' '{print "<tr><td>"$1"</td><td>"$3"</td></tr>"}')
# 填充模板
filled_template=$(echo "$template" | sed "s|{{CPU_DATA}}|$cpu_data|g" | sed "s|{{MEM_DATA}}|$mem_data|g" | sed "s|{{DISK_DATA}}|$disk_data|g")
# 输出HTML报告
echo "$filled_template" > daily_report.html

这里report_template.html是一个包含模板占位符的HTML文件,脚本通过替换占位符生成最终的HTML报告daily_report.html

自动化监控任务

为了实现持续的监控,需要将监控脚本设置为定时任务,让系统自动执行。

使用Cron实现定时任务

Cron是Linux系统中常用的定时任务调度工具。编辑Cron表可以使用crontab -e命令。

  1. 每分钟监控一次系统资源
* * * * * /path/to/cpu_monitor.sh
* * * * * /path/to/mem_monitor.sh
* * * * * /path/to/disk_monitor.sh

这样设置后,每分钟都会执行CPU、内存和磁盘监控脚本。

  1. 每天生成监控报告
0 0 * * * /path/to/daily_report.sh

这表示每天凌晨0点执行生成每日监控报告的脚本。

使用Systemd Timer实现定时任务

Systemd Timer是Systemd的一部分,也可以用于定时任务。首先创建一个服务单元文件,例如cpu - monitor.service

[Unit]
Description=CPU Monitor Service
ExecStart=/path/to/cpu_monitor.sh

然后创建一个Timer单元文件,例如cpu - monitor.timer

[Unit]
Description=Run CPU Monitor every minute

[Timer]
OnCalendar=* * * * *
Unit=cpu - monitor.service

[Install]
WantedBy=timers.target

之后通过以下命令启动和启用Timer:

sudo systemctl start cpu - monitor.timer
sudo systemctl enable cpu - monitor.timer

这样就通过Systemd Timer实现了每分钟执行一次CPU监控脚本的定时任务。

监控系统的扩展与优化

随着监控需求的增加,需要对监控系统进行扩展和优化。

分布式监控

在大型环境中,可能需要监控多个服务器。可以通过SSH在远程服务器上执行监控脚本,并将结果收集到中央服务器。例如:

#!/bin/bash
servers="server1 server2 server3"
for server in $servers; do
    ssh $server "path/to/cpu_monitor.sh" | sed "s/^/$server: /"
done

此脚本通过SSH在多个服务器上执行CPU监控脚本,并在输出结果前加上服务器名称。

监控指标的多样化

除了基本的系统资源和服务状态监控,还可以监控网络流量、进程状态等更多指标。例如监控网络流量:

#!/bin/bash
rx_bytes=$(cat /proc/net/dev | grep eth0 | awk '{print $2}')
tx_bytes=$(cat /proc/net/dev | grep eth0 | awk '{print $10}')
echo "Received bytes: $rx_bytes"
echo "Transmitted bytes: $tx_bytes"

这里通过/proc/net/dev文件获取网络接口eth0的接收和发送字节数。

性能优化

对于频繁执行的监控脚本,性能优化很重要。可以尽量减少命令的执行次数,使用缓存数据等。例如,在获取系统资源信息时,可以将一些常用的命令结果缓存起来,避免每次都重新执行命令。

#!/bin/bash
# 缓存CPU信息
cpu_info=$(mpstat)
cpu_usage=$(echo "$cpu_info" | grep "all" | awk '{print 100 - $12}')
# 缓存内存信息
mem_info=$(free -h)
total_mem=$(echo "$mem_info" | grep "Mem:" | awk '{print $2}')
used_mem=$(echo "$mem_info" | grep "Mem:" | awk '{print $3}')
mem_usage=$(echo "scale=2; ($used_mem / $total_mem) * 100" | bc -l)
echo "Current CPU usage: $cpu_usage%"
echo "Current memory usage: $mem_usage%"

通过缓存mpstatfree -h的结果,减少了命令的重复执行,提高了脚本的执行效率。

通过以上对Bash脚本在监控系统中的应用介绍,我们可以构建功能丰富、高效实用的监控系统,满足不同场景下的监控需求,保障系统的稳定运行。