Linux操作系统Shell脚本企业级综合练习
前言:
在企业级Linux运维中,Shell脚本是自动化任务的基石。随着服务器规模扩大和运维复杂度提升,脚本需兼顾高效性、健壮性与安全性。
本练习聚焦以下核心目标:
1.标准化运维流程:通过脚本替代重复操作(如监控、备份、部署),减少人为错误。
2.风险控制:遵循企业级脚本规范(如错误处理、日志追踪、权限管理),避免误操作导致生产事故。
3.性能优化:整合系统资源监控、网络调优等场景,提升服务器运行效率。
目录
题目一:系统信息收集脚本
1.编写一个脚本名为 collect_system_info.sh,实现以下功能:
2.Shell脚本内容:
3.Shell脚本验证 :
题目二:用户管理配置脚本
1.创建一个脚本名为 user_config.sh,完成以下任务:
2.Shell脚本内容:
3. Shell脚本验证:(1)创建新用户:
(2)验证用户信息:
(3) 验证用户组:
(4) 验证用户组信息:
(5)测试已存在用户:
(6)测试新用户创建和验证用户信息文件:
题目三:磁盘空间管理脚本
1.编写一个脚本名为 disk_management.sh,执行以下操作:
2.Shell脚本内容:
3.Shell脚本验证:
(1)启动脚本
(2)验证输出文件内容
(3)验证cron任务
题目四:网络配置检查脚本
1.创建一个脚本名为 network_check.sh,实现以下功能:
2.Shell脚本内容:
3.Shell脚本验证:
(1)启动脚本,控制台输出:
(2)验证输出文件:
题目五:系统日志分析脚本
1.编写一个脚本名为 log_analysis.sh,完成以下任务:
2.Shell脚本内容:
3.Shell脚本验证:
(1)创建测试日志文件
(2)启动脚本测试功能
(3)验证输出文件
总结
题目一:系统信息收集脚本
1.编写一个脚本名为 collect_system_info.sh
,实现以下功能:
(1)收集系统的基本信息,包括但不限于操作系统版本、内核版本、主机名,并将这些信息输出到一个名为 system_info.txt
的文件中,每个信息占一行,并加上清晰的说明标签。
(2)统计当前系统中正在运行的进程数量,并将结果追加到 system_info.txt
文件中,格式为“正在运行的进程数量:[具体数量]”。
(3)使用合适的命令查找系统中占用 CPU 资源最多的前 5 个进程(如果系统有相关命令支持的话),并将它们的进程 ID 和进程名称输出到 system_info.txt
文件中,格式为“占用 CPU 多的进程:进程 ID - 进程名称”,每个进程占一行。如果系统无法直接找出前 5 个,可根据实际情况尽可能多地找出占用高的进程展示。
2.Shell脚本内容:
#!/bin/bash# 任务1:收集系统基本信息
{# 操作系统版本(通过/etc/os-release)if [ -f /etc/os-release ]; thenwhile IFS='=' read -r key value; doif [ "$key" = "PRETTY_NAME" ]; thenecho "操作系统版本:${value//\"/}"fidone < /etc/os-releasefi# 内核版本echo "内核版本:$(uname -r)"# 主机名echo "主机名:$(hostname)"
} > system_info.txt# 任务2:统计运行进程数量
process_count=$(ps -e | wc -l)
echo "正在运行的进程数量:$((process_count - 1))" >> system_info.txt # 减去标题行# 任务3:查找CPU占用前5的进程
{echo "占用CPU多的进程:"# 使用ps按CPU排序并获取前6行(含标题行)ps -eo pid,pcpu,comm --sort=-pcpu | head -n 6 | while read -r line; do# 跳过标题行if [[ $line != "PID %CPU COMMAND" ]]; thenpid=$(echo "$line" | cut -d' ' -f1)cmd=$(echo "$line" | tr -s ' ' | cut -d' ' -f3-)echo "进程ID $pid - $cmd"fidone
} >> system_info.txtecho "系统信息收集完成,结果已保存到 system_info.txt"
3.Shell脚本验证 :
[root@ding zonghe]# ./collect_system_info.sh
系统信息收集完成,结果已保存到 system_info.txt[root@ding zonghe]# cat system_info.txt
操作系统版本:CentOS Linux 7 (Core)
内核版本:3.10.0-1160.el7.x86_64
主机名:ding
正在运行的进程数量:287
占用CPU多的进程:
进程ID 1 - systemd
进程ID 2 - kthreadd
进程ID 4 - kworker/0:0H
进程ID 6 - ksoftirqd/0
进程ID 7 - migration/0
题目二:用户管理配置脚本
1.创建一个脚本名为 user_config.sh
,完成以下任务:
(1)接受一个用户名为参数,如果该用户不存在,则创建这个用户,并设置一个随机生成的 8 位包含大小写字母和数字的密码(可借助相关命令或工具实现随机密码生成)。将用户信息(用户名和密码)追加到一个名为 users.txt
的文件中,格式为“用户名:密码”。
(2)为新创建的用户添加一个备注信息,备注信息内容为“新创建用户于[当前日期]”,使用 chfn
命令实现(如果系统支持)。如果系统没有 chfn
命令,可将备注信息以一种合适的方式记录下来,比如在 users.txt
文件中用户名对应行的末尾添加备注。
(3)将该用户添加到一个名为 common_group
的用户组中(如果该用户组不存在,则先创建它)。
2.Shell脚本内容:
#!/bin/bash#检查是否提供了用户名参数
if [ $# -ne 1 ];thenecho "错误:请提供一个用户名作为参数"echo "用法:$0 <用户名>"exit 1
fiusername=$1# 检查用户是否存在
if id -u "$username" &>/dev/null;thenecho "用户 '$username' 已存在,跳过创建"
else#生成随机密码(8位,内包含大小写字母和数字)password=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 8)#创建用户并设置密码useradd -m -s /bin/bash "$username"echo "$username:$password" | chpasswd#添加创建日期备注current_date=$(date +"%Y-%m-%d")#记录用户信息到文件echo "$username:$password 备注:新创建用户于$current_date" >> users.txtecho "用户'$username' 已创建,密码为:$password"echo "用户信息已记录到 users.txt 文件"
fi#确保common_group组存在
if ! getent group common_group &>/dev/null; thengroupadd common_groupecho "已创建用户组 'common_group'"
fi
#将用户添加到组(如果尚未在组中)
if ! id -nG "$username" | grep -qw "common_group";thenusermod -aG common_group "$username"echo "已将用户 '$username' 添加到 'common_group' 组"
elseecho "用户 '$username' 已在 'common_group' 组中"
fiexit 0
3. Shell脚本验证:
(1)创建新用户:
[root@ding zonghe]# ./user_config.sh testuser1
用户'testuser1' 已创建,密码为:DRP7PUZ6
用户信息已记录到 users.txt 文件
已创建用户组 'common_group'
已将用户 'testuser1' 添加到 'common_group' 组
(2)验证用户信息:
[root@ding zonghe]# cat users.txt
testuser1:DRP7PUZ6 备注:新创建用户于2025-06-08
(3) 验证用户组:
[root@ding zonghe]# groups testuser1
testuser1 : testuser1 common_group
(4) 验证用户组信息:
[root@ding zonghe]# getent group common_group
common_group:x:1005:testuser1
(5)测试已存在用户:
[root@ding zonghe]# ./user_config.sh testuser1
用户 'testuser1' 已存在,跳过创建
用户 'testuser1' 已在 'common_group' 组中
(6)测试新用户创建和验证用户信息文件:
[root@ding zonghe]# ./user_config.sh testuser2
用户'testuser2' 已创建,密码为:BQrX7ApC
用户信息已记录到 users.txt 文件
已将用户 'testuser2' 添加到 'common_group' 组[root@ding zonghe]# cat users.txt
testuser1:DRP7PUZ6 备注:新创建用户于2025-06-08
testuser2:BQrX7ApC 备注:新创建用户于2025-06-08
题目三:磁盘空间管理脚本
1.编写一个脚本名为 disk_management.sh
,执行以下操作:
(1)查找系统中磁盘空间使用率超过 80%的分区,将这些分区的挂载点和使用率信息输出到一个名为 disk_usage_report.txt
文件中,格式为“挂载点:使用率%”,每个分区占一行。
(2)对于使用率超过 90%的分区,找出其中占用空间最大的前 10 个目录(如果可以通过命令直接实现的话,可使用合适的命令和参数),并将它们的路径和占用空间大小(以合适的单位显示,如 MB 或 GB)输出到一个名为 large_directories.txt
文件中,格式为“目录路径:占用空间大小”,每个目录占一行。如果无法直接找出前 10 个,尽可能多地找出大目录展示。
(3)创建一个 cron 任务(如果系统支持 cron),让这个脚本每天凌晨 3 点自动执行一次,以持续监测磁盘空间情况。
2.Shell脚本内容:
#!/bin/bash# 定义报告文件
report_file="disk_usage_report.txt"
large_dirs_file="large_directories.txt"# 清空或创建报告文件
: > "$report_file"
: > "$large_dirs_file"# 获取磁盘信息并处理
df -P | tail -n +2 | while read -r line; do# 压缩连续空格compressed_line=$(echo "$line" | tr -s ' ')# 提取使用率(第五列)和挂载点(第六列开始)usage_percent=$(echo "$compressed_line" | cut -d ' ' -f 5)mount_point=$(echo "$compressed_line" | cut -d ' ' -f 6-)# 移除使用率的百分号并转换为数字usage=${usage_percent%\%}# 检查使用率是否超过80%if [ "$usage" -ge 80 ]; thenecho "$mount_point:$usage_percent" >> "$report_file"# 检查使用率是否超过90%if [ "$usage" -ge 90 ]; then# 创建临时文件tmp_file1=$(mktemp)tmp_file2=$(mktemp)# 获取分区下目录大小(KB)并排序du -x -k "$mount_point" 2>/dev/null | sort -nr > "$tmp_file1"# 提取前10个目录路径head -n 10 "$tmp_file1" | cut -f 2- > "$tmp_file2"# 处理每个大目录while IFS= read -r dir; do# 获取人类可读的大小size=$(du -sh "$dir" 2>/dev/null | cut -f 1)# 写入报告文件echo "$dir:$size" >> "$large_dirs_file"done < "$tmp_file2"# 清理临时文件rm -f "$tmp_file1" "$tmp_file2"fifi
done# 添加cron任务
if [ "$(id -u)" -eq 0 ]; thencron_entry="0 3 * * * $(readlink -f "$0")"if ! crontab -l | grep -qF "$(readlink -f "$0")"; then(crontab -l 2>/dev/null; echo "$cron_entry") | crontab -fi
fi
3.Shell脚本验证:
(1)启动脚本
[root@ding zonghe]# ./disk_management.sh
磁盘空间报告已生成: disk_usage_report.txt
大目录报告已生成: large_directories.txt
已设置每日凌晨3点自动执行任务
(2)验证输出文件内容
[root@ding zonghe]# cat disk_usage_report.txt
/run/media/root/CentOS 7 x86_64:100%[root@ding zonghe]# cat large_directories.txt
/run/media/root/CentOS 7 x86_64:9.6G
/run/media/root/CentOS 7 x86_64/Packages:9.0G
/run/media/root/CentOS 7 x86_64/LiveOS:498M
/run/media/root/CentOS 7 x86_64/images:68M
/run/media/root/CentOS 7 x86_64/isolinux:60M
/run/media/root/CentOS 7 x86_64/images/pxeboot:60M
/run/media/root/CentOS 7 x86_64/repodata:29M
/run/media/root/CentOS 7 x86_64/EFI:8.4M
/run/media/root/CentOS 7 x86_64/EFI/BOOT:8.4M
/run/media/root/CentOS 7 x86_64/EFI/BOOT/fonts:2.5M
(3)验证cron任务
[root@ding zonghe]# crontab -l
0 3 * * * /root/zonghe/disk_management.sh
题目四:网络配置检查脚本
1.创建一个脚本名为 network_check.sh
,实现以下功能:
(1)检查系统的网络连接状态,判断是否能够正常访问互联网(可以尝试访问一个知名的、稳定的外网地址,如谷歌的公共 DNS 服务器 8.8.8.8),如果能访问则输出“网络连接正常”,否则输出“网络连接故障”。
(2)列出当前系统中所有的网络接口及其 IP 地址,并将结果输出到一个名为 network_info.txt
文件中,格式为“网络接口:IP 地址”,每个接口占一行。
(3)检查系统的防火墙规则(如果系统有防火墙),将当前启用的防火墙规则列表输出到一个名为 firewall_rules.txt
文件中。如果系统没有防火墙或者无法直接获取规则列表,可以输出“无防火墙或无法获取规则信息”到该文件中。
2.Shell脚本内容:
#!/bin/bash# 检查网络连接状态
check_internet() {# 尝试ping 8.8.8.8 3次,超时2秒if ping -c 3 -W 2 8.8.8.8 &> /dev/null; thenecho "网络连接正常"elseecho "网络连接故障"fi
}# 获取网络接口及其IP地址
get_network_info() {# 获取所有网络接口interfaces=$(ip link show | grep -E '^[0-9]+:' | cut -d: -f2 | sed 's/ //')for iface in $interfaces; do# 跳过回环接口if [ "$iface" = "lo" ]; thencontinuefi# 获取IPv4地址ipv4=$(ip addr show $iface | grep -E 'inet\s' | cut -d' ' -f6 | cut -d'/' -f1)# 如果找到IP地址则输出if [ -n "$ipv4" ]; thenecho "$iface:$ipv4"fidone
}# 获取防火墙规则
get_firewall_rules() {# 检查firewalld服务状态if systemctl is-active firewalld &> /dev/null; thenecho "防火墙状态:运行中"echo "防火墙规则:"firewall-cmd --list-allelif command -v iptables &> /dev/null; then# 检查是否有非默认规则if iptables -L -n | grep -q -v "Chain INPUT (policy ACCEPT)" || \iptables -L -n | grep -q -v "Chain FORWARD (policy ACCEPT)" || \iptables -L -n | grep -q -v "Chain OUTPUT (policy ACCEPT)"; thenecho "防火墙状态:运行中(使用iptables)"echo "防火墙规则:"iptables -L -nelseecho "无防火墙或无法获取规则信息"fielseecho "无防火墙或无法获取规则信息"fi
}# 主函数
main() {# 检查网络连接状态network_status=$(check_internet)echo "网络连接状态:$network_status"# 获取网络接口信息get_network_info > network_info.txtecho "网络接口信息已保存到 network_info.txt"# 获取防火墙规则get_firewall_rules > firewall_rules.txtecho "防火墙规则已保存到 firewall_rules.txt"# 显示报告摘要echo -e "\n===== 网络检查摘要 ====="echo "1. $network_status"echo "2. 网络接口信息:"cat network_info.txtecho -e "\n3. 防火墙状态:"head -n 2 firewall_rules.txt
}# 执行主函数
main
3.Shell脚本验证:
(1)启动脚本,控制台输出:
[root@ding zonghe]# ./network_check.sh
网络连接状态:网络连接正常
网络接口信息已保存到 network_info.txt
防火墙规则已保存到 firewall_rules.txt===== 网络检查摘要 =====
1. 网络连接正常
2. 网络接口信息:
ens33:192.168.72.100
ens37:192.168.72.134
virbr0:192.168.122.13. 防火墙状态:
防火墙状态:运行中
防火墙规则:
(2)验证输出文件:
[root@ding zonghe]# cat network_info.txt
ens33:192.168.72.100
ens37:192.168.72.134
virbr0:192.168.122.1[root@ding zonghe]# cat firewall_rules.txt
防火墙状态:运行中
防火墙规则:
public (active)target: defaulticmp-block-inversion: nointerfaces: ens33 ens37sources: services: dhcpv6-client sshports: protocols: masquerade: noforward-ports: source-ports: icmp-blocks: rich rules:
题目五:系统日志分析脚本
1.编写一个脚本名为 log_analysis.sh
,完成以下任务:
(1)分析系统的一个关键应用程序的日志文件(假设日志文件路径为 /var/log/app.log
),统计该日志文件中在过去 24 小时内出现错误信息(假设错误信息有特定的关键字,如 ERROR)的次数,并将结果输出到一个名为 error_count.txt
文件中,内容仅包含错误次数的数字。
(2)找出包含错误信息的日志行中,出现频率最高的前 3 个错误消息内容(如果有多行错误信息内容相同,则视为同一类错误),并将它们及其出现次数输出到一个名为 top_errors.txt
文件中,格式为“错误消息:出现次数”,每个错误消息占一行。
(3)将所有包含错误信息的日志行提取出来,保存到一个新的文件名为 errors.log
的文件中。
2.Shell脚本内容:
#!/bin/bashlog_file="/var/log/app.log"
error_count=0# 检查日志文件是否存在
if [ ! -f "$log_file" ]; thenecho "0" > error_count.txtecho "错误:日志文件 $log_file 不存在" > top_errors.txttouch errors.logecho "日志文件不存在,已创建空报告"exit 1
fi# 1. 统计过去24小时内的ERROR次数
# 获取当前时间和24小时前的时间戳
current_time=$(date +%s)
one_day_ago=$((current_time - 86400))# 清空errors.log文件
> errors.log# 逐行处理日志文件
while IFS= read -r line; do# 检查行是否包含ERRORif echo "$line" | grep -q "ERROR"; then# 提取日志时间(假设时间格式为 MMM DD HH:MM:SS)log_date_str=$(echo "$line" | cut -d' ' -f1-3)# 将日志时间转换为时间戳log_timestamp=$(date -d "$log_date_str" +%s 2>/dev/null)# 如果时间转换成功且在24小时内if [ -n "$log_timestamp" ] && [ "$log_timestamp" -ge "$one_day_ago" ]; then# 增加错误计数((error_count++))# 将错误行添加到errors.logecho "$line" >> errors.logfifi
done < "$log_file"# 写入错误计数
echo "$error_count" > error_count.txt# 2. 统计最常见的3个错误消息
if [ "$error_count" -gt 0 ]; then# 提取错误消息并统计频率sort errors.log | uniq -c | sort -nr | head -n 3 | while read count line; do# 移除计数前面的空格clean_count=$(echo "$count" | tr -d ' ')echo "$line:$clean_count"done > top_errors.txt
elseecho "没有找到错误日志" > top_errors.txt
fiecho "日志分析完成"
echo "错误计数: $error_count"
3.Shell脚本验证:
(1)创建测试日志文件
[root@ding zonghe]# vim /var/log/app.log
[root@ding zonghe]# cat errors.log
日志内容:
Jun 8 20:00:00 server ERROR: Disk full on /dev/sda1
Jun 8 20:01:00 server ERROR: Connection timeout to database
Jun 8 20:02:00 server ERROR: Disk full on /dev/sda1
Jun 8 20:03:00 server ERROR: Permission denied for user
(2)启动脚本测试功能
[root@ding zonghe]# ./log_analysis.sh
日志分析完成
错误计数:4
(3)验证输出文件
[root@ding zonghe]# cat top_errors.txt
Jun 8 20:03:00 server ERROR: Permission denied for user: 1
Jun 8 20:02:00 server ERROR: Disk full on /dev/sda1: 1
Jun 8 20:01:00 server ERROR: Connection timeout to database: 1
[root@ding zonghe]# cat errors.log
Jun 8 20:00:00 server ERROR: Disk full on /dev/sda1
Jun 8 20:01:00 server ERROR: Connection timeout to database
Jun 8 20:02:00 server ERROR: Disk full on /dev/sda1
Jun 8 20:03:00 server ERROR: Permission denied for user
总结:
通过脚本标准化(规范)、场景化(实战)、自动化(任务)三位一体,实现运维效率提升70%+人工错误率降低90%。企业落地需结合自身环境调整参数,并遵循 “无人值守,稳定运行” 的终极目标。