name: Linux 生产环境 Shell 脚本 description: 当用户要求“创建bash脚本”、“自动化Linux任务”、“监控系统资源”、“备份文件”、“管理用户”或“编写生产shell脚本”时,应使用此技能。它提供用于系统管理的即用型Shell脚本模板。 metadata: author: zebbern version: “1.1”
Linux 生产环境 Shell 脚本
目的
为常见Linux系统管理任务提供生产级Shell脚本模板,包括备份、监控、用户管理、日志分析和自动化。这些脚本可作为安全操作和渗透测试环境的构建模块。
前提条件
所需环境
- Linux/Unix系统(bash shell)
- 任务的适当权限
- 安装所需实用程序(rsync、openssl等)
所需知识
- 基本bash脚本编写
- Linux文件系统结构
- 系统管理概念
输出和交付物
- 备份解决方案 - 自动化文件和数据库备份
- 监控脚本 - 资源使用跟踪
- 自动化工具 - 计划任务执行
- 安全脚本 - 密码管理、加密
核心工作流程
阶段1:文件备份脚本
基本目录备份
#!/bin/bash
backup_dir="/path/to/backup"
source_dir="/path/to/source"
# 创建源目录的时间戳备份
tar -czf "$backup_dir/backup_$(date +%Y%m%d_%H%M%S).tar.gz" "$source_dir"
echo "备份完成:backup_$(date +%Y%m%d_%H%M%S).tar.gz"
远程服务器备份
#!/bin/bash
source_dir="/path/to/source"
remote_server="user@remoteserver:/path/to/backup"
# 使用rsync将文件/目录备份到远程服务器
rsync -avz --progress "$source_dir" "$remote_server"
echo "文件已备份到远程服务器。"
备份轮换脚本
#!/bin/bash
backup_dir="/path/to/backups"
max_backups=5
# 如果备份超过最大数量,删除最旧的备份进行轮换
while [ $(ls -1 "$backup_dir" | wc -l) -gt "$max_backups" ]; do
oldest_backup=$(ls -1t "$backup_dir" | tail -n 1)
rm -r "$backup_dir/$oldest_backup"
echo "已删除旧备份:$oldest_backup"
done
echo "备份轮换完成。"
数据库备份脚本
#!/bin/bash
database_name="your_database"
db_user="username"
db_pass="password"
output_file="database_backup_$(date +%Y%m%d).sql"
# 使用mysqldump执行数据库备份
mysqldump -u "$db_user" -p"$db_pass" "$database_name" > "$output_file"
gzip "$output_file"
echo "数据库备份创建:$output_file.gz"
阶段2:系统监控脚本
CPU使用监控器
#!/bin/bash
threshold=90
# 监控CPU使用,如果超过阈值触发警报
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d. -f1)
if [ "$cpu_usage" -gt "$threshold" ]; then
echo "警报:检测到高CPU使用:$cpu_usage%"
# 添加通知逻辑(邮件、Slack等)
# mail -s "CPU警报" admin@example.com <<< "CPU使用:$cpu_usage%"
fi
磁盘空间监控器
#!/bin/bash
threshold=90
partition="/dev/sda1"
# 监控磁盘使用,如果超过阈值触发警报
disk_usage=$(df -h | grep "$partition" | awk '{print $5}' | cut -d% -f1)
if [ "$disk_usage" -gt "$threshold" ]; then
echo "警报:检测到高磁盘使用:$disk_usage%"
# 在此添加警报/通知逻辑
fi
CPU使用记录器
#!/bin/bash
output_file="cpu_usage_log.txt"
# 将当前CPU使用记录到带时间戳的文件中
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
cpu_usage=$(top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d. -f1)
echo "$timestamp - CPU使用:$cpu_usage%" >> "$output_file"
echo "CPU使用已记录。"
系统健康检查
#!/bin/bash
output_file="system_health_check.txt"
# 执行系统健康检查并将结果保存到文件
{
echo "系统健康检查 - $(date)"
echo "================================"
echo ""
echo "运行时间:"
uptime
echo ""
echo "负载平均:"
cat /proc/loadavg
echo ""
echo "内存使用:"
free -h
echo ""
echo "磁盘使用:"
df -h
echo ""
echo "顶级进程:"
ps aux --sort=-%cpu | head -10
} > "$output_file"
echo "系统健康检查已保存到 $output_file"
阶段3:用户管理脚本
用户账户创建
#!/bin/bash
username="newuser"
# 检查用户是否存在;如果不存在,创建新用户
if id "$username" &>/dev/null; then
echo "用户 $username 已存在。"
else
useradd -m -s /bin/bash "$username"
echo "用户 $username 已创建。"
# 交互式设置密码
passwd "$username"
fi
密码过期检查器
#!/bin/bash
output_file="password_expiry_report.txt"
# 检查使用bash shell的用户的密码过期情况
echo "密码过期报告 - $(date)" > "$output_file"
echo "=================================" >> "$output_file"
IFS=$'
'
for user in $(grep "/bin/bash" /etc/passwd | cut -d: -f1); do
password_expires=$(chage -l "$user" 2>/dev/null | grep "Password expires" | awk -F: '{print $2}')
echo "用户:$user - 密码过期:$password_expires" >> "$output_file"
done
unset IFS
echo "密码过期报告已保存到 $output_file"
阶段4:安全脚本
密码生成器
#!/bin/bash
length=${1:-16}
# 生成随机密码
password=$(openssl rand -base64 48 | tr -dc 'a-zA-Z0-9!@#$%^&*' | head -c"$length")
echo "生成的密码:$password"
文件加密脚本
#!/bin/bash
file="$1"
action="${2:-encrypt}"
if [ -z "$file" ]; then
echo "用法:$0 <文件> [encrypt|decrypt]"
exit 1
fi
if [ "$action" == "encrypt" ]; then
# 使用AES-256-CBC加密文件
openssl enc -aes-256-cbc -salt -pbkdf2 -in "$file" -out "$file.enc"
echo "文件已加密:$file.enc"
elif [ "$action" == "decrypt" ]; then
# 解密文件
output_file="${file%.enc}"
openssl enc -aes-256-cbc -d -pbkdf2 -in "$file" -out "$output_file"
echo "文件已解密:$output_file"
fi
阶段5:日志分析脚本
错误日志提取器
#!/bin/bash
logfile="${1:-/var/log/syslog}"
output_file="error_log_$(date +%Y%m%d).txt"
# 从日志文件中提取包含“ERROR”的行
grep -i "error\|fail\|critical" "$logfile" > "$output_file"
echo "错误日志已创建:$output_file"
echo "找到的总错误数:$(wc -l < "$output_file")"
Web服务器日志分析器
#!/bin/bash
log_file="${1:-/var/log/apache2/access.log}"
echo "Web服务器日志分析"
echo "========================"
echo ""
echo "前10个IP地址:"
awk '{print $1}' "$log_file" | sort | uniq -c | sort -rn | head -10
echo ""
echo "前10个请求URL:"
awk '{print $7}' "$log_file" | sort | uniq -c | sort -rn | head -10
echo ""
echo "HTTP状态码分布:"
awk '{print $9}' "$log_file" | sort | uniq -c | sort -rn
阶段6:网络脚本
网络连接检查器
#!/bin/bash
hosts=("8.8.8.8" "1.1.1.1" "google.com")
echo "网络连接检查"
echo "=========================="
for host in "${hosts[@]}"; do
if ping -c 1 -W 2 "$host" &>/dev/null; then
echo "[在线] $host 可达"
else
echo "[离线] $host 不可达"
fi
done
网站在线时间检查器
#!/bin/bash
websites=("https://google.com" "https://github.com")
log_file="uptime_log.txt"
echo "网站在线时间检查 - $(date)" >> "$log_file"
for website in "${websites[@]}"; do
if curl --output /dev/null --silent --head --fail --max-time 10 "$website"; then
echo "[在线] $website 可访问" | tee -a "$log_file"
else
echo "[离线] $website 不可访问" | tee -a "$log_file"
fi
done
网络接口信息
#!/bin/bash
interface="${1:-eth0}"
echo "网络接口信息:$interface"
echo "========================================="
ip addr show "$interface" 2>/dev/null || ifconfig "$interface" 2>/dev/null
echo ""
echo "路由表:"
ip route | grep "$interface"
阶段7:自动化脚本
自动化软件包安装
#!/bin/bash
packages=("vim" "htop" "curl" "wget" "git")
echo "安装软件包中..."
for package in "${packages[@]}"; do
if dpkg -l | grep -q "^ii $package"; then
echo "[跳过] $package 已安装"
else
sudo apt-get install -y "$package"
echo "[已安装] $package"
fi
done
echo "软件包安装完成。"
任务计划器(Cron设置)
#!/bin/bash
scheduled_task="/path/to/your_script.sh"
schedule_time="0 2 * * *" # 每天凌晨2点运行
# 将任务添加到crontab
(crontab -l 2>/dev/null; echo "$schedule_time $scheduled_task") | crontab -
echo "任务已计划:$schedule_time $scheduled_task"
服务重启脚本
#!/bin/bash
service_name="${1:-apache2}"
# 重启指定服务
if systemctl is-active --quiet "$service_name"; then
echo "正在重启 $service_name..."
sudo systemctl restart "$service_name"
echo "服务 $service_name 已重启。"
else
echo "服务 $service_name 未运行。正在启动..."
sudo systemctl start "$service_name"
echo "服务 $service_name 已启动。"
fi
阶段8:文件操作
目录同步
#!/bin/bash
source_dir="/path/to/source"
destination_dir="/path/to/destination"
# 使用rsync同步目录
rsync -avz --delete "$source_dir/" "$destination_dir/"
echo "目录已成功同步。"
数据清理脚本
#!/bin/bash
directory="${1:-/tmp}"
days="${2:-7}"
echo "清理 $directory 中超过 $days 天的文件"
# 删除超过指定天数的文件
find "$directory" -type f -mtime +"$days" -exec rm -v {} \;
echo "清理完成。"
文件夹大小检查器
#!/bin/bash
folder_path="${1:-.}"
echo "文件夹大小分析:$folder_path"
echo "===================================="
# 按大小排序显示子目录大小
du -sh "$folder_path"/* 2>/dev/null | sort -rh | head -20
echo ""
echo "总大小:"
du -sh "$folder_path"
阶段9:系统信息
系统信息收集器
#!/bin/bash
output_file="system_info_$(hostname)_$(date +%Y%m%d).txt"
{
echo "系统信息报告"
echo "生成时间:$(date)"
echo "========================="
echo ""
echo "主机名:$(hostname)"
echo "操作系统:$(uname -a)"
echo ""
echo "CPU信息:"
lscpu | grep -E "Model name|CPU\(s\)|Thread"
echo ""
echo "内存:"
free -h
echo ""
echo "磁盘空间:"
df -h
echo ""
echo "网络接口:"
ip -br addr
echo ""
echo "登录用户:"
who
} > "$output_file"
echo "系统信息已保存到 $output_file"
阶段10:Git和开发
Git仓库更新器
#!/bin/bash
git_repos=("/path/to/repo1" "/path/to/repo2")
for repo in "${git_repos[@]}"; do
if [ -d "$repo/.git" ]; then
echo "正在更新仓库:$repo"
cd "$repo"
git fetch --all
git pull origin "$(git branch --show-current)"
echo "已更新:$repo"
else
echo "非Git仓库:$repo"
fi
done
echo "所有仓库已更新。"
远程脚本执行
#!/bin/bash
remote_server="${1:-user@remote-server}"
remote_script="${2:-/path/to/remote/script.sh}"
# 通过SSH在远程服务器上执行脚本
ssh "$remote_server" "bash -s" < "$remote_script"
echo "远程脚本已在 $remote_server 上执行"
快速参考
常见脚本模式
| 模式 | 目的 |
|---|---|
#!/bin/bash |
bash的shebang |
$(date +%Y%m%d) |
日期格式化 |
$((expression)) |
算术运算 |
${var:-default} |
默认值 |
"$@" |
所有参数 |
有用命令
| 命令 | 目的 |
|---|---|
chmod +x script.sh |
使可执行 |
./script.sh |
运行脚本 |
nohup ./script.sh & |
在后台运行 |
crontab -e |
编辑cron作业 |
source script.sh |
在当前shell中运行 |
Cron格式
分钟(0-59) 小时(0-23) 日(1-31) 月(1-12) 周几(0-7, 0/7=周日)
约束和限制
- 始终在非生产环境先测试脚本
- 使用绝对路径以避免错误
- 引用变量以正确处理空格
- 许多脚本需要root/sudo权限
- 使用
bash -x script.sh进行调试