1. Shell 脚本入门基础
1.1 创建第一个 Shell 脚本
#!/bin/bash
# 创建脚本目录
mkdir -p ~/shell_scripts
cd ~/shell_scripts
# 创建第一个脚本文件
cat > hello_world.sh << 'EOF'
#!/bin/bash
# 这是一个简单的 Hello World 脚本
echo "===================================="
echo " 我的第一个 Shell 脚本"
echo "===================================="
# 显示当前用户
echo "当前用户: $(whoami)"
# 显示当前日期时间
echo "当前时间: $(date)"
# 显示系统信息
echo "操作系统: $(uname -s)"
echo "内核版本: $(uname -r)"
# 问候用户
read -p "请输入你的名字: " username
echo "你好, $username! 欢迎来到 Shell 编程世界!"
# 退出脚本
echo "脚本执行完成!"
exit 0
EOF
# 给脚本添加执行权限
chmod +x hello_world.sh
# 运行脚本
./hello_world.sh
1.2 变量和数据类型
#!/bin/bash
# 创建变量学习脚本
cat > variables_demo.sh << 'EOF'
#!/bin/bash
echo "============== 变量使用演示 ==============="
# 字符串变量
name="Shell 程序员"
company="Tech Corp"
greeting="欢迎学习 Shell 编程!"
# 数字变量
age=25
score=98.5
count=10
# 数组变量
fruits=("苹果" "香蕉" "橙子" "葡萄")
colors=("红色" "绿色" "蓝色" "黄色")
# 环境变量
echo "当前用户: $USER"
echo "家目录: $HOME"
echo "当前路径: $PWD"
echo "Shell 类型: $SHELL"
echo ""
echo "============== 自定义变量 ==============="
echo "姓名: $name"
echo "公司: $company"
echo "问候: $greeting"
echo "年龄: $age"
echo "分数: $score"
echo ""
echo "============== 数组操作 ==============="
echo "第一个水果: ${fruits[0]}"
echo "所有水果: ${fruits[@]}"
echo "水果数量: ${#fruits[@]}"
echo ""
echo "============== 变量操作 ==============="
# 字符串长度
echo "姓名长度: ${#name}"
# 字符串切片
echo "姓名前5个字符: ${name:0:5}"
# 默认值
unset undefined_var
echo "未定义变量: ${undefined_var:-默认值}"
EOF
chmod +x variables_demo.sh
./variables_demo.sh
1.3 条件判断和循环
#!/bin/bash
# 创建条件循环脚本
cat > control_structures.sh << 'EOF'
#!/bin/bash
echo "============== 条件判断演示 ==============="
# 简单的 if 语句
read -p "请输入一个数字: " number
if [ $number -gt 100 ]; then
echo "数字 $number 大于 100"
elif [ $number -eq 100 ]; then
echo "数字 $number 等于 100"
else
echo "数字 $number 小于 100"
fi
echo ""
echo "============== 文件检查 ==============="
filename="test.txt"
if [ -f "$filename" ]; then
echo "文件 $filename 存在"
else
echo "文件 $filename 不存在,正在创建..."
touch "$filename"
echo "创建完成!"
fi
echo ""
echo "============== for 循环演示 ==============="
echo "数字循环:"
for i in {1..5}; do
echo "循环次数: $i"
done
echo ""
echo "文件循环:"
for file in *; do
if [ -f "$file" ]; then
echo "找到文件: $file"
fi
done
echo ""
echo "============== while 循环演示 ==============="
counter=1
while [ $counter -le 3 ]; do
echo "while 循环计数: $counter"
((counter++))
done
echo ""
echo "============== case 语句演示 ==============="
read -p "请输入一个命令 (start|stop|restart|status): " command
case $command in
start)
echo "启动服务..."
;;
stop)
echo "停止服务..."
;;
restart)
echo "重启服务..."
;;
status)
echo "服务状态: 运行中"
;;
*)
echo "未知命令: $command"
echo "可用命令: start, stop, restart, status"
;;
esac
EOF
chmod +x control_structures.sh
./control_structures.sh
2. Shell 脚本放弃阶段(常见陷阱)
2.1 语法陷阱和调试技巧
#!/bin/bash
# 创建调试脚本
cat > debugging_demo.sh << 'EOF'
#!/bin/bash
# 启用调试模式
set -e # 遇到错误立即退出
set -u # 使用未定义变量时报错
set -o pipefail # 管道中任何一个命令失败则整个管道失败
# 调试函数
debug_info() {
echo "=== 调试信息 ==="
echo "当前行号: $LINENO"
echo "函数名: ${FUNCNAME[1]}"
echo "脚本名: $0"
echo "参数数量: $#"
echo "所有参数: $@"
echo "================"
}
echo "============== 常见陷阱演示 ==============="
# 陷阱1:未引用的变量
echo ""
echo "1. 变量引用问题:"
filename="my file with spaces.txt"
echo "创建带空格的文件..."
touch "$filename" # 正确:使用引号
# touch $filename # 错误:不适用引号会导致多个文件
# 陷阱2:错误处理
echo ""
echo "2. 错误处理:"
handle_error() {
echo "发生错误!退出状态: $?"
echo "错误发生在: ${BASH_SOURCE[1]} 第 ${BASH_LINENO[0]} 行"
}
# 设置错误处理
trap handle_error ERR
# 故意制造错误
cd /nonexistent_directory || {
echo "目录不存在,但脚本继续执行"
}
# 陷阱3:管道错误
echo ""
echo "3. 管道错误处理:"
echo "测试管道错误..."
ls /nonexistent | head -1 || echo "管道命令失败"
# 陷阱4:算术运算
echo ""
echo "4. 算术运算:"
num1=10
num2=3
# 错误的算术运算
# result=$num1 / $num2 # 这会失败
# 正确的算术运算
result=$((num1 / num2))
echo "算术结果: $num1 / $num2 = $result"
# 使用 expr
result2=$(expr $num1 / $num2)
echo "expr 结果: $result2"
# 使用 bc 进行浮点运算
result3=$(echo "scale=2; $num1 / $num2" | bc)
echo "浮点结果: $result3"
debug_info
EOF
chmod +x debugging_demo.sh
./debugging_demo.sh
2.2 输入验证和错误处理
#!/bin/bash
# 创建输入验证脚本
cat > input_validation.sh << 'EOF'
#!/bin/bash
# 严格的错误处理
set -euo pipefail
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 日志函数
log_error() {
echo -e "${RED}[错误] $1${NC}" >&2
}
log_warning() {
echo -e "${YELLOW}[警告] $1${NC}" >&2
}
log_success() {
echo -e "${GREEN}[成功] $1${NC}"
}
# 输入验证函数
validate_number() {
local input=$1
if ! [[ $input =~ ^[0-9]+$ ]]; then
log_error "输入 '$input' 不是有效的数字"
return 1
fi
return 0
}
validate_email() {
local email=$1
local regex="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
if ! [[ $email =~ $regex ]]; then
log_error "邮箱格式无效: $email"
return 1
fi
return 0
}
validate_file() {
local file=$1
if [ ! -f "$file" ]; then
log_error "文件不存在: $file"
return 1
fi
return 0
}
echo "============== 输入验证演示 ==============="
# 数字验证演示
echo ""
echo "1. 数字验证:"
while true; do
read -p "请输入年龄 (0-120): " age
if validate_number "$age" && [ "$age" -ge 0 ] && [ "$age" -le 120 ]; then
log_success "年龄验证通过: $age"
break
else
log_error "年龄必须在 0-120 之间"
fi
done
# 邮箱验证演示
echo ""
echo "2. 邮箱验证:"
while true; do
read -p "请输入邮箱地址: " email
if validate_email "$email"; then
log_success "邮箱验证通过: $email"
break
fi
done
# 文件操作演示
echo ""
echo "3. 文件操作验证:"
read -p "请输入要检查的文件名: " filename
if validate_file "$filename"; then
file_size=$(wc -c < "$filename")
line_count=$(wc -l < "$filename")
log_success "文件信息:"
echo " 文件名: $filename"
echo " 文件大小: $file_size 字节"
echo " 行数: $line_count"
else
log_warning "文件不存在,跳过文件检查"
fi
# 菜单选择验证
echo ""
echo "4. 菜单选择验证:"
show_menu() {
echo "请选择操作:"
echo "1) 显示系统信息"
echo "2) 显示磁盘使用"
echo "3) 显示内存信息"
echo "4) 退出"
}
while true; do
show_menu
read -p "请输入选择 (1-4): " choice
case $choice in
1)
echo "=== 系统信息 ==="
uname -a
;;
2)
echo "=== 磁盘使用 ==="
df -h
;;
3)
echo "=== 内存信息 ==="
free -h
;;
4)
log_success "再见!"
exit 0
;;
*)
log_error "无效选择: $choice,请输入 1-4"
;;
esac
echo ""
done
EOF
chmod +x input_validation.sh
./input_validation.sh
2.3 高级调试和错误追踪
graph TD
A[脚本开始] --> B[设置调试选项]
B --> C[定义错误处理函数]
C --> D[执行主要逻辑]
D --> E{执行成功?}
E -->|是| F[记录成功日志]
E -->|否| G[调用错误处理]
G --> H[记录错误信息]
H --> I[清理临时文件]
I --> J[发送错误通知]
J --> K[优雅退出]
F --> L[脚本完成]
style A fill:#2E8B57,color:white
style B fill:#4169E1,color:white
style C fill:#4169E1,color:white
style D fill:#4682B4,color:white
style F fill:#32CD32,color:white
style G fill:#FF6347,color:white
style H fill:#DC143C,color:white
style I fill:#FF4500,color:white
style J fill:#B22222,color:white
style K fill:#8B0000,color:white
style L fill:#2E8B57,color:white
#!/bin/bash
# 创建高级调试脚本
cat > advanced_debugging.sh << 'EOF'
#!/bin/bash
# 严格的执行模式
set -eEuo pipefail
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# 日志文件
LOG_FILE="script_debug.log"
exec > >(tee -a "$LOG_FILE")
exec 2>&1
# 信号处理
cleanup() {
echo -e "${YELLOW}[清理] 正在清理临时文件...${NC}"
rm -rf "${TEMP_DIR:-/tmp/nothing}"
echo -e "${GREEN}[清理] 清理完成${NC}"
}
trap cleanup EXIT
trap 'echo -e "${RED}[信号] 收到中断信号${NC}"; exit 1' INT TERM
# 错误处理函数
error_handler() {
local exit_code=$?
local line_no=$1
local command=$2
echo -e "${RED}========================================${NC}"
echo -e "${RED}[错误追踪] 脚本执行失败!${NC}"
echo -e "${RED}========================================${NC}"
echo -e "${YELLOW}位置: ${BASH_SOURCE[1]} 第 $line_no 行${NC}"
echo -e "${YELLOW}命令: $command${NC}"
echo -e "${YELLOW}退出码: $exit_code${NC}"
echo -e "${YELLOW}调用栈:${NC}"
# 显示调用栈
local frame=0
while caller $frame; do
((frame++))
done | tac
echo -e "${RED}========================================${NC}"
exit $exit_code
}
trap 'error_handler ${LINENO} "$BASH_COMMAND"' ERR
# 创建临时目录
TEMP_DIR=$(mktemp -d)
echo -e "${GREEN}[初始化] 临时目录: $TEMP_DIR${NC}"
# 调试信息函数
debug() {
echo -e "${CYAN}[调试] $1${NC}"
}
info() {
echo -e "${BLUE}[信息] $1${NC}"
}
warn() {
echo -e "${YELLOW}[警告] $1${NC}"
}
success() {
echo -e "${GREEN}[成功] $1${NC}"
}
# 复杂的业务逻辑函数
complex_operation() {
local input=$1
debug "开始复杂操作,输入: $input"
# 模拟一些操作
local temp_file="$TEMP_DIR/temp_$$.dat"
echo "处理数据..." > "$temp_file"
# 模拟随机错误
local random=$((RANDOM % 10))
if [ $random -lt 2 ]; then
warn "模拟随机错误发生"
return 1
fi
# 处理数据
for i in {1..3}; do
debug "处理阶段 $i"
sleep 0.5
echo "阶段 $i 完成" >> "$temp_file"
done
success "复杂操作完成"
return 0
}
# 主函数
main() {
info "脚本开始执行"
info "PID: $$"
info "开始时间: $(date)"
# 创建一些测试文件
debug "创建测试文件..."
for i in {1..5}; do
echo "这是测试文件 $i 的内容" > "$TEMP_DIR/test$i.txt"
done
# 执行复杂操作
info "执行复杂操作..."
if complex_operation "测试数据"; then
success "所有操作成功完成"
else
warn "部分操作失败,但脚本继续执行"
fi
# 文件操作演示
info "执行文件操作..."
local total_size=0
for file in "$TEMP_DIR"/*.txt; do
if [ -f "$file" ]; then
local size=$(wc -c < "$file")
total_size=$((total_size + size))
debug "文件: $(basename "$file") - 大小: ${size}字节"
fi
done
info "总文件大小: ${total_size}字节"
# 性能测试
info "开始性能测试..."
local start_time=$(date +%s.%N)
# 模拟耗时操作
for i in {1..1000}; do
echo "性能测试 $i" > /dev/null
done
local end_time=$(date +%s.%N)
local duration=$(echo "$end_time - $start_time" | bc)
info "性能测试完成,耗时: ${duration}秒"
success "脚本执行完成"
info "结束时间: $(date)"
}
# 运行主函数
main "$@"
EOF
chmod +x advanced_debugging.sh
./advanced_debugging.sh
3. Shell 脚本装逼阶段(高级技巧)
3.1 函数库和模块化编程
#!/bin/bash
# 创建函数库
cat > shell_library.sh << 'EOF'
#!/bin/bash
# Shell 脚本函数库
# 提供常用的工具函数
# 颜色定义
readonly COLOR_RED='\033[0;31m'
readonly COLOR_GREEN='\033[0;32m'
readonly COLOR_YELLOW='\033[1;33m'
readonly COLOR_BLUE='\033[0;34m'
readonly COLOR_MAGENTA='\033[0;35m'
readonly COLOR_CYAN='\033[0;36m'
readonly COLOR_RESET='\033[0m'
# 日志级别
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
# 配置
LOG_LEVEL=${LOG_LEVEL:-1} # 默认 INFO 级别
# 日志函数
log() {
local level=$1
local message=$2
local color=$3
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
if [ $level -ge $LOG_LEVEL ]; then
echo -e "${color}[$timestamp] $message${COLOR_RESET}" >&2
fi
}
log_debug() { log $LOG_LEVEL_DEBUG "DEBUG: $1" "$COLOR_CYAN"; }
log_info() { log $LOG_LEVEL_INFO "INFO: $1" "$COLOR_BLUE"; }
log_warn() { log $LOG_LEVEL_WARN "WARN: $1" "$COLOR_YELLOW"; }
log_error() { log $LOG_LEVEL_ERROR "ERROR: $1" "$COLOR_RED"; }
# 字符串函数
string_trim() {
local str=$1
echo "$str" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
string_length() {
local str=$1
echo -n "$str" | wc -c
}
string_contains() {
local str=$1
local substr=$2
[[ "$str" == *"$substr"* ]]
}
string_to_upper() {
local str=$1
echo "$str" | tr '[:lower:]' '[:upper:]'
}
string_to_lower() {
local str=$1
echo "$str" | tr '[:upper:]' '[:lower:]'
}
# 数组函数
array_join() {
local delimiter=$1
shift
local array=("$@")
local result=""
for item in "${array[@]}"; do
if [ -z "$result" ]; then
result="$item"
else
result="$result$delimiter$item"
fi
done
echo "$result"
}
array_contains() {
local target=$1
shift
local array=("$@")
for item in "${array[@]}"; do
if [ "$item" = "$target" ]; then
return 0
fi
done
return 1
}
# 文件操作函数
file_get_size() {
local file=$1
if [ -f "$file" ]; then
wc -c < "$file"
else
echo 0
fi
}
file_get_lines() {
local file=$1
if [ -f "$file" ]; then
wc -l < "$file"
else
echo 0
fi
}
file_backup() {
local file=$1
local backup_dir=${2:-./backup}
if [ ! -f "$file" ]; then
log_error "文件不存在: $file"
return 1
fi
mkdir -p "$backup_dir"
local backup_file="$backup_dir/$(basename "$file").$(date +%Y%m%d_%H%M%S).bak"
cp "$file" "$backup_file"
log_info "文件已备份: $backup_file"
echo "$backup_file"
}
# 系统信息函数
system_get_os() {
if [ -f /etc/os-release ]; then
source /etc/os-release
echo "$NAME $VERSION"
else
uname -s
fi
}
system_get_uptime() {
if command -v uptime >/dev/null; then
uptime | sed 's/.*up //' | sed 's/,.*//'
else
echo "未知"
fi
}
system_get_memory_info() {
if [ -f /proc/meminfo ]; then
local total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}')
local free_mem=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
echo "$((total_mem / 1024)) MB / $((free_mem / 1024)) MB"
else
echo "未知"
fi
}
# 网络函数
network_check_url() {
local url=$1
local timeout=${2:-5}
if command -v curl >/dev/null; then
if curl -s --max-time "$timeout" --head "$url" >/dev/null; then
return 0
fi
elif command -v wget >/dev/null; then
if wget -q --timeout="$timeout" --spider "$url" >/dev/null; then
return 0
fi
fi
return 1
}
network_get_public_ip() {
local services=(
"ifconfig.me"
"icanhazip.com"
"ident.me"
"ipecho.net/plain"
)
for service in "${services[@]}"; do
if command -v curl >/dev/null; then
local ip=$(curl -s "http://$service")
if [ -n "$ip" ]; then
echo "$ip"
return 0
fi
fi
done
echo "未知"
}
# 验证函数
validate_email() {
local email=$1
local regex="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
[[ $email =~ $regex ]]
}
validate_ip() {
local ip=$1
local regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
if [[ $ip =~ $regex ]]; then
local IFS='.'
read -r i1 i2 i3 i4 <<< "$ip"
[ "$i1" -le 255 ] && [ "$i2" -le 255 ] && [ "$i3" -le 255 ] && [ "$i4" -le 255 ]
else
return 1
fi
}
validate_domain() {
local domain=$1
local regex="^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
[[ $domain =~ $regex ]]
}
# 进度条函数
progress_bar() {
local current=$1
local total=$2
local width=${3:-50}
local percentage=$((current * 100 / total))
local completed=$((width * current / total))
local remaining=$((width - completed))
printf "\r["
printf "%${completed}s" | tr ' ' '='
printf "%${remaining}s" | tr ' ' '-'
printf "] %d%%" "$percentage"
if [ $current -eq $total ]; then
printf "\n"
fi
}
# 初始化检查
init_check() {
local dependencies=("$@")
local missing=()
for dep in "${dependencies[@]}"; do
if ! command -v "$dep" >/dev/null 2>&1; then
missing+=("$dep")
fi
done
if [ ${#missing[@]} -gt 0 ]; then
log_error "缺少依赖: $(array_join ', ' "${missing[@]}")"
return 1
fi
log_info "所有依赖检查通过"
return 0
}
EOF
# 创建使用函数库的示例脚本
cat > use_library.sh << 'EOF'
#!/bin/bash
# 导入函数库
source ./shell_library.sh
# 设置日志级别
LOG_LEVEL=0 # DEBUG
main() {
log_info "开始演示函数库使用"
# 系统信息演示
echo "=== 系统信息 ==="
echo "操作系统: $(system_get_os)"
echo "运行时间: $(system_get_uptime)"
echo "内存信息: $(system_get_memory_info)"
echo "公网 IP: $(network_get_public_ip)"
# 字符串操作演示
echo ""
echo "=== 字符串操作 ==="
test_string=" Hello World! "
echo "原始字符串: '$test_string'"
echo "修剪后: '$(string_trim "$test_string")'"
echo "大写: '$(string_to_upper "$test_string")'"
echo "小写: '$(string_to_lower "$test_string")'"
echo "长度: $(string_length "$test_string")"
# 数组操作演示
echo ""
echo "=== 数组操作 ==="
fruits=("Apple" "Banana" "Orange" "Grape")
echo "水果数组: $(array_join ', ' "${fruits[@]}")"
if array_contains "Apple" "${fruits[@]}"; then
log_success "找到 Apple"
else
log_error "未找到 Apple"
fi
# 进度条演示
echo ""
echo "=== 进度条演示 ==="
total=50
for i in $(seq 1 $total); do
progress_bar $i $total
sleep 0.05
done
# 文件操作演示
echo ""
echo "=== 文件操作 ==="
test_file="test_example.txt"
echo "创建测试文件..." > "$test_file"
echo "文件大小: $(file_get_size "$test_file") 字节"
echo "行数: $(file_get_lines "$test_file")"
# 备份文件
backup_file=$(file_backup "$test_file")
echo "备份文件: $backup_file"
# 清理
rm -f "$test_file" "$backup_file"
rmdir backup 2>/dev/null || true
log_success "演示完成"
}
# 检查依赖
required_commands=("curl" "wget" "bc")
if init_check "${required_commands[@]}"; then
main "$@"
else
log_warn "部分依赖缺失,但继续执行..."
main "$@"
fi
EOF
chmod +x shell_library.sh use_library.sh
./use_library.sh
3.2 高级文本处理和数据分析
graph LR
A[原始数据] --> B[数据清洗]
B --> C[数据转换]
C --> D[数据分析]
D --> E[结果输出]
D --> F[数据可视化]
D --> G[报告生成]
B --> B1[去除空行]
B --> B2[格式标准化]
B --> B3[数据验证]
C --> C1[字段提取]
C --> C2[数据计算]
C --> C3[格式转换]
D --> D1[统计分析]
D --> D2[模式识别]
D --> D3[异常检测]
style A fill:#4B0082,color:white
style B fill:#6A5ACD,color:white
style C fill:#483D8B,color:white
style D fill:#4169E1,color:white
style E fill:#32CD32,color:white
style F fill:#FFD700,color:white
style G fill:#FF6347,color:white
#!/bin/bash
# 创建高级文本处理脚本
cat > text_processing.sh << 'EOF'
#!/bin/bash
source ./shell_library.sh
# 高级文本处理函数
text_analyze() {
local file=$1
local output_dir=${2:-./analysis}
mkdir -p "$output_dir"
log_info "开始分析文件: $file"
if [ ! -f "$file" ]; then
log_error "文件不存在: $file"
return 1
fi
# 基础统计
local total_lines=$(file_get_lines "$file")
local total_words=$(wc -w < "$file")
local total_chars=$(wc -c < "$file")
local file_size=$(file_get_size "$file")
# 生成报告
local report_file="$output_dir/analysis_report.txt"
{
echo "文件分析报告"
echo "=============="
echo "文件名: $(basename "$file")"
echo "分析时间: $(date)"
echo ""
echo "基础统计:"
echo "---------"
echo "文件大小: $file_size 字节"
echo "总行数: $total_lines"
echo "总单词数: $total_words"
echo "总字符数: $total_chars"
echo ""
echo "行长度分析:"
echo "-----------"
awk '{print length}' "$file" | sort -n | uniq -c | \
awk '{printf "长度 %3d 字符: %4d 行\n", $2, $1}' | head -10
echo ""
echo "单词频率分析 (Top 20):"
echo "---------------------"
tr '[:upper:]' '[:lower:]' < "$file" | \
tr -cs '[:alnum:]' '\n' | \
sort | uniq -c | sort -nr | \
head -20 | awk '{printf "%-15s: %4d\n", $2, $1}'
echo ""
echo "字符频率分析:"
echo "-------------"
fold -w1 "$file" | sort | uniq -c | sort -nr | \
head -15 | awk '{
char = $2
if (char == " ") char="空格"
if (char == "\t") char="制表符"
if (char == "\n") char="换行符"
printf "%-10s: %4d\n", char, $1
}'
} > "$report_file"
# 生成可视化数据
generate_visualization "$file" "$output_dir"
log_success "分析完成: $report_file"
echo "$report_file"
}
generate_visualization() {
local file=$1
local output_dir=$2
# 生成单词频率 CSV
tr '[:upper:]' '[:lower:]' < "$file" | \
tr -cs '[:alnum:]' '\n' | \
sort | uniq -c | sort -nr | \
head -30 | awk '{print $2 "," $1}' > "$output_dir/word_freq.csv"
# 生成行长度分布
awk '{print length}' "$file" | sort -n | uniq -c | \
awk '{print $2 "," $1}' > "$output_dir/line_lengths.csv"
# 生成字符分布
fold -w1 "$file" | sort | uniq -c | sort -nr | head -20 | \
awk '{
char = $2
if (char == " ") char="space"
if (char == "\t") char="tab"
if (char == "\n") char="newline"
print char "," $1
}' > "$output_dir/char_freq.csv"
}
# 日志文件分析
analyze_log_file() {
local log_file=$1
local output_dir=${2:-./log_analysis}
mkdir -p "$output_dir"
log_info "分析日志文件: $log_file"
# 常见日志分析模式
local patterns=(
"ERROR"
"WARN"
"INFO"
"DEBUG"
"Exception"
"Failed"
"Timeout"
)
{
echo "日志分析报告"
echo "============="
echo "日志文件: $(basename "$log_file")"
echo "分析时间: $(date)"
echo ""
echo "日志级别统计:"
echo "-------------"
for pattern in "${patterns[@]}"; do
local count=$(grep -c "$pattern" "$log_file" || true)
echo "$pattern: $count"
done
echo ""
echo "时间分布分析:"
echo "-------------"
# 提取时间戳并统计
if grep -qE '[0-9]{4}-[0-9]{2}-[0-9]{2}' "$log_file"; then
grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' "$log_file" | \
sort | uniq -c | \
awk '{printf "%-12s: %4d 条日志\n", $2, $1}' | head -10
fi
echo ""
echo Top错误信息:
echo "-------------"
grep -i "error" "$log_file" | \
sed 's/.*[Ee]rror[: ]*//' | \
sort | uniq -c | sort -nr | \
head -10 | awk '{printf "%-40s: %3d\n", $2, $1}'
echo ""
echo "请求频率分析 (如果适用):"
echo "---------------------"
# 提取IP地址
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' "$log_file" 2>/dev/null | \
sort | uniq -c | sort -nr | \
head -10 | awk '{printf "%-15s: %4d 次访问\n", $2, $1}'
} > "$output_dir/log_analysis_report.txt"
log_success "日志分析完成"
}
# CSV 文件处理
csv_analyze() {
local csv_file=$1
local output_dir=${2:-./csv_analysis}
mkdir -p "$output_dir"
log_info "分析 CSV 文件: $csv_file"
if [ ! -f "$csv_file" ]; then
log_error "CSV 文件不存在: $csv_file"
return 1
fi
{
echo "CSV 文件分析报告"
echo "================="
echo "文件: $(basename "$csv_file")"
echo "分析时间: $(date)"
echo ""
echo "基础信息:"
echo "---------"
local total_lines=$(file_get_lines "$csv_file")
local header_line=$(head -1 "$csv_file")
local field_count=$(echo "$header_line" | tr ',' '\n' | wc -l)
echo "总行数: $total_lines"
echo "字段数: $field_count"
echo "数据行数: $((total_lines - 1))"
echo ""
echo "字段列表:"
echo "---------"
echo "$header_line" | tr ',' '\n' | nl -w2 -s': '
echo ""
echo "各字段统计:"
echo "-----------"
# 对每个字段进行基本统计
for ((i=1; i<=field_count; i++)); do
echo "字段 $i:"
# 提取该列数据 (跳过标题)
tail -n +2 "$csv_file" | cut -d',' -f"$i" | \
awk '
{
count++
if ($0 ~ /^[0-9]+(\.[0-9]+)?$/) {
sum += $0
nums[count] = $0
}
}
END {
if (count > 0) {
print " 样本数: " count
if (length(nums) > 0) {
asort(nums)
print " 数值范围: " nums[1] " - " nums[count]
print " 平均值: " sum/count
if (count % 2 == 1) {
print " 中位数: " nums[(count+1)/2]
} else {
print " 中位数: " (nums[count/2] + nums[count/2+1])/2
}
}
}
}
'
echo ""
done
} > "$output_dir/csv_analysis_report.txt"
log_success "CSV 分析完成"
}
# 主演示函数
main() {
log_info "开始高级文本处理演示"
# 创建测试数据
local test_data="sample_data.txt"
local test_log="sample_log.txt"
local test_csv="sample_data.csv"
# 生成测试文本文件
cat > "$test_data" << 'SAMPLE'
Shell scripting is a powerful tool for system administrators and developers.
It allows automation of complex tasks and system management.
Error handling is crucial in production scripts.
Debugging skills are essential for every programmer.
The Linux command line provides numerous text processing utilities.
Regular expressions are patterns used to match character combinations in strings.
Data analysis can be performed using awk, sed, and other tools.
Automation saves time and reduces human errors.
Shell scripts can process logs, CSV files, and other data formats.
Advanced scripting includes functions, libraries, and modular design.
SAMPLE
# 生成测试日志文件
cat > "$test_log" << 'LOG'
2024-01-15 10:00:01 INFO Application started successfully
2024-01-15 10:00:05 DEBUG Loading configuration from file
2024-01-15 10:00:10 WARN Configuration file not found, using defaults
2024-01-15 10:01:15 ERROR Database connection failed: Connection timeout
2024-01-15 10:01:20 INFO Retrying database connection
2024-01-15 10:01:25 ERROR Authentication failed: Invalid credentials
2024-01-15 10:02:30 INFO User login successful from IP 192.168.1.100
2024-01-15 10:03:45 WARN High memory usage detected: 85%
2024-01-15 10:04:50 INFO Backup completed successfully
2024-01-15 10:05:55 ERROR File not found: /var/log/app/archive.log
LOG
# 生成测试 CSV 文件
cat > "$test_csv" << 'CSV'
Name,Age,Salary,Department
John Doe,30,50000,Engineering
Jane Smith,25,45000,Marketing
Bob Johnson,35,60000,Engineering
Alice Brown,28,52000,Sales
Charlie Wilson,42,75000,Management
Diana Lee,29,48000,Engineering
CSV
# 执行各种分析
log_info "执行文本分析..."
text_analyze "$test_data" "text_analysis"
log_info "执行日志分析..."
analyze_log_file "$test_log" "log_analysis"
log_info "执行 CSV 分析..."
csv_analyze "$test_csv" "csv_analysis"
# 显示结果摘要
echo ""
echo "=== 分析结果摘要 ==="
echo "文本分析: text_analysis/analysis_report.txt"
echo "日志分析: log_analysis/log_analysis_report.txt"
echo "CSV 分析: csv_analysis/csv_analysis_report.txt"
# 清理测试文件
rm -f "$test_data" "$test_log" "$test_csv"
log_success "高级文本处理演示完成"
}
main "$@"
EOF
chmod +x text_processing.sh
./text_processing.sh
3.3 系统管理和自动化脚本
#!/bin/bash
# 创建系统管理脚本
cat > system_manager.sh << 'EOF'
#!/bin/bash
source ./shell_library.sh
# 系统管理函数
system_monitor() {
local output_file=${1:-./system_report.txt}
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
log_info "生成系统监控报告..."
{
echo "系统监控报告"
echo "============="
echo "生成时间: $timestamp"
echo "主机名: $(hostname)"
echo ""
echo "1. 系统信息:"
echo "-----------"
echo "操作系统: $(system_get_os)"
echo "内核版本: $(uname -r)"
echo "系统架构: $(uname -m)"
echo "运行时间: $(system_get_uptime)"
echo ""
echo "2. CPU 信息:"
echo "-----------"
echo "CPU 型号: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2 | sed 's/^ *//')"
echo "CPU 核心数: $(grep -c 'processor' /proc/cpuinfo)"
echo "CPU 使用率: $(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1"%"}')"
echo ""
echo "3. 内存信息:"
echo "-----------"
free -h | sed 's/^/ /'
echo ""
echo "4. 磁盘使用:"
echo "-----------"
df -h | grep -v tmpfs | sed 's/^/ /'
echo ""
echo "5. 网络信息:"
echo "-----------"
echo "主机名: $(hostname)"
echo "IP 地址: $(hostname -I 2>/dev/null || echo '未知')"
echo "公网 IP: $(network_get_public_ip)"
echo ""
echo "6. 负载信息:"
echo "-----------"
uptime | sed 's/^/ /'
echo ""
echo "7. 当前用户:"
echo "-----------"
who | sed 's/^/ /'
echo ""
echo "8. 进程统计:"
echo "-----------"
echo "总进程数: $(ps -e | wc -l)"
echo "用户进程数: $(ps -u $(whoami) | wc -l)"
echo ""
echo "9. 服务状态:"
echo "-----------"
# 检查常见服务
local services=("ssh" "nginx" "apache2" "mysql" "docker")
for service in "${services[@]}"; do
if systemctl is-active --quiet "$service" 2>/dev/null; then
echo " $service: 运行中"
elif command -v "$service" >/dev/null 2>&1; then
echo " $service: 已安装"
else
echo " $service: 未安装"
fi
done
echo ""
echo "10. 安全信息:"
echo "------------"
echo "失败登录尝试: $(lastb 2>/dev/null | wc -l || echo '无权限')"
echo "最近登录:"
last -5 | head -5 | sed 's/^/ /'
} > "$output_file"
log_success "系统监控报告已生成: $output_file"
}
# 自动化备份函数
auto_backup() {
local source_dir=$1
local backup_dir=$2
local retention_days=${3:-7}
if [ ! -d "$source_dir" ]; then
log_error "源目录不存在: $source_dir"
return 1
fi
mkdir -p "$backup_dir"
local timestamp=$(date '+%Y%m%d_%H%M%S')
local backup_name="backup_$(basename "$source_dir")_$timestamp.tar.gz"
local backup_path="$backup_dir/$backup_name"
log_info "开始备份: $source_dir -> $backup_path"
# 创建备份
if tar -czf "$backup_path" -C "$(dirname "$source_dir")" "$(basename "$source_dir")" 2>/dev/null; then
local backup_size=$(du -h "$backup_path" | cut -f1)
log_success "备份完成: $backup_path ($backup_size)"
# 清理旧备份
cleanup_old_backups "$backup_dir" "$retention_days"
else
log_error "备份失败: $source_dir"
return 1
fi
}
cleanup_old_backups() {
local backup_dir=$1
local retention_days=$2
log_info "清理 $retention_days 天前的旧备份..."
find "$backup_dir" -name "backup_*.tar.gz" -type f -mtime "+$retention_days" | \
while read -r old_backup; do
log_info "删除旧备份: $(basename "$old_backup")"
rm -f "$old_backup"
done
log_success "备份清理完成"
}
# 日志轮转函数
log_rotate() {
local log_file=$1
local max_size_mb=${2:-10}
local backup_count=${3:-5}
if [ ! -f "$log_file" ]; then
log_warn "日志文件不存在: $log_file"
return 0
fi
local current_size=$(file_get_size "$log_file")
local max_size=$((max_size_mb * 1024 * 1024))
if [ $current_size -gt $max_size ]; then
log_info "执行日志轮转: $log_file"
# 轮转现有备份文件
for ((i=backup_count-1; i>=1; i--)); do
local old_file="$log_file.$i"
local new_file="$log_file.$((i+1))"
if [ -f "$old_file" ]; then
mv "$old_file" "$new_file"
fi
done
# 创建新备份
mv "$log_file" "$log_file.1"
touch "$log_file"
chmod 644 "$log_file"
log_success "日志轮转完成"
else
log_debug "日志文件大小正常: $((current_size/1024/1024))MB < ${max_size_mb}MB"
fi
}
# 系统健康检查
health_check() {
local warning_threshold=80
local critical_threshold=90
log_info "执行系统健康检查..."
local issues=()
local warnings=()
# 检查磁盘使用率
while IFS= read -r line; do
local usage=$(echo "$line" | awk '{print $5}' | sed 's/%//')
local mount=$(echo "$line" | awk '{print $6}')
if [ "$usage" -ge "$critical_threshold" ]; then
issues+=("磁盘空间严重不足: $mount ($usage%)")
elif [ "$usage" -ge "$warning_threshold" ]; then
warnings+=("磁盘空间警告: $mount ($usage%)")
fi
done < <(df -h | grep -v tmpfs | tail -n +2)
# 检查内存使用
local mem_info=$(free | grep Mem)
local total_mem=$(echo "$mem_info" | awk '{print $2}')
local used_mem=$(echo "$mem_info" | awk '{print $3}')
local mem_usage=$((used_mem * 100 / total_mem))
if [ "$mem_usage" -ge "$critical_threshold" ]; then
issues+=("内存使用率过高: $mem_usage%")
elif [ "$mem_usage" -ge "$warning_threshold" ]; then
warnings+=("内存使用率警告: $mem_usage%")
fi
# 检查负载
local load_avg=$(awk '{print $1}' /proc/loadavg)
local cpu_cores=$(grep -c processor /proc/cpuinfo)
local load_percentage=$(echo "scale=2; $load_avg * 100 / $cpu_cores" | bc)
if [ $(echo "$load_percentage > $critical_threshold" | bc) -eq 1 ]; then
issues+=("系统负载过高: $load_avg ($load_percentage%)")
elif [ $(echo "$load_percentage > $warning_threshold" | bc) -eq 1 ]; then
warnings+=("系统负载警告: $load_avg ($load_percentage%)")
fi
# 输出检查结果
echo "=== 系统健康检查报告 ==="
echo "检查时间: $(date)"
echo ""
if [ ${#issues[@]} -eq 0 ] && [ ${#warnings[@]} -eq 0 ]; then
log_success "所有系统指标正常"
else
if [ ${#issues[@]} -gt 0 ]; then
echo "严重问题:"
for issue in "${issues[@]}"; do
log_error " ❌ $issue"
done
echo ""
fi
if [ ${#warnings[@]} -gt 0 ]; then
echo "警告信息:"
for warning in "${warnings[@]}"; do
log_warn " ⚠️ $warning"
done
fi
fi
return ${#issues[@]}
}
# 主演示函数
main() {
local action=${1:-all}
case $action in
monitor)
system_monitor "./system_report_$(date +%Y%m%d_%H%M%S).txt"
;;
backup)
auto_backup "/home/$USER" "./backups" 7
;;
health)
health_check
;;
log-rotate)
log_rotate "/var/log/syslog" 10 5
;;
all|*)
log_info "执行完整的系统管理演示..."
# 系统监控
system_monitor "./system_report_$(date +%Y%m%d_%H%M%S).txt"
# 健康检查
health_check
# 创建测试目录进行备份演示
local test_dir="./test_backup_source"
mkdir -p "$test_dir"
echo "测试备份数据" > "$test_dir/test_file.txt"
# 备份演示
auto_backup "$test_dir" "./backups" 7
# 清理
rm -rf "$test_dir"
log_success "系统管理演示完成"
;;
esac
}
# 参数处理
case ${1:-} in
-h|--help)
echo "系统管理脚本"
echo "用法: $0 [命令]"
echo ""
echo "命令:"
echo " monitor 生成系统监控报告"
echo " backup 执行目录备份"
echo " health 系统健康检查"
echo " log-rotate 日志轮转"
echo " all 执行所有操作(默认)"
;;
*)
main "$@"
;;
esac
EOF
chmod +x system_manager.sh
# 创建安装和配置脚本
cat > setup_environment.sh << 'EOF'
#!/bin/bash
# 环境设置脚本
source ./shell_library.sh
setup_environment() {
log_info "开始设置 Shell 脚本开发环境"
# 创建目录结构
local directories=(
"~/shell_scripts"
"~/shell_scripts/libs"
"~/shell_scripts/utils"
"~/shell_scripts/backups"
"~/shell_scripts/logs"
"~/shell_scripts/tests"
)
for dir in "${directories[@]}"; do
local expanded_dir=$(eval echo "$dir")
mkdir -p "$expanded_dir"
log_success "创建目录: $expanded_dir"
done
# 复制函数库
if [ -f "shell_library.sh" ]; then
cp "shell_library.sh" ~/shell_scripts/libs/
log_success "安装函数库"
fi
# 创建配置文件
local config_file="$HOME/.shell_config"
cat > "$config_file" << 'CONFIG'
# Shell 脚本开发环境配置
SHELL_SCRIPT_HOME="$HOME/shell_scripts"
LOG_LEVEL=1 # 0=DEBUG, 1=INFO, 2=WARN, 3=ERROR
BACKUP_RETENTION_DAYS=7
MAX_LOG_SIZE_MB=10
# 颜色配置
export COLOR_DEBUG="\\033[0;36m"
export COLOR_INFO="\\033[0;32m"
export COLOR_WARN="\\033[1;33m"
export COLOR_ERROR="\\033[0;31m"
# 路径配置
export PATH="$HOME/shell_scripts/utils:$PATH"
CONFIG
log_success "创建配置文件: $config_file"
# 创建实用工具脚本
create_utility_scripts
# 设置 bashrc
setup_bashrc
log_success "环境设置完成"
echo ""
echo "下一步:"
echo "1. 重新加载配置: source ~/.bashrc"
echo "2. 探索目录: cd ~/shell_scripts"
echo "3. 开始编写你的脚本!"
}
create_utility_scripts() {
local utils_dir="$HOME/shell_scripts/utils"
# 创建脚本模板生成器
cat > "$utils_dir/new_script.sh" << 'TEMPLATE'
#!/bin/bash
# 脚本模板生成器
create_script() {
local script_name=$1
local script_type=${2:-basic}
if [ -z "$script_name" ]; then
echo "用法: $0 <脚本名> [类型]"
echo "类型: basic, advanced, library, tool"
return 1
fi
local template=""
case $script_type in
advanced)
template=$(cat << 'ADVANCED'
#!/bin/bash
# 高级脚本模板
set -eEuo pipefail
# 导入函数库
source ~/shell_scripts/libs/shell_library.sh
# 配置
readonly SCRIPT_NAME="$(basename "$0")"
readonly VERSION="1.0.0"
readonly LOCK_FILE="/tmp/${SCRIPT_NAME}.lock"
# 信号处理
cleanup() {
log_info "清理资源..."
rm -f "$LOCK_FILE"
}
trap cleanup EXIT
trap 'log_error "脚本被中断"; exit 1' INT TERM
# 用法说明
usage() {
cat << EOF
用法: $SCRIPT_NAME [选项]
选项:
-h, --help 显示帮助信息
-v, --version 显示版本信息
-d, --debug 启用调试模式
-f, --file FILE 指定输入文件
示例:
$SCRIPT_NAME -f input.txt
$SCRIPT_NAME --debug
EOF
}
# 参数解析
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
exit 0
;;
-v|--version)
echo "$SCRIPT_NAME version $VERSION"
exit 0
;;
-d|--debug)
LOG_LEVEL=0
set -x
;;
-f|--file)
INPUT_FILE="$2"
shift 2
;;
*)
log_error "未知参数: $1"
usage
exit 1
;;
esac
done
}
# 主函数
main() {
log_info "开始执行 $SCRIPT_NAME"
# 检查锁文件
if [ -f "$LOCK_FILE" ]; then
log_error "脚本已在运行中: $LOCK_FILE"
exit 1
fi
echo $$ > "$LOCK_FILE"
# 参数解析
parse_arguments "$@"
# 业务逻辑
log_success "脚本执行完成"
}
# 运行主函数
main "$@"
ADVANCED
)
;;
library)
template=$(cat << 'LIBRARY'
#!/bin/bash
# 函数库模板
# 库信息
readonly LIB_NAME="$(basename "$0")"
readonly LIB_VERSION="1.0.0"
# 初始化检查
lib_init() {
local dependencies=("$@")
for dep in "${dependencies[@]}"; do
if ! command -v "$dep" >/dev/null 2>&1; then
echo "错误: 缺少依赖 $dep" >&2
return 1
fi
done
return 0
}
# 库函数示例
example_function() {
local input=$1
echo "处理输入: $input"
}
# 如果直接执行库文件,显示信息
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
echo "库: $LIB_NAME"
echo "版本: $LIB_VERSION"
echo "这是一个函数库,应该通过 source 命令导入"
fi
LIBRARY
)
;;
tool)
template=$(cat << 'TOOL'
#!/bin/bash
# 工具脚本模板
# 配置
readonly TOOL_NAME="$(basename "$0")"
readonly VERSION="1.0.0"
# 颜色定义
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m'
# 日志函数
log() {
local level=$1
shift
local message=$*
case $level in
error) echo -e "${RED}[错误]${NC} $message" >&2 ;;
warn) echo -e "${YELLOW}[警告]${NC} $message" >&2 ;;
info) echo -e "${BLUE}[信息]${NC} $message" ;;
success) echo -e "${GREEN}[成功]${NC} $message" ;;
esac
}
# 显示帮助
show_help() {
cat << EOF
$TOOL_NAME - 工具描述
用法: $TOOL_NAME [命令] [选项]
命令:
command1 描述命令1
command2 描述命令2
选项:
-h, --help 显示此帮助信息
-v, --version 显示版本信息
示例:
$TOOL_NAME command1
$TOOL_NAME command2 --option value
EOF
}
# 命令实现
command1() {
log info "执行命令1"
# 命令1的实现
log success "命令1完成"
}
command2() {
log info "执行命令2"
# 命令2的实现
log success "命令2完成"
}
# 主函数
main() {
local command=${1:-}
case $command in
-h|--help)
show_help
;;
-v|--version)
echo "$TOOL_NAME version $VERSION"
;;
command1)
shift
command1 "$@"
;;
command2)
shift
command2 "$@"
;;
*)
if [ -n "$command" ]; then
log error "未知命令: $command"
fi
show_help
exit 1
;;
esac
}
# 运行主函数
main "$@"
TOOL
)
;;
basic|*)
template=$(cat << 'BASIC'
#!/bin/bash
# 基础脚本模板
# 描述: 脚本功能描述
set -e # 遇到错误退出
# 配置
SCRIPT_NAME="$(basename "$0")"
# 帮助信息
show_help() {
echo "用法: $SCRIPT_NAME [选项]"
echo ""
echo "选项:"
echo " -h, --help 显示帮助信息"
echo " -v, --version 显示版本信息"
}
# 主逻辑
main() {
echo "Hello from $SCRIPT_NAME"
# 在这里添加你的逻辑
echo "脚本执行完成"
}
# 参数处理
case ${1:-} in
-h|--help)
show_help
;;
-v|--version)
echo "$SCRIPT_NAME version 1.0.0"
;;
*)
main "$@"
;;
esac
BASIC
)
;;
esac
local script_path="$utils_dir/$script_name"
echo "$template" > "$script_path"
chmod +x "$script_path"
log_success "创建脚本: $script_path"
}
setup_bashrc() {
local bashrc_file="$HOME/.bashrc"
local marker="# Shell Script Environment Setup"
if grep -q "$marker" "$bashrc_file"; then
log_info "环境配置已存在"
return 0
fi
cat >> "$bashrc_file" << 'BASHRC'
# Shell Script Environment Setup
export SHELL_SCRIPT_HOME="$HOME/shell_scripts"
export PATH="$SHELL_SCRIPT_HOME/utils:$PATH"
# 加载 shell 配置
if [ -f "$HOME/.shell_config" ]; then
source "$HOME/.shell_config"
fi
# 有用的别名
alias ss='cd $SHELL_SCRIPT_HOME'
alias ss-run='$SHELL_SCRIPT_HOME/utils/'
alias ss-lib='source $SHELL_SCRIPT_HOME/libs/shell_library.sh'
echo "Shell 脚本环境已加载"
BASHRC
log_success "更新 bashrc 配置"
}
# 主执行
setup_environment
EOF
chmod +x setup_environment.sh
echo "================================================"
echo " 所有脚本创建完成!"
echo "================================================"
echo ""
echo "下一步操作:"
echo "1. 设置环境: ./setup_environment.sh"
echo "2. 学习基础: 从 hello_world.sh 开始"
echo "3. 掌握调试: 运行 debugging_demo.sh"
echo "4. 使用高级功能: 查看 text_processing.sh"
echo "5. 系统管理: 运行 system_manager.sh"
echo ""
echo "记住 Shell 编程的旅程:"
echo "入门 → 理解基础"
echo "放弃 → 克服困难"
echo "装逼 → 掌握高级技巧"
echo "================================================"
# 设置环境
./setup_environment.sh
4. 实际项目实战
4.1 完整的网站部署脚本
#!/bin/bash
# 创建网站部署脚本
cat > website_deploy.sh << 'EOF'
#!/bin/bash
# 网站自动化部署脚本
set -eEuo pipefail
# 导入函数库
source ~/shell_scripts/libs/shell_library.sh
# 配置
readonly SCRIPT_NAME="website_deploy.sh"
readonly VERSION="2.0.0"
readonly DEPLOY_LOG="/var/log/website_deploy.log"
# 部署配置
DEPLOY_ENV=${1:-staging}
BACKUP_ENABLED=true
VALIDATE_SSL=true
SEND_NOTIFICATIONS=true
# 环境特定配置
case $DEPLOY_ENV in
production)
DOMAIN="example.com"
WEB_ROOT="/var/www/production"
DB_NAME="app_production"
NOTIFICATION_EMAIL="admin@example.com"
;;
staging)
DOMAIN="staging.example.com"
WEB_ROOT="/var/www/staging"
DB_NAME="app_staging"
NOTIFICATION_EMAIL="dev@example.com"
;;
development)
DOMAIN="dev.example.com"
WEB_ROOT="/var/www/development"
DB_NAME="app_development"
NOTIFICATION_EMAIL="dev@example.com"
BACKUP_ENABLED=false
VALIDATE_SSL=false
;;
*)
log_error "未知环境: $DEPLOY_ENV"
echo "可用环境: production, staging, development"
exit 1
;;
esac
# 信号处理
cleanup() {
log_info "执行清理操作..."
# 清理临时文件
rm -rf "/tmp/deploy_$$*"
log_success "清理完成"
}
trap cleanup EXIT
trap 'log_error "部署被中断"; exit 1' INT TERM
# 通知函数
send_notification() {
local subject=$1
local message=$2
if [ "$SEND_NOTIFICATIONS" = true ]; then
echo "$message" | mail -s "$subject" "$NOTIFICATION_EMAIL" 2>/dev/null || \
log_warn "无法发送邮件通知"
fi
log_info "通知: $subject"
}
# 数据库备份
backup_database() {
if [ "$BACKUP_ENABLED" = false ]; then
log_info "跳过数据库备份"
return 0
fi
local backup_dir="/backup/database"
local timestamp=$(date '+%Y%m%d_%H%M%S')
local backup_file="$backup_dir/${DB_NAME}_${timestamp}.sql.gz"
log_info "开始数据库备份..."
mkdir -p "$backup_dir"
if mysqldump -u root "$DB_NAME" | gzip > "$backup_file"; then
local size=$(du -h "$backup_file" | cut -f1)
log_success "数据库备份完成: $backup_file ($size)"
echo "$backup_file"
else
log_error "数据库备份失败"
return 1
fi
}
# 文件备份
backup_files() {
if [ "$BACKUP_ENABLED" = false ]; then
log_info "跳过文件备份"
return 0
fi
local backup_dir="/backup/files"
local timestamp=$(date '+%Y%m%d_%H%M%S')
local backup_file="$backup_dir/webroot_${timestamp}.tar.gz"
log_info "开始文件备份..."
mkdir -p "$backup_dir"
if tar -czf "$backup_file" -C "/var/www" "$(basename "$WEB_ROOT")" 2>/dev/null; then
local size=$(du -h "$backup_file" | cut -f1)
log_success "文件备份完成: $backup_file ($size)"
echo "$backup_file"
else
log_error "文件备份失败"
return 1
fi
}
# 验证系统要求
validate_requirements() {
log_info "验证系统要求..."
local required_commands=("git" "tar" "gzip" "mysql" "curl")
local missing_commands=()
for cmd in "${required_commands[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
missing_commands+=("$cmd")
fi
done
if [ ${#missing_commands[@]} -gt 0 ]; then
log_error "缺少必要命令: ${missing_commands[*]}"
return 1
fi
# 验证目录权限
if [ ! -w "$WEB_ROOT" ]; then
log_error "没有写入权限: $WEB_ROOT"
return 1
fi
# 验证数据库连接
if ! mysql -u root -e "USE $DB_NAME" 2>/dev/null; then
log_error "无法连接数据库: $DB_NAME"
return 1
fi
log_success "所有系统要求验证通过"
}
# 获取最新代码
fetch_latest_code() {
local repo_url="https://github.com/example/app.git"
local temp_dir="/tmp/deploy_$$"
local branch="main"
log_info "获取最新代码..."
mkdir -p "$temp_dir"
if [ -d "$WEB_ROOT/.git" ]; then
# 已有仓库,拉取更新
cd "$WEB_ROOT"
git fetch origin
git checkout "$branch"
git pull origin "$branch"
else
# 全新部署
git clone -b "$branch" "$repo_url" "$temp_dir/app"
# 备份现有文件(如果有)
if [ -d "$WEB_ROOT" ] && [ "$(ls -A "$WEB_ROOT")" ]; then
local backup_file=$(backup_files)
fi
# 清空目标目录
rm -rf "$WEB_ROOT"/*
# 复制新文件
cp -r "$temp_dir/app"/* "$WEB_ROOT/"
cp -r "$temp_dir/app"/.env.example "$WEB_ROOT/.env"
fi
log_success "代码更新完成"
}
# 安装依赖
install_dependencies() {
log_info "安装依赖..."
cd "$WEB_ROOT"
if [ -f "composer.json" ]; then
log_info "安装 PHP 依赖..."
composer install --no-dev --optimize-autoloader
fi
if [ -f "package.json" ]; then
log_info "安装 Node.js 依赖..."
npm install --production
if [ -f "package-lock.json" ]; then
npm ci --production
fi
fi
if [ -f "requirements.txt" ]; then
log_info "安装 Python 依赖..."
pip install -r requirements.txt
fi
log_success "依赖安装完成"
}
# 运行数据库迁移
run_migrations() {
log_info "运行数据库迁移..."
cd "$WEB_ROOT"
if [ -f "artisan" ]; then
# Laravel
php artisan migrate --force
php artisan db:seed --force
elif [ -f "manage.py" ]; then
# Django
python manage.py migrate
python manage.py collectstatic --noinput
elif [ -f "yii" ]; then
# Yii
php yii migrate --interactive=0
fi
log_success "数据库迁移完成"
}
# 构建前端资源
build_assets() {
log_info "构建前端资源..."
cd "$WEB_ROOT"
if [ -f "webpack.mix.js" ] || [ -f "webpack.config.js" ]; then
npm run production
elif [ -f "gulpfile.js" ]; then
gulp --production
elif [ -f "vite.config.js" ]; then
npm run build
fi
log_success "前端资源构建完成"
}
# 优化应用
optimize_application() {
log_info "优化应用..."
cd "$WEB_ROOT"
if [ -f "artisan" ]; then
# Laravel 优化
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
elif [ -f "manage.py" ]; then
# Django 优化已在 collectstatic 中处理
:
fi
# 设置正确的文件权限
chown -R www-data:www-data "$WEB_ROOT"
find "$WEB_ROOT" -type f -exec chmod 644 {} \;
find "$WEB_ROOT" -type d -exec chmod 755 {} \;
# 设置存储目录权限
if [ -d "$WEB_ROOT/storage" ]; then
chmod -R 775 "$WEB_ROOT/storage"
fi
if [ -d "$WEB_ROOT/bootstrap/cache" ]; then
chmod -R 775 "$WEB_ROOT/bootstrap/cache"
fi
log_success "应用优化完成"
}
# 健康检查
health_check() {
local max_attempts=30
local attempt=1
log_info "执行健康检查..."
while [ $attempt -le $max_attempts ]; do
if curl -f -s "https://$DOMAIN/health" > /dev/null 2>&1; then
log_success "健康检查通过"
return 0
fi
log_info "健康检查尝试 $attempt/$max_attempts 失败,重试..."
sleep 5
((attempt++))
done
log_error "健康检查失败:应用在 $max_attempts 次尝试后仍不可用"
return 1
}
# SSL 验证
validate_ssl() {
if [ "$VALIDATE_SSL" = false ]; then
log_info "跳过 SSL 验证"
return 0
fi
log_info "验证 SSL 证书..."
if ! openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" < /dev/null 2>/dev/null | openssl x509 -noout -dates; then
log_error "SSL 证书验证失败"
return 1
fi
log_success "SSL 证书验证通过"
}
# 部署后清理
post_deploy_cleanup() {
log_info "执行部署后清理..."
# 清理旧备份(保留最近7天)
find /backup -name "*.sql.gz" -type f -mtime +7 -delete
find /backup -name "*.tar.gz" -type f -mtime +7 -delete
# 清理缓存文件
if [ -d "$WEB_ROOT/storage/framework/cache" ]; then
rm -rf "$WEB_ROOT/storage/framework/cache/*"
fi
# 清理日志文件(保留最近5个)
find "$WEB_ROOT/storage/logs" -name "*.log" -type f | sort -r | tail -n +6 | xargs rm -f
log_success "清理完成"
}
# 生成部署报告
generate_deploy_report() {
local report_file="/tmp/deploy_report_$$.txt"
local deployment_time=$(date '+%Y-%m-%d %H:%M:%S')
{
echo "网站部署报告"
echo "============="
echo "环境: $DEPLOY_ENV"
echo "域名: $DOMAIN"
echo "部署时间: $deployment_time"
echo "版本: $VERSION"
echo ""
echo "执行步骤:"
echo "---------"
echo "✓ 系统要求验证"
echo "✓ 数据库备份"
echo "✓ 文件备份"
echo "✓ 代码更新"
echo "✓ 依赖安装"
echo "✓ 数据库迁移"
echo "✓ 前端构建"
echo "✓ 应用优化"
echo "✓ 健康检查"
echo "✓ SSL 验证"
echo "✓ 部署后清理"
echo ""
echo "状态: 成功 ✅"
echo ""
echo "部署详情:"
echo "---------"
echo "Web 根目录: $WEB_ROOT"
echo "数据库: $DB_NAME"
echo "日志文件: $DEPLOY_LOG"
} > "$report_file"
log_success "部署报告生成: $report_file"
cat "$report_file"
# 发送通知
send_notification "部署成功: $DOMAIN ($DEPLOY_ENV)" "网站部署已完成且验证成功"
}
# 主部署函数
deploy() {
local start_time=$(date +%s)
log_info "开始部署到 $DEPLOY_ENV 环境"
log_info "目标: $DOMAIN"
# 执行部署步骤
validate_requirements
backup_database
backup_files
fetch_latest_code
install_dependencies
run_migrations
build_assets
optimize_application
health_check
validate_ssl
post_deploy_cleanup
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log_success "部署完成! 总耗时: ${duration}秒"
generate_deploy_report
}
# 回滚函数
rollback() {
local backup_type=${1:-database}
local rollback_point=${2:-latest}
log_info "开始回滚: $backup_type ($rollback_point)"
case $backup_type in
database)
# 查找最新的数据库备份
local latest_backup=$(find /backup/database -name "*${DB_NAME}*.sql.gz" -type f | sort -r | head -1)
if [ -z "$latest_backup" ]; then
log_error "找不到数据库备份文件"
return 1
fi
log_info "恢复数据库备份: $latest_backup"
gunzip -c "$latest_backup" | mysql -u root "$DB_NAME"
;;
files)
# 查找最新的文件备份
local latest_backup=$(find /backup/files -name "webroot_*.tar.gz" -type f | sort -r | head -1)
if [ -z "$latest_backup" ]; then
log_error "找不到文件备份"
return 1
fi
log_info "恢复文件备份: $latest_backup"
tar -xzf "$latest_backup" -C "/"
;;
full)
rollback database
rollback files
;;
*)
log_error "未知的回滚类型: $backup_type"
echo "可用类型: database, files, full"
return 1
;;
esac
log_success "回滚完成"
send_notification "回滚执行: $DOMAIN" "已回滚 $backup_type 到 $rollback_point"
}
# 显示部署状态
deploy_status() {
log_info "检查部署状态..."
echo "=== 部署状态报告 ==="
echo "环境: $DEPLOY_ENV"
echo "检查时间: $(date)"
echo ""
# 检查服务状态
echo "服务状态:"
if systemctl is-active nginx >/dev/null 2>&1; then
echo "✓ Nginx: 运行中"
else
echo "✗ Nginx: 未运行"
fi
if systemctl is-active mysql >/dev/null 2>&1; then
echo "✓ MySQL: 运行中"
else
echo "✗ MySQL: 未运行"
fi
if systemctl is-active php-fpm >/dev/null 2>&1; then
echo "✓ PHP-FPM: 运行中"
else
echo "✗ PHP-FPM: 未运行"
fi
echo ""
# 检查应用状态
echo "应用状态:"
if curl -f -s "https://$DOMAIN/health" >/dev/null 2>&1; then
echo "✓ 应用: 健康"
else
echo "✗ 应用: 不健康"
fi
if [ -d "$WEB_ROOT/.git" ]; then
local commit_hash=$(cd "$WEB_ROOT" && git log -1 --format=%H)
local commit_date=$(cd "$WEB_ROOT" && git log -1 --format=%cd)
echo "✓ Git: 最新提交 $commit_hash"
echo " 日期: $commit_date"
else
echo "✗ Git: 未初始化"
fi
echo ""
# 检查资源使用
echo "资源使用:"
local disk_usage=$(df -h "$WEB_ROOT" | awk 'NR==2 {print $5}')
echo "磁盘使用: $disk_usage"
local memory_usage=$(free -h | awk 'NR==2 {print $3"/"$2}')
echo "内存使用: $memory_usage"
}
# 主函数
main() {
local command=${1:-deploy}
shift
case $command in
deploy)
deploy "$@"
;;
rollback)
rollback "$@"
;;
status)
deploy_status "$@"
;;
validate)
validate_requirements
;;
-h|--help)
cat << EOF
网站部署脚本 - $VERSION
用法: $SCRIPT_NAME [命令] [参数]
命令:
deploy [环境] 执行部署 (默认: staging)
rollback [类型] 回滚到上一个版本
status 检查部署状态
validate 验证系统要求
环境:
production 生产环境
staging 预发布环境
development 开发环境
回滚类型:
database 回滚数据库
files 回滚文件
full 完全回滚
示例:
$SCRIPT_NAME deploy production
$SCRIPT_NAME rollback database
$SCRIPT_NAME status
$SCRIPT_NAME validate
EOF
;;
-v|--version)
echo "$SCRIPT_NAME version $VERSION"
;;
*)
log_error "未知命令: $command"
echo "使用 $SCRIPT_NAME --help 查看帮助"
exit 1
;;
esac
}
# 日志重定向
exec > >(tee -a "$DEPLOY_LOG")
exec 2>&1
# 运行主函数
main "$@"
EOF
chmod +x website_deploy.sh
4.2 Docker 容器管理脚本
#!/bin/bash
# 创建 Docker 管理脚本
cat > docker_manager.sh << 'EOF'
#!/bin/bash
# Docker 容器管理脚本
set -eEuo pipefail
source ~/shell_scripts/libs/shell_library.sh
# 配置
readonly SCRIPT_NAME="docker_manager.sh"
readonly VERSION="1.5.0"
readonly DOCKER_COMPOSE_FILE="docker-compose.yml"
readonly BACKUP_DIR="/backup/docker"
# 颜色定义
readonly DOCKER_COLOR_CYAN='\033[0;36m'
readonly DOCKER_COLOR_BLUE='\033[0;34m'
readonly DOCKER_COLOR_RESET='\033[0m'
# 容器配置
declare -A SERVICES=(
["web"]="nginx:alpine"
["app"]="node:16-alpine"
["db"]="mysql:8.0"
["cache"]="redis:alpine"
)
# 显示 Docker 信息
docker_info() {
echo -e "${DOCKER_COLOR_CYAN}"
echo "🐳 Docker 环境信息"
echo -e "${DOCKER_COLOR_RESET}"
echo "Docker 版本: $(docker --version 2>/dev/null | cut -d' ' -f3 | sed 's/,//')"
echo "Docker Compose 版本: $(docker-compose --version 2>/dev/null | cut -d' ' -f3 | sed 's/,//')"
echo "容器数量: $(docker ps -q | wc -l)"
echo "镜像数量: $(docker images -q | wc -l)"
echo ""
}
# 生成 Docker Compose 文件
generate_docker_compose() {
local env=${1:-development}
log_info "生成 Docker Compose 配置: $env"
cat > "$DOCKER_COMPOSE_FILE" << COMPOSE
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: web_server
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./html:/usr/share/nginx/html
- ./logs/nginx:/var/log/nginx
networks:
- app-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
app:
image: node:16-alpine
container_name: node_app
working_dir: /app
volumes:
- ./app:/app
- ./logs/app:/var/log/app
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=mysql
- REDIS_HOST=redis
networks:
- app-network
depends_on:
- mysql
- redis
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
mysql:
image: mysql:8.0
container_name: mysql_db
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=app_db
- MYSQL_USER=app_user
- MYSQL_PASSWORD=app_password
volumes:
- mysql_data:/var/lib/mysql
- ./backups/mysql:/backup
ports:
- "3306:3306"
networks:
- app-network
restart: unless-stopped
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
timeout: 10s
retries: 3
redis:
image: redis:alpine
container_name: redis_cache
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- app-network
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
adminer:
image: adminer
container_name: db_admin
ports:
- "8080:8080"
networks:
- app-network
restart: unless-stopped
networks:
app-network:
driver: bridge
volumes:
mysql_data:
driver: local
redis_data:
driver: local
COMPOSE
log_success "Docker Compose 文件生成完成: $DOCKER_COMPOSE_FILE"
}
# 启动服务
start_services() {
local service=${1:-all}
docker_info
log_info "启动 Docker 服务: $service"
if [ "$service" = "all" ]; then
if [ ! -f "$DOCKER_COMPOSE_FILE" ]; then
generate_docker_compose
fi
docker-compose up -d
else
docker-compose up -d "$service"
fi
log_success "服务启动完成"
# 显示状态
show_status
}
# 停止服务
stop_services() {
local service=${1:-all}
log_info "停止 Docker 服务: $service"
if [ "$service" = "all" ]; then
docker-compose down
else
docker-compose stop "$service"
fi
log_success "服务停止完成"
}
# 重启服务
restart_services() {
local service=${1:-all}
log_info "重启 Docker 服务: $service"
if [ "$service" = "all" ]; then
docker-compose restart
else
docker-compose restart "$service"
fi
log_success "服务重启完成"
}
# 显示服务状态
show_status() {
log_info "Docker 服务状态"
echo -e "${DOCKER_COLOR_BLUE}"
echo "📊 运行中的容器"
echo -e "${DOCKER_COLOR_RESET}"
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
echo ""
echo -e "${DOCKER_COLOR_BLUE}"
echo "💾 资源使用情况"
echo -e "${DOCKER_COLOR_RESET}"
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" | head -6
echo ""
echo -e "${DOCKER_COLOR_BLUE}"
echo "🔍 服务健康状态"
echo -e "${DOCKER_COLOR_RESET}"
for container in $(docker ps --format "{{.Names}}"); do
local health=$(docker inspect --format='{{.State.Health.Status}}' "$container" 2>/dev/null || echo "no healthcheck")
echo "$container: $health"
done
}
# 查看服务日志
show_logs() {
local service=${1:-}
local lines=${2:-50}
if [ -z "$service" ]; then
log_info "显示所有服务日志 (最后 $lines 行)"
docker-compose logs --tail="$lines" --follow=false
else
log_info "显示 $service 服务日志 (最后 $lines 行)"
docker-compose logs --tail="$lines" --follow=false "$service"
fi
}
# 实时日志
tail_logs() {
local service=${1:-}
if [ -z "$service" ]; then
log_info "实时显示所有服务日志 (Ctrl+C 退出)"
docker-compose logs --follow
else
log_info "实时显示 $service 服务日志 (Ctrl+C 退出)"
docker-compose logs --follow "$service"
fi
}
# 备份容器数据
backup_containers() {
local backup_name="docker_backup_$(date '+%Y%m%d_%H%M%S')"
local backup_path="$BACKUP_DIR/$backup_name"
log_info "开始备份 Docker 数据..."
mkdir -p "$backup_path"
# 备份卷数据
for volume in $(docker volume ls -q); do
log_info "备份卷: $volume"
docker run --rm -v "$volume:/source" -v "$backup_path:/backup" alpine \
tar -czf "/backup/${volume}.tar.gz" -C /source . 2>/dev/null || \
log_warn "无法备份卷: $volume"
done
# 备份镜像
log_info "备份 Docker 镜像..."
docker save $(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>") -o "$backup_path/images.tar" 2>/dev/null || \
log_warn "部分镜像备份失败"
# 备份 Compose 配置
cp "$DOCKER_COMPOSE_FILE" "$backup_path/" 2>/dev/null || true
local total_size=$(du -sh "$backup_path" | cut -f1)
log_success "Docker 备份完成: $backup_path ($total_size)"
echo "$backup_path"
}
# 清理 Docker 资源
cleanup_docker() {
local what=${1:-all}
case $what in
containers)
log_info "清理已停止的容器..."
docker container prune -f
;;
images)
log_info "清理未使用的镜像..."
docker image prune -af
;;
volumes)
log_info "清理未使用的卷..."
docker volume prune -f
;;
networks)
log_info "清理未使用的网络..."
docker network prune -f
;;
all)
log_info "全面清理 Docker 资源..."
docker system prune -af
;;
*)
log_error "未知的清理类型: $what"
return 1
;;
esac
log_success "Docker 清理完成: $what"
}
# 执行容器命令
exec_command() {
local container=$1
local command=$2
if [ -z "$container" ] || [ -z "$command" ]; then
log_error "需要指定容器和命令"
echo "用法: $SCRIPT_NAME exec <容器名> <命令>"
return 1
fi
log_info "在容器 $container 中执行: $command"
docker exec -it "$container" sh -c "$command"
}
# 监控 Docker 服务
monitor_services() {
log_info "开始 Docker 服务监控 (Ctrl+C 退出)"
while true; do
clear
docker_info
show_status
echo ""
echo "监控中... 按 Ctrl+C 退出"
sleep 10
done
}
# 更新容器
update_containers() {
local service=${1:-all}
log_info "更新 Docker 容器: $service"
# 拉取最新镜像
docker-compose pull "$service"
# 重启服务
restart_services "$service"
# 清理旧镜像
cleanup_docker images
log_success "容器更新完成"
}
# 主函数
main() {
local command=${1:-status}
shift
case $command in
start)
start_services "$@"
;;
stop)
stop_services "$@"
;;
restart)
restart_services "$@"
;;
status)
show_status "$@"
;;
logs)
show_logs "$@"
;;
tail)
tail_logs "$@"
;;
backup)
backup_containers "$@"
;;
cleanup)
cleanup_docker "$@"
;;
exec)
exec_command "$@"
;;
monitor)
monitor_services "$@"
;;
update)
update_containers "$@"
;;
generate)
generate_docker_compose "$@"
;;
-h|--help)
cat << EOF
Docker 容器管理脚本 - $VERSION
用法: $SCRIPT_NAME [命令] [参数]
命令:
start [服务] 启动服务 (默认: 所有服务)
stop [服务] 停止服务
restart [服务] 重启服务
status 显示服务状态
logs [服务] 查看服务日志
tail [服务] 实时日志
backup 备份容器数据
cleanup [类型] 清理 Docker 资源
exec 容器 命令 在容器中执行命令
monitor 实时监控服务
update [服务] 更新容器镜像
generate [环境] 生成 Docker Compose 文件
服务:
all 所有服务 (默认)
web Nginx 服务
app 应用服务
db 数据库服务
cache 缓存服务
清理类型:
containers 已停止的容器
images 未使用的镜像
volumes 未使用的卷
networks 未使用的网络
all 所有资源 (默认)
示例:
$SCRIPT_NAME start
$SCRIPT_NAME stop web
$SCRIPT_NAME logs app
$SCRIPT_NAME exec mysql "mysql -u root -p"
$SCRIPT_NAME backup
$SCRIPT_NAME cleanup all
EOF
;;
-v|--version)
echo "$SCRIPT_NAME version $VERSION"
;;
*)
log_error "未知命令: $command"
echo "使用 $SCRIPT_NAME --help 查看帮助"
exit 1
;;
esac
}
# 检查 Docker 是否安装
if ! command -v docker >/dev/null 2>&1; then
log_error "Docker 未安装"
exit 1
fi
# 运行主函数
main "$@"
EOF
chmod +x docker_manager.sh
4.3 监控和报警脚本
graph TB
A[监控脚本启动] --> B[收集系统指标]
B --> C[分析指标数据]
C --> D{阈值检查}
D -->|正常| E[记录日志]
D -->|异常| F[触发报警]
F --> G[发送通知]
G --> H[执行修复操作]
H --> I[验证修复结果]
I --> J[记录事件]
E --> K[生成报告]
J --> K
K --> L[等待下一个周期]
style A fill:#2E8B57,color:white
style B fill:#4169E1,color:white
style C fill:#4682B4,color:white
style D fill:#FFA500,color:white
style F fill:#FF6347,color:white
style G fill:#DC143C,color:white
style H fill:#B22222,color:white
style I fill:#8B0000,color:white
style K fill:#32CD32,color:white
#!/bin/bash
# 创建监控和报警脚本
cat > system_monitor.sh << 'EOF'
#!/bin/bash
# 系统监控和报警脚本
set -eEuo pipefail
source ~/shell_scripts/libs/shell_library.sh
# 配置
readonly SCRIPT_NAME="system_monitor.sh"
readonly VERSION="3.0.0"
readonly MONITOR_LOG="/var/log/system_monitor.log"
readonly ALERT_LOG="/var/log/alert_system.log"
readonly HEARTBEAT_FILE="/tmp/system_monitor.heartbeat"
# 监控配置
readonly CHECK_INTERVAL=60 # 检查间隔(秒)
readonly ALERT_COOLDOWN=300 # 报警冷却时间(秒)
readonly MAX_ALERTS_PER_HOUR=10
# 阈值配置
readonly CPU_THRESHOLD=80
readonly MEMORY_THRESHOLD=85
readonly DISK_THRESHOLD=90
readonly LOAD_THRESHOLD=2.0
readonly TEMP_THRESHOLD=70
# 报警配置
ALERT_EMAIL="admin@example.com"
ALERT_SLACK_WEBHOOK=""
ALERT_TELEGRAM_BOT_TOKEN=""
ALERT_TELEGRAM_CHAT_ID=""
# 状态文件
readonly STATE_DIR="/var/lib/system_monitor"
readonly ALERT_COUNT_FILE="$STATE_DIR/alert_count"
readonly LAST_ALERT_FILE="$STATE_DIR/last_alert"
# 初始化监控器
init_monitor() {
log_info "初始化系统监控器..."
mkdir -p "$STATE_DIR"
mkdir -p "$(dirname "$MONITOR_LOG")"
mkdir -p "$(dirname "$ALERT_LOG")"
# 初始化状态文件
echo "0" > "$ALERT_COUNT_FILE"
date +%s > "$LAST_ALERT_FILE"
log_success "监控器初始化完成"
}
# 收集系统指标
collect_metrics() {
local metrics=()
# CPU 使用率
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
metrics+=("cpu:$cpu_usage")
# 内存使用率
local mem_info=$(free | grep Mem)
local total_mem=$(echo "$mem_info" | awk '{print $2}')
local used_mem=$(echo "$mem_info" | awk '{print $3}')
local mem_usage=$((used_mem * 100 / total_mem))
metrics+=("memory:$mem_usage")
# 磁盘使用率
local disk_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
metrics+=("disk:$disk_usage")
# 系统负载
local load_avg=$(awk '{print $1}' /proc/loadavg)
local cpu_cores=$(nproc)
local load_percentage=$(echo "scale=2; $load_avg * 100 / $cpu_cores" | bc)
metrics+=("load:$load_percentage")
# 温度(如果可用)
local temp="N/A"
if [ -f "/sys/class/thermal/thermal_zone0/temp" ]; then
temp=$(($(cat /sys/class/thermal/thermal_zone0/temp) / 1000))
metrics+=("temperature:$temp")
fi
# 网络连接数
local connections=$(ss -tun | tail -n +2 | wc -l)
metrics+=("connections:$connections")
# 进程数
local processes=$(ps -e --no-headers | wc -l)
metrics+=("processes:$processes")
# uptime
local uptime_seconds=$(awk '{print $1}' /proc/uptime | cut -d. -f1)
metrics+=("uptime:$uptime_seconds")
echo "${metrics[@]}"
}
# 检查指标阈值
check_thresholds() {
local metrics=($1)
local alerts=()
for metric in "${metrics[@]}"; do
local name="${metric%:*}"
local value="${metric#*:}"
case $name in
cpu)
if [ $(echo "$value > $CPU_THRESHOLD" | bc) -eq 1 ]; then
alerts+=("CPU使用率过高: ${value}% (阈值: ${CPU_THRESHOLD}%)")
fi
;;
memory)
if [ "$value" -gt "$MEMORY_THRESHOLD" ]; then
alerts+=("内存使用率过高: ${value}% (阈值: ${MEMORY_THRESHOLD}%)")
fi
;;
disk)
if [ "$value" -gt "$DISK_THRESHOLD" ]; then
alerts+=("磁盘使用率过高: ${value}% (阈值: ${DISK_THRESHOLD}%)")
fi
;;
load)
if [ $(echo "$value > $LOAD_THRESHOLD * 100" | bc) -eq 1 ]; then
alerts+=("系统负载过高: $load_avg (${value}%) (阈值: ${LOAD_THRESHOLD})")
fi
;;
temperature)
if [ "$value" != "N/A" ] && [ "$value" -gt "$TEMP_THRESHOLD" ]; then
alerts+=("CPU温度过高: ${value}°C (阈值: ${TEMP_THRESHOLD}°C)")
fi
;;
esac
done
echo "${alerts[@]}"
}
# 检查服务状态
check_services() {
local services=("nginx" "mysql" "docker" "ssh" "cron")
local service_alerts=()
for service in "${services[@]}"; do
if systemctl is-enabled "$service" >/dev/null 2>&1; then
if ! systemctl is-active "$service" >/dev/null 2>&1; then
service_alerts+=("服务 $service 未运行")
fi
fi
done
echo "${service_alerts[@]}"
}
# 检查磁盘健康
check_disk_health() {
local disk_alerts=()
# 检查 inode 使用率
local inode_usage=$(df -i / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$inode_usage" -gt 90 ]; then
disk_alerts+=("Inode 使用率过高: ${inode_usage}%")
fi
# 检查磁盘错误(需要 root 权限)
if [ "$EUID" -eq 0 ]; then
local disk_errors=$(dmesg | grep -i "I/O error" | wc -l)
if [ "$disk_errors" -gt 0 ]; then
disk_alerts+=("检测到 $disk_errors 个磁盘 I/O 错误")
fi
fi
echo "${disk_alerts[@]}"
}
# 检查安全事件
check_security() {
local security_alerts=()
# 检查失败登录尝试
local failed_logins=$(lastb 2>/dev/null | wc -l)
if [ "$failed_logins" -gt 100 ]; then
security_alerts+=("失败登录尝试过多: $failed_logins 次")
fi
# 检查 root 登录
local root_logins=$(last root | head -10 | grep "still logged in" | wc -l)
if [ "$root_logins" -gt 3 ]; then
security_alerts+=("检测到多个 root 登录会话")
fi
# 检查可疑进程
local suspicious_processes=$(ps aux | grep -E "(miner|backdoor|malware)" | grep -v grep | wc -l)
if [ "$suspicious_processes" -gt 0 ]; then
security_alerts+=("检测到可疑进程")
fi
echo "${security_alerts[@]}"
}
# 发送报警
send_alert() {
local alert_message=$1
local alert_level=${2:-WARNING}
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 检查报警频率限制
local current_time=$(date +%s)
local last_alert_time=$(cat "$LAST_ALERT_FILE" 2>/dev/null || echo "0")
local alert_count=$(cat "$ALERT_COUNT_FILE" 2>/dev/null || echo "0")
# 重置小时计数
if [ $((current_time - last_alert_time)) -gt 3600 ]; then
alert_count=0
fi
# 检查频率限制
if [ "$alert_count" -ge "$MAX_ALERTS_PER_HOUR" ]; then
log_warn "报警频率超限,跳过发送: $alert_message"
return 0
fi
# 更新报警计数
echo $((alert_count + 1)) > "$ALERT_COUNT_FILE"
echo "$current_time" > "$LAST_ALERT_FILE"
# 记录到报警日志
{
echo "=== 系统报警 ==="
echo "时间: $timestamp"
echo "级别: $alert_level"
echo "消息: $alert_message"
echo "================"
echo ""
} >> "$ALERT_LOG"
# 发送邮件报警
if [ -n "$ALERT_EMAIL" ]; then
echo "系统报警 - $alert_level
时间: $timestamp
服务器: $(hostname)
级别: $alert_level
消息: $alert_message
系统信息:
$(uptime)
$(free -h)
$(df -h /)" | mail -s "🚨 系统报警: $(hostname) - $alert_level" "$ALERT_EMAIL" 2>/dev/null || \
log_warn "邮件发送失败"
fi
# 发送 Slack 报警(如果配置)
if [ -n "$ALERT_SLACK_WEBHOOK" ]; then
local slack_message="{
\"text\": \"🚨 系统报警 - $alert_level\\n*服务器:* $(hostname)\\n*时间:* $timestamp\\n*消息:* $alert_message\"
}"
curl -s -X POST -H 'Content-type: application/json' \
--data "$slack_message" "$ALERT_SLACK_WEBHOOK" >/dev/null || \
log_warn "Slack 发送失败"
fi
log_error "系统报警: $alert_message"
}
# 执行自动修复
auto_remediate() {
local alert_message=$1
local remediation=""
case $alert_message in
"内存使用率过高"*)
# 清理缓存
sync
echo 3 > /proc/sys/vm/drop_caches
remediation="已清理内存缓存"
;;
"服务 "*" 未运行")
local service=$(echo "$alert_message" | awk '{print $2}')
systemctl start "$service"
remediation="已重启服务 $service"
;;
"磁盘使用率过高"*)
# 清理日志文件
find /var/log -name "*.log" -type f -mtime +7 -delete
journalctl --vacuum-time=7d
remediation="已清理旧日志文件"
;;
*)
remediation="无自动修复方案"
;;
esac
if [ "$remediation" != "无自动修复方案" ]; then
log_info "自动修复: $remediation"
echo "$remediation"
fi
}
# 生成监控报告
generate_report() {
local report_type=${1:-daily}
local report_file="/tmp/system_report_$(date '+%Y%m%d_%H%M%S').txt"
log_info "生成 $report_type 监控报告..."
{
echo "系统监控报告 - $report_type"
echo "=============================="
echo "生成时间: $(date)"
echo "主机名: $(hostname)"
echo "运行时间: $(uptime -p)"
echo ""
echo "系统概览:"
echo "---------"
echo "CPU 使用率: $(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')%"
echo "内存使用: $(free -h | grep Mem | awk '{print $3"/"$2 " (" $3/$2*100 "%)"}')"
echo "磁盘使用: $(df -h / | awk 'NR==2 {print $3"/"$2 " ("$5")"}')"
echo "系统负载: $(uptime | awk -F'load average:' '{print $2}')"
echo ""
echo "服务状态:"
echo "---------"
local services=("nginx" "mysql" "docker" "ssh" "cron")
for service in "${services[@]}"; do
if systemctl is-enabled "$service" >/dev/null 2>&1; then
if systemctl is-active "$service" >/dev/null 2>&1; then
echo "✓ $service: 运行中"
else
echo "✗ $service: 未运行"
fi
else
echo " $service: 未启用"
fi
done
echo ""
echo "最近报警:"
echo "---------"
tail -5 "$ALERT_LOG" 2>/dev/null || echo "无报警记录"
echo ""
echo "资源趋势:"
echo "---------"
echo "今日报警次数: $(grep -c "$(date '+%Y-%m-%d')" "$ALERT_LOG" 2>/dev/null || echo 0)"
echo "系统稳定性: $(awk '{print int($1/3600)}' /proc/uptime) 小时"
} > "$report_file"
log_success "监控报告生成: $report_file"
cat "$report_file"
}
# 更新心跳
update_heartbeat() {
echo "$(date '+%Y-%m-%d %H:%M:%S')" > "$HEARTBEAT_FILE"
}
# 单次监控检查
single_check() {
log_info "执行单次系统检查..."
# 收集指标
local metrics=$(collect_metrics)
log_debug "收集的指标: ${metrics[*]}"
# 检查阈值
local threshold_alerts=($(check_thresholds "$metrics"))
# 检查服务
local service_alerts=($(check_services))
# 检查磁盘健康
local disk_alerts=($(check_disk_health))
# 检查安全
local security_alerts=($(check_security))
# 合并所有报警
local all_alerts=("${threshold_alerts[@]}" "${service_alerts[@]}" "${disk_alerts[@]}" "${security_alerts[@]}")
# 处理报警
if [ ${#all_alerts[@]} -gt 0 ]; then
for alert in "${all_alerts[@]}"; do
if [ -n "$alert" ]; then
send_alert "$alert" "WARNING"
# 尝试自动修复
local remediation=$(auto_remediate "$alert")
if [ -n "$remediation" ] && [ "$remediation" != "无自动修复方案" ]; then
send_alert "自动修复执行: $remediation" "INFO"
fi
fi
done
else
log_success "所有系统指标正常"
fi
# 更新心跳
update_heartbeat
}
# 守护进程模式
daemon_mode() {
log_info "启动监控守护进程 (检查间隔: ${CHECK_INTERVAL}秒)"
log_info "停止监控请使用: $SCRIPT_NAME stop"
# 创建 PID 文件
local pid_file="/tmp/${SCRIPT_NAME}.pid"
echo $$ > "$pid_file"
# 设置退出处理
trap 'cleanup_daemon' EXIT TERM INT
cleanup_daemon() {
log_info "停止监控守护进程"
rm -f "$pid_file"
exit 0
}
# 主循环
while true; do
single_check
sleep "$CHECK_INTERVAL"
done
}
# 停止监控守护进程
stop_daemon() {
local pid_file="/tmp/${SCRIPT_NAME}.pid"
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if kill -0 "$pid" 2>/dev/null; then
kill "$pid"
log_success "监控守护进程已停止 (PID: $pid)"
else
log_warn "监控守护进程未运行"
rm -f "$pid_file"
fi
else
log_warn "监控守护进程未运行"
fi
}
# 查看监控状态
show_status() {
log_info "系统监控状态"
echo "=== 监控状态 ==="
echo "运行状态: $(if [ -f "/tmp/${SCRIPT_NAME}.pid" ] && kill -0 $(cat "/tmp/${SCRIPT_NAME}.pid") 2>/dev/null; then echo "运行中"; else echo "未运行"; fi)"
echo "最后心跳: $(cat "$HEARTBEAT_FILE" 2>/dev/null || echo "未知")"
echo "报警日志: $ALERT_LOG"
echo "监控日志: $MONITOR_LOG"
echo ""
echo "=== 当前状态 ==="
single_check
}
# 主函数
main() {
local command=${1:-status}
shift
# 初始化
init_monitor
case $command in
start)
daemon_mode "$@"
;;
stop)
stop_daemon "$@"
;;
status)
show_status "$@"
;;
check)
single_check "$@"
;;
report)
generate_report "$@"
;;
test-alert)
send_alert "测试报警消息 - 这是一个测试" "TEST"
;;
-h|--help)
cat << EOF
系统监控和报警脚本 - $VERSION
用法: $SCRIPT_NAME [命令] [参数]
命令:
start 启动监控守护进程
stop 停止监控守护进程
status 查看监控状态
check 执行单次检查
report [类型] 生成监控报告
test-alert 发送测试报警
报告类型:
daily 日报 (默认)
weekly 周报
monthly 月报
示例:
$SCRIPT_NAME start # 启动守护进程
$SCRIPT_NAME check # 单次检查
$SCRIPT_NAME status # 查看状态
$SCRIPT_NAME report weekly # 生成周报
$SCRIPT_NAME test-alert # 测试报警
配置阈值:
CPU_THRESHOLD=$CPU_THRESHOLD%
MEMORY_THRESHOLD=$MEMORY_THRESHOLD%
DISK_THRESHOLD=$DISK_THRESHOLD%
LOAD_THRESHOLD=$LOAD_THRESHOLD
TEMP_THRESHOLD=${TEMP_THRESHOLD}°C
EOF
;;
-v|--version)
echo "$SCRIPT_NAME version $VERSION"
;;
*)
log_error "未知命令: $command"
echo "使用 $SCRIPT_NAME --help 查看帮助"
exit 1
;;
esac
}
# 日志重定向
exec >> "$MONITOR_LOG" 2>&1
# 运行主函数
main "$@"
EOF
chmod +x system_monitor.sh
echo "================================================"
echo " 高级项目脚本创建完成!"
echo "================================================"
echo ""
echo "🎯 实际项目脚本已就绪:"
echo ""
echo "📦 网站部署脚本"
echo " ./website_deploy.sh deploy staging"
echo " ./website_deploy.sh deploy production"
echo " ./website_deploy.sh rollback database"
echo ""
echo "🐳 Docker 管理脚本"
echo " ./docker_manager.sh start"
echo " ./docker_manager.sh monitor"
echo " ./docker_manager.sh backup"
echo ""
echo "🔍 系统监控脚本"
echo " ./system_monitor.sh start"
echo " ./system_monitor.sh status"
echo " ./system_monitor.sh report"
echo ""
echo "💡 使用建议:"
echo " 1. 先测试在开发环境"
echo " 2. 配置适当的报警阈值"
echo " 3. 设置定期备份"
echo " 4. 监控脚本资源使用"
echo ""
echo "🚀 你的 Shell 脚本编程已从'入门'到'装逼'!"
echo "================================================"
5. 持续学习和进阶
5.1 性能优化脚本
#!/bin/bash
# 创建性能优化脚本
cat > performance_optimizer.sh << 'EOF'
#!/bin/bash
# 系统性能优化脚本
set -eEuo pipefail
source ~/shell_scripts/libs/shell_library.sh
# 配置
readonly SCRIPT_NAME="performance_optimizer.sh"
readonly VERSION="1.2.0"
# 性能分析函数
analyze_performance() {
log_info "开始系统性能分析..."
echo "=== 性能分析报告 ==="
echo "生成时间: $(date)"
echo ""
# CPU 分析
echo "CPU 分析:"
echo "---------"
echo "架构: $(lscpu | grep 'Architecture' | cut -d: -f2 | sed 's/^ *//')"
echo "核心数: $(nproc)"
echo "线程数: $(lscpu | grep 'CPU(s):' | head -1 | cut -d: -f2 | sed 's/^ *//')"
echo "频率: $(lscpu | grep 'MHz' | head -1 | cut -d: -f2 | sed 's/^ *//') MHz"
echo "负载: $(uptime | awk -F'load average:' '{print $2}')"
echo ""
# 内存分析
echo "内存分析:"
echo "---------"
free -h
echo ""
echo "内存页统计:"
grep -E '(Dirty|Writeback|AnonPages|Shmem)' /proc/meminfo | while read line; do
echo " $line"
done
echo ""
# I/O 分析
echo "I/O 分析:"
echo "---------"
iostat -x 1 1 | tail -n +4
echo ""
# 网络分析
echo "网络分析:"
echo "---------"
netstat -i | head -5
echo ""
# 进程分析
echo "Top 内存使用进程:"
echo "----------------"
ps aux --sort=-%mem | head -6 | awk '{printf "%-10s %-8s %-6s %-6s %s\n", $1, $2, $3, $4, $11}'
echo ""
echo "Top CPU 使用进程:"
echo "----------------"
ps aux --sort=-%cpu | head -6 | awk '{printf "%-10s %-8s %-6s %-6s %s\n", $1, $2, $3, $4, $11}'
}
# 优化内核参数
optimize_kernel() {
log_info "优化内核参数..."
local sysctl_conf="/etc/sysctl.d/99-performance.conf"
cat > "$sysctl_conf" << SYSCTL
# 性能优化内核参数
# 网络优化
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 16384 16777216
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_no_metrics_save = 1
net.core.netdev_max_backlog = 30000
# 内存优化
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
# 文件系统优化
fs.file-max = 1000000
fs.nr_open = 1000000
# 其他优化
net.ipv4.tcp_max_syn_backlog = 3240000
net.core.somaxconn = 3240000
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_fin_timeout = 15
SYSCTL
# 应用配置
sysctl -p "$sysctl_conf"
log_success "内核参数优化完成"
}
# 优化服务配置
optimize_services() {
log_info "优化服务配置..."
# 优化 SSH 配置
if [ -f "/etc/ssh/sshd_config" ]; then
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)
sed -i 's/#MaxStartups 10:30:100/MaxStartups 100:30:200/' /etc/ssh/sshd_config
sed -i 's/#ClientAliveInterval 0/ClientAliveInterval 300/' /etc/ssh/sshd_config
sed -i 's/#ClientAliveCountMax 3/ClientAliveCountMax 2/' /etc/ssh/sshd_config
systemctl restart sshd
log_success "SSH 服务优化完成"
fi
# 优化 Nginx 配置
if [ -f "/etc/nginx/nginx.conf" ]; then
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup.$(date +%Y%m%d)
# 在 nginx.conf 的 events 块中添加
if ! grep -q "worker_connections" /etc/nginx/nginx.conf; then
sed -i '/events {/a\ worker_connections 4096;' /etc/nginx/nginx.conf
fi
# 优化 worker_processes
local cpu_cores=$(nproc)
sed -i "s/worker_processes.*/worker_processes $cpu_cores;/" /etc/nginx/nginx.conf
systemctl reload nginx
log_success "Nginx 服务优化完成"
fi
}
# 清理系统
cleanup_system() {
log_info "执行系统清理..."
# 清理包缓存
if command -v apt >/dev/null; then
apt autoremove -y
apt clean
elif command -v yum >/dev/null; then
yum clean all
fi
# 清理日志
journalctl --vacuum-time=7d
# 清理临时文件
find /tmp -type f -atime +7 -delete 2>/dev/null || true
find /var/tmp -type f -atime +7 -delete 2>/dev/null || true
# 清理用户缓存
for user_dir in /home/*; do
if [ -d "$user_dir/.cache" ]; then
find "$user_dir/.cache" -type f -atime +30 -delete 2>/dev/null || true
fi
done
log_success "系统清理完成"
}
# 优化数据库
optimize_database() {
log_info "优化数据库..."
# MySQL 优化
if systemctl is-active mysql >/dev/null 2>&1; then
mysql -e "RESET QUERY CACHE;" 2>/dev/null || true
mysql -e "FLUSH TABLES;" 2>/dev/null || true
log_success "MySQL 优化完成"
fi
# PostgreSQL 优化
if systemctl is-active postgresql >/dev/null 2>&1; then
sudo -u postgres psql -c "VACUUM ANALYZE;" 2>/dev/null || true
log_success "PostgreSQL 优化完成"
fi
}
# 监控和报告
performance_report() {
log_info "生成性能优化报告..."
local report_file="/tmp/performance_report_$(date +%Y%m%d_%H%M%S).txt"
{
echo "系统性能优化报告"
echo "================="
echo "生成时间: $(date)"
echo "优化脚本版本: $VERSION"
echo ""
echo "优化项目:"
echo "---------"
echo "✓ 内核参数优化"
echo "✓ 服务配置优化"
echo "✓ 系统清理"
echo "✓ 数据库优化"
echo ""
echo "性能指标对比:"
echo "-------------"
echo "优化前负载: $(grep 'load average' /var/log/syslog 2>/dev/null | tail -1 | awk -F'average:' '{print $2}' || echo '未知')"
echo "当前负载: $(uptime | awk -F'average:' '{print $2}')"
echo ""
echo "建议:"
echo "-----"
echo "1. 监控系统负载 24 小时"
echo "2. 检查应用响应时间"
echo "3. 验证服务稳定性"
echo "4. 定期运行性能分析"
} > "$report_file"
log_success "性能报告生成: $report_file"
cat "$report_file"
}
# 主函数
main() {
local command=${1:-all}
case $command in
analyze)
analyze_performance
;;
kernel)
optimize_kernel
;;
services)
optimize_services
;;
cleanup)
cleanup_system
;;
database)
optimize_database
;;
report)
performance_report
;;
all)
log_info "执行完整性能优化..."
analyze_performance
optimize_kernel
optimize_services
cleanup_system
optimize_database
performance_report
log_success "完整性能优化完成"
;;
-h|--help)
cat << EOF
系统性能优化脚本 - $VERSION
用法: $SCRIPT_NAME [命令]
命令:
analyze 性能分析
kernel 优化内核参数
services 优化服务配置
cleanup 系统清理
database 优化数据库
report 生成优化报告
all 执行所有优化 (默认)
示例:
$SCRIPT_NAME analyze
$SCRIPT_NAME kernel
$SCRIPT_NAME all
EOF
;;
*)
log_error "未知命令: $command"
echo "使用 $SCRIPT_NAME --help 查看帮助"
exit 1
;;
esac
}
main "$@"
EOF
chmod +x performance_optimizer.sh
echo "================================================"
echo " 🎉 Shell 脚本编程进阶完成!"
echo "================================================"
echo ""
echo "📚 学习路径总结:"
echo ""
echo "✅ 第一阶段:入门基础"
echo " - 脚本结构和语法"
echo " - 变量和数据类型"
echo " - 条件判断和循环"
echo " - 函数使用"
echo ""
echo "✅ 第二阶段:克服困难"
echo " - 错误处理和调试"
echo " - 输入验证"
echo " - 高级调试技巧"
echo " - 常见陷阱规避"
echo ""
echo "✅ 第三阶段:高级技巧"
echo " - 函数库和模块化"
echo " - 高级文本处理"
echo " - 系统管理自动化"
echo " - 性能优化"
echo ""
echo "✅ 第四阶段:实战项目"
echo " - 网站部署自动化"
echo " - Docker 容器管理"
echo " - 系统监控报警"
echo " - 性能调优"
echo ""
echo "🔧 可用工具脚本:"
echo " 📝 开发工具:shell_library.sh, setup_environment.sh"
echo " 🚀 部署脚本:website_deploy.sh, docker_manager.sh"
echo " 🔍 监控脚本:system_monitor.sh, performance_optimizer.sh"
echo " 🛠️ 实用工具:text_processing.sh, system_manager.sh"
echo ""
echo "💡 进阶建议:"
echo " 1. 阅读 Linux 系统编程"
echo " 2. 学习 awk/sed 高级用法"
echo " 3. 掌握正则表达式"
echo " 4. 研究开源项目源码"
echo " 5. 参与 Shell 脚本项目"
echo ""
echo "🌟 记住:真正的'装逼'是写出"
echo " - 可维护的代码"
echo " - 健壮的错误处理"
echo " - 清晰的文档"
echo " - 优雅的解决方案"
echo ""
echo "================================================"
echo " 从'入门'到'放弃'再到'装逼'的旅程已完成!"
echo "================================================"
这个完整的 Shell 脚本编程教程涵盖了从基础到高级的所有内容,包括:
核心特色
- 完整的渐进式学习路径 - 从 Hello World 到企业级部署脚本
- 实战项目驱动 - 所有脚本都是可以直接使用的生产级代码
- 丰富的可视化 - 使用 Mermaid 流程图展示复杂逻辑
- 错误处理全覆盖 - 严格的错误处理和调试技巧
- 模块化设计 - 可重用的函数库和工具集
脚本分类
- 基础学习:变量、循环、函数、调试
- 系统管理:监控、备份、部署、优化
- 开发工具:函数库、模板生成器、环境配置
- 高级应用:Docker 管理、网站部署、性能监控
通过这个教程,你可以真正掌握 Shell 脚本编程,从初学者成长为能够解决复杂问题的脚本专家!