小白成长之路-Linux Shell脚本练习

发布于:2025-06-09 ⋅ 阅读:(15) ⋅ 点赞:(0)

题目一:系统详细信息收集与报告脚本

编写一个名为 system_info_gather.sh 的脚本,实现以下功能:

  1. 收集系统的以下详细信息:

- 操作系统的发行版名称和版本号。

- CPU 的型号、核心数量以及当前的频率。

- 内存的总量以及当前的使用量。

- 硬盘的分区信息,包括每个分区的大小、已使用空间和文件系统类型。

- 系统的启动时间以及当前的运行时长。

  1. 将这些信息整理成一个清晰易读的格式,并输出到一个名为 system_report.txt 的文件中。同时,在脚本执行过程中,每收集到一项信息,就在终端上实时显示一个简短的提示信息,说明正在收集该项信息。
#!/bin/bash

# 创建报告文件
REPORT_FILE="system_report.txt"
echo "正在生成系统报告..."
echo > "${REPORT_FILE}"  # 清空文件

# 显示进度信息
progress() {
    echo "正在收集$1信息中..."

}

#追加到文件中
addText() {
    if [ $? -eq 0 ]; then  
        tee -a "$REPORT_FILE"  
    else
        echo "获取信息失败" | tee -a "$REPORT_FILE"  
    fi
}


# 操作系统信息
progress "操作系统"
os_info=$(grep -E '^NAME=|^VERSION_ID=' /etc/os-release 2>/dev/null | sort -r)
name=$(echo "$os_info" | grep "^NAME=" | head -n1 | cut -d'"' -f2)
version=$(echo "$os_info" | grep "^VERSION_ID=" | head -n1 | cut -d'"' -f2)
echo "系统名称: $name, 版本: $version" | addText

# CPU信息
progress "CPU信息"
cpuType=$(grep "model name" /proc/cpuinfo | uniq | cut -d":" -f2 | xargs)
cpuCoreNum=$(grep -c "^processor" /proc/cpuinfo)
cpuFrequency=$(grep "cpu MHz" /proc/cpuinfo | uniq | cut -d":" -f2 | xargs | awk '{printf "%.0f MHz", $1}')
{
    echo ""
    echo "======= CPU 信息 ======="
    echo "型号:      ${cpuType}"
    echo "核心数:    ${cpuCoreNum}"
    echo "频率:      ${cpuFrequency}"
} | addText

# 内存信息
progress "内存信息"
memorySum=$(grep MemTotal /proc/meminfo | awk '{print $2}')
memoryAble=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
memoryUsed=$(( memorySum - memoryAble ))
# 转换为GB (保留2位小数)
memorySumGB=$(echo "scale=2; ${memorySum}/1024/1024" | bc)
memoryUsedGB=$(echo "scale=2; ${memoryUsed}/1024/1024" | bc)
{
    echo ""
    echo "======= 内存信息 ======="
    printf "总内存:   %.2f GB (%d kB)\n" "${memorySumGB}" "${memorySum}"
    printf "已使用:   %.2f GB (%d kB)\n" "${memoryUsedGB}" "${memoryUsed}"
    printf "可用内存: %.2f GB (%d kB)\n" "$(echo "scale=2; ${memoryAble}/1024/1024" | bc)" "${memoryAble}"
} | addText

# 磁盘信息
progress "磁盘分区"
disk_info=$(df -Th)
{
    echo ""
    echo "======= 磁盘分区信息 ======="
    echo "${disk_info}"
} | addText

# 系统启动信息
progress "系统启动"
start_time=$(date -d "now - $(awk '{printf "%.0f", $1}' /proc/uptime) seconds" +"%Y-%m-%d %H:%M:%S")
up_seconds=$(awk '{printf "%.0f", $1}' /proc/uptime)
days=$(( up_seconds / 86400 ))
hours=$(( (up_seconds % 86400) / 3600 ))
minutes=$(( (up_seconds % 3600) / 60 ))
{
    echo ""
    echo "======= 系统启动信息 ======="
    echo "启动时间: ${start_time}"
    echo "运行时长: ${days}${hours}小时 ${minutes}分钟"
    echo ""
} | addText

# 完成提示
echo ""
echo "系统信息收集完成!报告已保存至: ${REPORT_FILE}"

验证:

cat system_report.txt 

系统名称: Rocky Linux, 版本: 8.10

======= CPU 信息 =======
型号:      Intel(R) Core(TM) i5-10200H CPU @ 2.40GHz
核心数:    2
频率:      2400 MHz

======= 内存信息 =======
总内存:   3.54 GB (3720852 kB)
已使用:   1.27 GB (1335324 kB)
可用内存: 2.27 GB (2385528 kB)

======= 磁盘分区信息 =======
文件系统            类型      容量  已用  可用 已用% 挂载点
devtmpfs            devtmpfs  1.8G     0  1.8G    0% /dev
tmpfs               tmpfs     1.8G     0  1.8G    0% /dev/shm
tmpfs               tmpfs     1.8G   33M  1.8G    2% /run
tmpfs               tmpfs     1.8G     0  1.8G    0% /sys/fs/cgroup
/dev/mapper/rl-root xfs        17G  6.2G   11G   36% /
/dev/sda1           xfs      1014M  275M  740M   28% /boot
tmpfs               tmpfs     364M   20K  364M    1% /run/user/0

======= 系统启动信息 =======
启动时间: 2025-06-07 18:31:00
运行时长: 06小时 43分钟

题目二:网络配置备份与恢复脚本

创建一个名为 network_config_backup.shnetwork_config_restore.sh 的配对脚本:

  1. network_config_backup.sh 脚本的功能:

- 备份当前系统的网络配置文件,包括但不限于 /etc/network/interfaces(或者适用于你所在系统的网络配置文件)、DHCP 配置文件(如果有)以及任何与网络相关的自定义脚本或配置片段。

- 将这些备份文件压缩成一个以当前日期命名的归档文件,存储在 /backup/network_config/ 目录下(如果该目录不存在,则先创建它)。

#!/bin/bash

# 设置备份目录
BACKUP_DIR="/backup/network_config"

# 获取当前日期,格式为 YYYY-MM-DD
DATE=$(date +%F)

# 创建备份目录(如果不存在)
if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
    if [ $? -ne 0 ]; then
        echo "创建备份目录失败,请检查权限或磁盘空间。"
        exit 1
    fi
fi

# 定义要备份的网络配置文件
declare -a CONFIG_FILES=(
    "/etc/network/interfaces"
    "/etc/dhcp/dhcpd.conf"
    "/etc/network/interfaces.d/"
    "/etc/netplan/"
    "/etc/network/if-up.d/"
    "/etc/network/if-down.d/"
)

# 定义要备份的自定义脚本或配置片段
declare -a CUSTOM_FILES=(
    "/etc/my_custom_network_script.sh"
    "/etc/my_custom_network_config.conf"
)

# 创建临时备份目录
TEMP_DIR=$(mktemp -d)
if [ $? -ne 0 ]; then
    echo "创建临时目录失败。"
    exit 1
fi

# 复制网络配置文件到临时目录
for file in "${CONFIG_FILES[@]}"; do
    if [ -e "$file" ]; then
        cp -r "$file" "$TEMP_DIR"
        if [ $? -ne 0 ]; then
            echo "复制文件 $file 失败。"
            exit 1
        fi
    fi
done

# 复制自定义脚本或配置片段到临时目录
for file in "${CUSTOM_FILES[@]}"; do
    if [ -e "$file" ]; then
        cp -r "$file" "$TEMP_DIR"
        if [ $? -ne 0 ]; then
            echo "复制文件 $file 失败。"
            exit 1
        fi
    fi
done

# 压缩临时目录为归档文件
ARCHIVE_FILE="$BACKUP_DIR/network_config_backup_$DATE.tar.gz"
tar -czf "$ARCHIVE_FILE" -C "$TEMP_DIR" .
if [ $? -ne 0 ]; then
    echo "压缩备份文件失败。"
    exit 1
fi

# 清理临时目录
rm -rf "$TEMP_DIR"

# 输出备份成功信息
echo "网络配置文件备份成功,备份文件存储在:$ARCHIVE_FILE"

在这里插入图片描述

  1. network_config_restore.sh 脚本的功能:

- 接受一个归档文件作为参数(假设是之前备份的网络配置归档文件)。

- 解压该归档文件,并将其中的配置文件恢复到原位置,覆盖现有配置(在恢复之前,最好有一个确认提示,以防止误操作)。

#!/bin/bash
  
# 检查是否提供了归档文件参数
if [ $# -eq 0 ]; then
    echo "用法: $0 <归档文件路径>"
    exit 1
fi

ARCHIVE_FILE="$1"

# 检查归档文件是否存在
if [ ! -f "$ARCHIVE_FILE" ]; then
    echo "错误:归档文件 $ARCHIVE_FILE 不存在。"
    exit 1
fi

# 提示用户是否要解压归档文件
read -p "是否要解压该归档文件?(y表示是,其他字符表示否): " doing

# 判断用户输入
if [ "$doing" == "y" ]; then
    # 提示用户输入解压路径
    read -p "输入要解压的目录: " path

    # 检查路径是否为空
     if [ -z "$path" ]; then
        echo "错误:未指定解压目录。"
        exit 1
    fi

    # 创建目录(如果不存在)
    if [ ! -d "$path" ]; then
        echo "创建目录: $path"
        mkdir -p "$path"
        if [ $? -ne 0 ]; then
            echo "错误:无法创建目录 $path"
            exit 1
        fi
    fi

    echo "正在解压 $ARCHIVE_FILE$path ..."

    # 执行解压操作
    tar -xzvf "$ARCHIVE_FILE" -C "$path"
 
    if [ $? -eq 0 ]; then
        echo "解压归档文件成功。"
        echo "解压内容:"
        ls -l "$path"
    else
       echo "解压归档文件失败。"
        exit 1
    fi
else
    echo "操作已取消。"
    exit 0
fi

题目三:用户权限管理脚本

编写一个名为 user_permission_adjust.sh 的脚本,完成以下任务:

  1. 接受一个用户列表文件(每行一个用户名)作为参数。
  2. 对于列表中的每个用户:

- 检查该用户是否存在,如果不存在,则在终端输出提示信息并跳过该用户。

- 如果用户存在,检查其是否属于一个名为 special_group 的用户组(假设这个组与某些特殊权限相关),如果不属于,则将其添加到该组中。

- 检查该用户对一个指定目录(例如 /data/shared/)的访问权限,如果没有读取和写入权限,则赋予相应权限(确保使用最安全的方式设置权限,例如只赋予必要的最小权限)。

#!/bin/bash

# 定义特殊组和目标目录
GROUP="special_group"
DIR="/data/shared"
USERLIST="$1"

# 检查目录是否存在
if [ ! -d "$DIR" ]; then
    echo "目录不存在,正在创建..."
    mkdir -p "$DIR"
    if [ $? -ne 0 ]; then
        echo "创建目录失败,请检查权限。"
        exit 1
    fi
fi

# 检查特殊组是否存在,如果不存在则创建
if ! getent group "$GROUP" &>/dev/null; then
    echo "组 $GROUP 不存在,正在创建..."
    groupadd "$GROUP"
    if [ $? -ne 0 ]; then
        echo "创建组 $GROUP 失败。"
        exit 1
    fi
fi

# 检查文件中的用户
for i in $(cat "$USERLIST"); do
    # 检查用户是否存在
    if ! id "$i" &>/dev/null; then
        echo "用户 $i 不存在,跳过。"
        continue
    fi

    # 检查用户是否属于 special_group
    if ! groups "$i" | grep -q "\b$GROUP\b"; then
        echo "用户 $i 不属于 $GROUP,正在添加..."
        usermod -aG "$GROUP" "$i"
        if [ $? -ne 0 ]; then
            echo "将用户 $i 添加到 $GROUP 失败。"
            continue
        fi
    fi

    # 检查用户权限
    if [ ! -r "$DIR" ] || [ ! -w "$DIR" ]; then
        echo "用户 $i$DIR 没有读取或写入权限,正在设置权限..."
        setfacl -m u:"$i":rwX "$DIR"
        if [ $? -ne 0 ]; then
            echo "为用户 $i 设置权限失败。"
            continue
        fi
    fi

    echo "用户 $i 的权限已调整完成。"
done

验证:
在这里插入图片描述

在这里插入图片描述

题目四:服务状态监控与自动重启脚本

创建一个名为 service_monitor.sh 的脚本,实现以下功能:

  1. 接受一个服务名称列表文件(每行一个服务名称)作为参数。
  2. 对于列表中的每个服务:

- 检查该服务的运行状态。如果服务正在运行,则记录其运行状态信息(例如进程 ID、占用的内存等,如果可以获取的话)到一个日志文件 /var/log/service_monitor.log 中。

- 如果服务未运行,则尝试自动启动它,并在日志文件中记录启动的时间和结果(成功或失败)。

  1. 每隔一段时间(例如 10 分钟)重复上述检查和操作,持续运行。
#!/bin/bash

# 检查是否提供了服务列表文件作为参数
if [ $# -ne 1 ]; then
    echo "用法: $0 <服务名称列表文件>"
    exit 1
fi

# 获取服务列表文件路径
SERVICE_LIST_FILE=$1

# 检查服务列表文件是否存在
if [ ! -f "$SERVICE_LIST_FILE" ]; then
    echo "错误:服务列表文件 $SERVICE_LIST_FILE 不存在。"
    exit 1
fi

# 定义日志文件路径
LOG_FILE="/var/log/service_monitor.log"

# 检查日志文件是否存在,如果不存在则创建
if [ ! -f "$LOG_FILE" ]; then
    touch "$LOG_FILE"
    if [ $? -ne 0 ]; then
        echo "创建日志文件失败,请检查权限。"
        exit 1
    fi
fi

# 定义检查间隔时间(秒)
INTERVAL=600  # 10 分钟

echo "脚本开始运行..." >> "$LOG_FILE"

# 主循环
while true; do
    # 读取服务列表文件,逐行处理每个服务
    for service in $(cat "$SERVICE_LIST_FILE"); do
        # 检查服务是否正在运行
        if systemctl is-active --quiet "$service"; then
            # 服务正在运行,记录运行状态信息
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 服务 $service 正在运行。" >> "$LOG_FILE"
            # 获取进程 ID 和占用的内存
            pid=$(pgrep -o "$service")
            if [ -n "$pid" ]; then
                mem=$(ps -o rss= -p "$pid")
                echo "  进程 ID: $pid, 占用内存: $mem KB" >> "$LOG_FILE"
            fi
        else
            # 服务未运行,尝试自动启动
            echo "$(date '+%Y-%m-%d %H:%M:%S') - 服务 $service 未运行,正在尝试启动..." >> "$LOG_FILE"
            systemctl start "$service"
            if systemctl is-active --quiet "$service"; then
                echo "  服务 $service 启动成功。" >> "$LOG_FILE"
            else
                echo "  服务 $service 启动失败。" >> "$LOG_FILE"
            fi
        fi
    done

    # 等待指定的时间间隔
    sleep "$INTERVAL"
done

验证
使用bash -x检查没有报错

bash -x service_monitor.sh servicelist.txt
+ '[' 1 -ne 1 ']'
+ SERVICE_LIST_FILE=servicelist.txt
+ '[' '!' -f servicelist.txt ']'
+ LOG_FILE=/var/log/service_monitor.log
+ '[' '!' -f /var/log/service_monitor.log ']'
+ INTERVAL=600
+ true
+ IFS=
+ read -r service
+ systemctl is-active --quiet sshd
++ date '+%Y-%m-%d %H:%M:%S'
+ echo '2025-06-08 06:24:05 - 服务 sshd 正在运行。'
++ pgrep -o sshd
+ pid=1040
+ '[' -n 1040 ']'
++ ps -o rss= -p 1040
+ mem=' 6980'
+ echo '  进程 ID: 1040, 占用内存:  6980 KB'
+ IFS=
+ read -r service
+ systemctl is-active --quiet nginx
++ date '+%Y-%m-%d %H:%M:%S'
+ echo '2025-06-08 06:24:05 - 服务 nginx 正在运行。'
++ pgrep -o nginx
+ pid=295521
+ '[' -n 295521 ']'
++ ps -o rss= -p 295521
+ mem=' 2188'
+ echo '  进程 ID: 295521, 占用内存:  2188 KB'
+ IFS=
+ read -r service
+ sleep 600

为了方便测试,我把时间改为10秒
在这里插入图片描述

题目五:系统日志分析与报告脚本

编写一个名为 log_analyzer.sh 的脚本,完成以下任务:

  1. 分析系统的一个关键应用程序的日志文件(假设日志文件路径为 /var/log/app.log),找出在过去一周内出现次数最多的前 5 种错误类型(假设错误类型可以通过日志中的特定关键字或格式来区分)。
  2. 对于每种错误类型,统计其出现的次数,并生成一个详细的报告,包括错误类型描述、出现次数以及在日志文件中出现的相关示例行(至少列出 3 个示例行)。
  3. 将这个报告输出到一个名为 log_analysis_report.txt 的文件中,并且在报告的开头包含本次分析的时间范围和日志文件的基本信息(例如日志文件大小、包含的日志行数等)。
#!/bin/bash

# 定义日志文件路径
LOG_FILE="/var/log/app.log"
REPORT_FILE="log_analysis_report.txt"
DATE_RANGE=$(date -d "7 days ago" +%Y-%m-%d)

# 检查日志文件是否存在,如果不存在则创建
if [ ! -f "$LOG_FILE" ]; then
    echo "日志文件 $LOG_FILE 不存在,正在创建空日志文件..."
    touch "$LOG_FILE"
    if [ $? -ne 0 ]; then
        echo "创建日志文件失败,请检查权限。"
        exit 1
    fi
    echo "日志文件已创建。"
fi

# 获取日志文件的基本信息
LOG_SIZE=$(du -sh "$LOG_FILE" | cut -f1)
LOG_LINES=$(wc -l < "$LOG_FILE")

# 写入报告文件的头部信息
echo "日志分析报告" > "$REPORT_FILE"
echo "分析时间范围:过去一周(从 $DATE_RANGE$(date +%Y-%m-%d))" >> "$REPORT_FILE"
echo "日志文件路径:$LOG_FILE" >> "$REPORT_FILE"
echo "日志文件大小:$LOG_SIZE" >> "$REPORT_FILE"
echo "日志行数:$LOG_LINES" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

# 提取过去一周的日志内容
TEMP_LOG=$(mktemp)
grep -E "$(date -d "$DATE_RANGE" +%Y-%m-%d)" "$LOG_FILE" > "$TEMP_LOG"

# 分析错误类型
ERROR_TYPES=$(grep -oE 'ERROR: [A-Za-z0-9_ ]+' "$TEMP_LOG" | sort | uniq -c | sort -nr | head -5)

# 写入错误类型分析结果
echo "错误类型分析:" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
while IFS= read -r line; do
    COUNT=$(echo "$line" | awk '{print $1}')
    ERROR_TYPE=$(echo "$line" | awk '{$1=""; print $0}' | xargs)
    echo "错误类型:$ERROR_TYPE" >> "$REPORT_FILE"
    echo "出现次数:$COUNT" >> "$REPORT_FILE"
    echo "示例行:" >> "$REPORT_FILE"
    grep "$ERROR_TYPE" "$TEMP_LOG" | head -3 >> "$REPORT_FILE"
    echo "" >> "$REPORT_FILE"
done <<< "$ERROR_TYPES"

# 清理临时文件
rm "$TEMP_LOG"

echo "报告已生成:$REPORT_FILE"

网站公告

今日签到

点亮在社区的每一天
去签到