当前位置:首页>Linux>Linux从零部署实战指南(五):性能优化、监控与日志(完结篇)

Linux从零部署实战指南(五):性能优化、监控与日志(完结篇)

  • 2026-09-09 18:01:57
Linux从零部署实战指南(五):性能优化、监控与日志(完结篇)

Linux 从零部署项目实战指南(五):性能优化、监控与日志(完结篇)

本系列面向零基础或初中级开发者,手把手教你将一个项目从零部署到 Linux 服务器,并解决过程中遇到的常见问题。


一、前言

前四篇文章我们完成了从服务器选购到应用上线的完整流程。但部署上线只是开始,后续的运维同样重要。

本篇目标:掌握服务器性能监控、日志管理、安全加固三大核心运维技能,成为能独立管理服务器的开发者。


二、服务器性能监控

2.1 监控什么?

运维监控的核心指标,可以概括为 CPU、内存、磁盘、网络 四大维度:

┌─────────────────────────────────────────────────────────┐│                    服务器监控仪表盘                        │├──────────────┬──────────────┬──────────────┬──────────────┤│   CPU 使用率  │   内存占用    │   磁盘空间    │   网络流量    ││   ████████░░  │  ████████░░  │  ████████░░  │  ████████░░  ││   78%         │   3.2G/4G    │   45G/60G    │   5Mbps      ││  正常         │  正常        │  正常        │  正常        │├──────────────┴──────────────┴──────────────┴──────────────┤│  进程数: 245  │  运行时间: 15天  │  负载: 1.2    │  状态: ✅  │└───────────────────────────────────────────────────────────┘

2.2 命令行实时监控

# ========== CPU 和内存(实时刷新) ==========top# 按 q 退出# 常用快捷键:#   1 — 查看每个 CPU 核心的负载#   P — 按 CPU 使用率排序#   M — 按内存使用率排序#   c — 显示完整命令路径# htop(更友好的 top,需要安装)sudo apt install -y htophtop# ========== 磁盘空间 ==========df -h# 查看各分区使用情况,重点关注 / 和 /data 的使用率# 查看目录大小du -sh /home/wwwdu -sh /var/logdu -sh /data# 按大小排序查看前 10 的大目录du -sh /* 2>/dev/null | sort -rh | head -10# ========== 内存 ==========free -h# 输出中 -/+ buffers/cache 那一行才是实际使用量# available 列是可用内存(包括缓存可回收部分)# ========== 网络流量 ==========# 查看网络接口流量ip -s link# 或使用 nload(需要安装)sudo apt install -y nloadnload# ========== 磁盘 I/O ==========sudo apt install -y iotopsudo iotop -o# -o 参数只显示正在 I/O 的进程# ========== 系统负载 ==========uptime# 输出示例:10:00:00 up 15 days, 3:20, 2 users, load average: 0.08, 0.03, 0.01# load average 的三个值分别代表 1分钟、5分钟、15分钟的平均负载# 负载值超过 CPU 核心数时说明系统过载

2.3 安装 Netdata 可视化监控

Netdata 是一个开源的实时监控工具,安装后通过浏览器访问,可以看到精美的仪表盘:

# 一键安装 Netdatabash <(curl -Ss https://my-netdata.io/kickstart.sh)# 安装完成后,Netdata 会监听在 19999 端口# 访问:http://yourdomain.com:19999# 配置 Nginx 反向代理(可选,建议放在内网或加密码)sudo tee /etc/nginx/sites-available/netdata << 'EOF'server {    listen 8080;    server_name _;    location / {        proxy_pass http://127.0.0.1:19999;        proxy_set_header Host $host;        proxy_set_header X-Real-IP $remote_addr;        # 添加简单密码认证(需要安装 apache2-utils)        # auth_basic "Netdata Monitor";        # auth_basic_user_file /etc/nginx/.htpasswd;    }}EOF# 如果不想暴露到公网,只允许本机访问sudo ufw allow from 127.0.0.1 to any port 19999

2.4 使用 Prometheus + Node Exporter 监控

对于更专业的监控方案,推荐 Prometheus 生态:

# 安装 Node Exporter(收集系统指标)sudo useradd --no-create-home --shell /bin/false node_exporterwget https://github.com/prometheus/node_exporter/releases/latest/download/node_exporter-*.linux-amd64.tar.gztar xzf node_exporter-*.linux-amd64.tar.gzsudo cp node_exporter-*/node_exporter /usr/local/bin/sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter# 创建 systemd 服务sudo tee /etc/systemd/system/node_exporter.service << 'EOF'[Unit]Description=Node ExporterAfter=network.target[Service]User=node_exporterGroup=node_exporterType=simpleExecStart=/usr/local/bin/node_exporter[Install]WantedBy=multi-user.targetEOF# 启动 Node Exportersudo systemctl daemon-reloadsudo systemctl start node_exportersudo systemctl enable node_exporter# 验证(默认监听 9100 端口)curl http://localhost:9100/metrics | head -20

2.5 设置资源告警阈值

掌握服务器资源的"红线"在哪里,对运维至关重要:

CPU 使用率:  正常: < 70%  警告: 70% - 90%  危险: > 90%(持续 5 分钟以上)内存使用率:  正常: < 70%  警告: 70% - 85%  危险: > 85%(开始使用 Swap,性能下降)磁盘使用率:  正常: < 70%  警告: 70% - 85%  危险: > 85%(需要立即清理或扩容)系统负载(Load Average):  正常: < CPU 核心数 × 0.7  警告: CPU 核心数 × 0.7 - 1.0  危险: > CPU 核心数(请求排队,响应变慢)

三、日志管理

3.1 日志分类

Linux 服务器上常见的日志:

/var/log/├── syslog              # 系统日志(Ubuntu 默认)├── auth.log            # 认证日志(SSH 登录记录)├── kern.log            # 内核日志├── nginx/│   ├── access.log      # Nginx 访问日志│   └── error.log       # Nginx 错误日志├── mysql/│   └── error.log       # MySQL 错误日志├── redis/│   └── redis-server.log # Redis 日志└── myproject/           # 项目日志    ├── app.log          # 应用日志    └── access.log       # 应用访问日志

3.2 日志查看技巧

# 实时查看日志(最常用)sudo tail -f /var/log/nginx/access.log# 查看最近 100 行sudo tail -n 100 /var/log/nginx/error.log# 查看今天的日志sudo journalctl -u mywebapi --since today# 查看特定时间段的日志sudo journalctl -u mywebapi --since "2026-07-28 10:00:00" --until "2026-07-28 12:00:00"# 模糊搜索日志sudo grep "ERROR" /var/log/nginx/error.logsudo grep -r "500" /var/log/nginx/# 统计错误次数sudo grep "ERROR" /var/log/nginx/error.log | wc -l# 统计 IP 访问次数(排错时很有用)sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10# 输出示例:# 12345 123.123.123.123  ← 这个 IP 访问了 12345 次(可能是在攻击)# 567   192.168.1.100# 234   10.0.0.1# 统计 HTTP 状态码sudo awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn# 输出示例:# 9876 200  ← 正常# 123  404  ← 页面不存在# 45   500  ← 服务器错误# 12   502  ← 网关错误

3.3 日志轮转(防止日志撑爆磁盘)

日志文件会不断增长,必须配置日志轮转(logrotate)自动切割和清理旧日志:

# 查看系统的 logrotate 配置ls -la /etc/logrotate.d/# 添加项目日志的轮转配置sudo tee /etc/logrotate.d/myproject << 'EOF'/home/www/myproject/logs/*.log {    daily                    # 每天轮转一次    rotate 7                 # 保留最近 7 天的日志    compress                 # 压缩旧日志(.gz)    delaycompress            # 压缩延期一天,方便查看昨天的日志    missingok                # 如果日志文件不存在,不报错    notifempty               # 如果日志为空,不轮转    copytruncate             # 复制并截断原文件(不影响正在写入的进程)    dateext                  # 在文件名中添加日期    dateformat -%Y%m%d       # 日期格式}EOF# 手动测试 logrotate 配置sudo logrotate -d /etc/logrotate.d/myproject# -d 是调试模式,不会实际执行# 强制执行sudo logrotate -f /etc/logrotate.d/myproject# 查看 logrotate 执行状态sudo cat /var/lib/logrotate/status

3.4 使用 journalctl 管理 systemd 日志

# 查看应用日志sudo journalctl -u mywebapi# 实时查看sudo journalctl -u mywebapi -f# 查看最近 100 行sudo journalctl -u mywebapi -n 100# 限制日志大小(防止日志占用过多磁盘)sudo journalctl --vacuum-size=500M    # 保留最近 500MB 日志sudo journalctl --vacuum-time=30d     # 保留最近 30 天的日志# 永久限制日志大小sudo vim /etc/systemd/journald.conf# 修改以下行:SystemMaxUse=500M           # 日志最大占用 500MBMaxFileSec=30               # 日志文件最大保留 30 天# 重启 journald 服务sudo systemctl restart systemd-journald

四、性能优化

4.1 系统层面优化

# 优化 swappiness(减少磁盘交换,提升响应速度)echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.confsudo sysctl -p# 优化文件描述符限制echo 'fs.file-max=100000' | sudo tee -a /etc/sysctl.confsudo sysctl -p# 禁用不必要的服务(释放资源)sudo systemctl list-unit-files --state=enabled | grep -E 'bluetooth|avahi|cups'# 以下服务如果不需要可以禁用sudo systemctl disable bluetooth  # 服务器不需要蓝牙sudo systemctl disable avahi-daemon  # 不需要零配置网络sudo systemctl disable cups  # 不需要打印服务

4.2 Nginx 优化

# 编辑 /etc/nginx/nginx.confsudo vim /etc/nginx/nginx.conf
# 工作进程数 = CPU 核心数worker_processes auto;# 每个进程的最大连接数worker_connections 1024;# 使用 epoll(Linux 高性能 I/O)events {    use epoll;    multi_accept on;}# 开启 gzip 压缩gzip on;gzip_min_length 1000;gzip_comp_level 5;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;gzip_vary on;gzip_proxied any;# 开启静态文件缓存# 在站点配置中:location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {    expires 30d;    add_header Cache-Control "public, immutable";    access_log off;}# 开启 HTTP/2(需要 HTTPS)# 在 server 块中添加:listen 443 ssl http2;
# 测试配置并重载sudo nginx -t && sudo systemctl reload nginx

4.3 MySQL 优化

# 使用 MySQLTuner 工具分析数据库性能wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.plperl mysqltuner.pl --user root --pass 你的数据库密码

根据 MySQLTuner 的推荐,调整 MySQL 配置:

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
# 根据服务器内存调整(2G 服务器推荐值)# InnoDB 缓冲池大小(最重要的参数,建议总内存的 50%)innodb_buffer_pool_size = 1G# 日志文件大小innodb_log_file_size = 256M# 最大连接数(根据应用需求调整)max_connections = 100# 连接超时(单位:秒)wait_timeout = 600interactive_timeout = 600# 表缓存table_open_cache = 2000# 临时表大小tmp_table_size = 64Mmax_heap_table_size = 64M
# 重启 MySQLsudo systemctl restart mysql

4.4 Redis 优化

# 编辑 /etc/redis/redis.confsudo vim /etc/redis/redis.conf
# 内存限制maxmemory 512mb# 淘汰策略(推荐 allkeys-lru)maxmemory-policy allkeys-lru# 关闭 RDB 持久化(如果只做缓存,不需要持久化)# save ""  # 注释掉所有 save 选项# 或者保留 AOF 但调整频率appendfsync everysecno-appendfsync-on-rewrite yes
# 重启 Redissudo systemctl restart redis-server

4.5 .NET 应用优化

# 在 Program.cs 中添加性能配置
var builder = WebApplication.CreateBuilder(args);// 配置 Kestrel 服务器builder.WebHost.ConfigureKestrel(options =>{    // 最大并发连接数    options.Limits.MaxConcurrentConnections = 100;    options.Limits.MaxConcurrentUpgradedConnections = 100;    // 请求体大小限制(按需调整)    options.Limits.MaxRequestBodySize = 100 * 1024 * 1024; // 100MB    // 保持连接超时    options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);});// 启用响应压缩builder.Services.AddResponseCompression(options =>{    options.EnableForHttps = true;    options.Providers.Add<BrotliCompressionProvider>();    options.Providers.Add<GzipCompressionProvider>();});// 配置 JSON 序列化builder.Services.ConfigureHttpJsonOptions(options =>{    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;    options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;});

五、安全加固

5.1 安全基线检查清单

# ========== 1. 检查是否有未授权的用户 ==========cat /etc/passwd | grep -E "/bin/bash|/bin/sh"# 确认所有用户都是你创建的,没有可疑用户# ========== 2. 检查 sudo 权限 ==========sudo cat /etc/sudoers | grep -E "^[^#]"# 确认只有必要用户有 sudo 权限# ========== 3. 检查 SSH 配置 ==========sudo cat /etc/ssh/sshd_config | grep -E "^(PermitRootLogin|PasswordAuthentication|Port|PubkeyAuthentication)"# 确认:#   PermitRootLogin no(禁止 root 直接登录)#   PasswordAuthentication no(禁用密码登录)#   PubkeyAuthentication yes(仅允许密钥登录)# ========== 4. 检查防火墙规则 ==========sudo ufw status verbose# 确认只开放了必要端口# ========== 5. 检查监听端口 ==========sudo ss -tlnp# 确认没有未授权的端口在监听# ========== 6. 检查 Fail2ban 状态 ==========sudo fail2ban-client status sshd# 查看被封禁的 IP 数量# ========== 7. 检查系统更新 ==========sudo apt list --upgradable# 如果有安全更新,及时安装sudo apt upgrade -y

5.2 自动安全扫描

# 安装 Lynis 安全审计工具sudo apt install -y lynis# 执行安全审计sudo lynis audit system# 查看审计报告sudo lynis show details

5.3 配置自动备份

除了数据库备份,还要备份配置文件和项目代码:

# 创建完整的备份脚本sudo tee /usr/local/bin/backup-all.sh << 'EOF'#!/bin/bashBACKUP_DIR="/data/backup"DATE=$(date +%Y%m%d_%H%M%S)# 1. 备份 MySQL 数据库echo "[1/3] 备份数据库..."mysqldump -u myapp -pYourAppPassword2024! myproject_db | \  gzip > $BACKUP_DIR/db/myproject_db_$DATE.sql.gz# 2. 备份 Nginx 配置echo "[2/3] 备份 Nginx 配置..."tar czf $BACKUP_DIR/config/nginx-config_$DATE.tar.gz /etc/nginx/# 3. 备份项目代码echo "[3/3] 备份项目代码..."tar czf $BACKUP_DIR/code/myproject-source_$DATE.tar.gz /home/www/myproject/source# 4. 删除 30 天前的旧备份echo "清理旧备份..."find $BACKUP_DIR -name "*.gz" -mtime +30 -deleteecho "备份完成: $DATE"EOFsudo chmod +x /usr/local/bin/backup-all.sh# 配置定时任务:每天凌晨 2 点执行sudo crontab -e# 添加:0 2 * * * /usr/local/bin/backup-all.sh >> /var/log/backup-all.log 2>&1

5.4 监控关键文件变化

使用 AIDE(Advanced Intrusion Detection Environment)监控关键文件是否被篡改:

# 安装 AIDEsudo apt install -y aide# 初始化数据库sudo aideinit# 移动数据库到默认位置sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db# 运行检查(对比文件状态)sudo aide --check# 配置定时检查(每天凌晨 4 点)sudo crontab -e# 添加:0 4 * * * /usr/bin/aide --check | mail -s "AIDE Report" admin@yourdomain.com

六、系统健康检查脚本

创建一个一键检查脚本,可以快速了解服务器整体状态:

sudo tee /usr/local/bin/health-check.sh << 'EOF'#!/bin/bash# ==========================================# 服务器健康检查脚本# 用法:sudo bash health-check.sh# ==========================================RED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[1;33m'NC='\033[0m'echo "=========================================="echo "      服务器健康检查报告"echo "      时间:$(date)"echo "=========================================="# CPU 检查echo -n "CPU 使用率: "CPU=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')echo "$CPU%"if (( $(echo "$CPU > 80" | bc -l) )); then    echo -e "  ${RED}⚠ CPU 使用率过高${NC}"elif (( $(echo "$CPU > 60" | bc -l) )); then    echo -e "  ${YELLOW}⚡ CPU 使用率偏高${NC}"else    echo -e "  ${GREEN}✓ 正常${NC}"fi# 内存检查echo -n "内存使用率: "MEM=$(free | grep Mem | awk '{print $3/$2 * 100.0}')echo "${MEM%.*}%"if (( $(echo "$MEM > 80" | bc -l) )); then    echo -e "  ${RED}⚠ 内存不足${NC}"elif (( $(echo "$MEM > 60" | bc -l) )); then    echo -e "  ${YELLOW}⚡ 内存偏高${NC}"else    echo -e "  ${GREEN}✓ 正常${NC}"fi# 磁盘检查echo "磁盘使用率:"df -h | grep -E "^/dev|/data" | awk '{print "  " $5 " " $6}'# 服务检查echo -n "Nginx: "systemctl is-active nginx > /dev/null && echo -e "${GREEN}运行中${NC}" || echo -e "${RED}已停止${NC}"echo -n "MySQL: "systemctl is-active mysql > /dev/null && echo -e "${GREEN}运行中${NC}" || echo -e "${RED}已停止${NC}"echo -n "Redis: "systemctl is-active redis-server > /dev/null && echo -e "${GREEN}运行中${NC}" || echo -e "${RED}已停止${NC}"echo -n "应用: "systemctl is-active mywebapi > /dev/null && echo -e "${GREEN}运行中${NC}" || echo -e "${RED}已停止${NC}"# 监听端口echo "监听端口:"sudo ss -tlnp | grep -E "80|443|5000|3306|6379" | awk '{print "  " $4}'# 系统负载echo "系统负载: $(uptime | awk -F'load average:' '{print $2}')"# 在线时间echo "运行时间: $(uptime -p | sed 's/up //')"# Fail2ban 状态BANNED=$(sudo fail2ban-client status sshd 2>/dev/null | grep "Banned IP list" | awk '{print $NF}')echo "Fail2ban 封禁数: ${BANNED:-0}"# 最后登录echo "最后 5 次登录失败:"sudo lastb 2>/dev/null | head -3echo "=========================================="echo "      检查完成"echo "=========================================="EOFsudo chmod +x /usr/local/bin/health-check.sh# 运行检查脚本sudo bash /usr/local/bin/health-check.sh

七、常见问题

❓ Q1:服务器 CPU 使用率一直 100%

# 找出 CPU 使用率最高的进程top -c -b -n 1 | head -20# 或者使用ps aux --sort=-%cpu | head -10# 常见原因:# ① 网站被大量爬虫抓取# ② 代码中有死循环或无限递归# ③ 数据库查询没有索引,导致全表扫描# ④ 受到 CC 攻击# 如果是爬虫问题,可以封禁 IPsudo ufw deny from 爬虫IP# 或者在 Nginx 中限制访问频率

❓ Q2:磁盘空间满了怎么办?

# 紧急释放空间sudo apt clean                          # 清理 apt 缓存sudo journalctl --vacuum-size=200M      # 清理 journal 日志sudo rm -rf /tmp/*                      # 清理临时文件sudo du -sh /var/log/*                  # 查看日志占用sudo truncate -s 0 /var/log/nginx/access.log  # 清空大日志文件# 如果还是不够,扩容数据盘# 云平台控制台 → 磁盘 → 扩容 → 然后执行:sudo growpart /dev/vdb 1sudo resize2fs /dev/vdb1

❓ Q3:网站访问慢,如何定位瓶颈?

# ① 检查网络延迟ping yourdomain.com# ② 检查 DNS 解析时间dig yourdomain.com | grep "Query time"# ③ 检查页面加载时间curl -w "TCP: %{time_connect}s, SSL: %{time_starttransfer}s, Total: %{time_total}s\n" -o /dev/null -s https://yourdomain.com# ④ 检查数据库查询时间# 开启慢查询日志sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf# 添加:slow_query_log = 1slow_query_log_file = /var/log/mysql/slow.loglong_query_time = 2# 然后分析慢查询sudo tail -f /var/log/mysql/slow.log

❓ Q4:如何防止服务器被 DDoS 攻击?

# ① Nginx 限制单个 IP 的连接数# 在 nginx.conf 的 http 块中添加:limit_conn_zone $binary_remote_addr zone=addr:10m;limit_req_zone $binary_remote_addr zone=one:10m rate=30r/s;# 在站点配置的 server 块中添加:limit_conn addr 10;           # 每个 IP 最多 10 个并发连接limit_req zone=one burst=20;  # 每秒最多 30 个请求,突发允许 20 个# ② 使用 Cloudflare 等 CDN 防护# 开启 Under Attack 模式# ③ 安装 Fail2ban(已配置)# 添加 Nginx 防护规则sudo tee /etc/fail2ban/jail.d/nginx-http.conf << 'EOF'[nginx-http-auth]enabled = trueport = http,httpsfilter = nginx-http-authlogpath = /var/log/nginx/error.logmaxretry = 5findtime = 600bantime = 3600EOFsudo systemctl restart fail2ban

❓ Q5:如何查看谁在访问服务器?

# 查看当前登录的用户whow# 查看最近的 SSH 登录记录last | head -20# 查看失败的登录尝试sudo lastb | head -20# 查看 Nginx 实时访问日志sudo tail -f /var/log/nginx/access.log | awk '{print $1, $7, $9}'

八、系列总结

运维好习惯清单

每天:  ✅ 查看一次服务器的健康状态(health-check.sh)  ✅ 查看 Nginx 错误日志(tail -f /var/log/nginx/error.log)每周:  ✅ 检查系统更新(sudo apt update && sudo apt upgrade -y)  ✅ 检查磁盘空间(df -h)  ✅ 检查 Fail2ban 封禁情况(sudo fail2ban-client status sshd)每月:  ✅ 全量备份(数据库 + 配置 + 代码)  ✅ 清理旧日志和备份  ✅ 检查 SSL 证书到期时间  ✅ 审查所有用户和权限不定期:  ✅ 手动测试备份恢复流程  ✅ 安全审计(lynis audit system)  ✅ 检查应用性能,优化慢查询  ✅ 更新系统文档

完整系列回顾

篇目
核心内容
关键命令/技能
一:服务器选购与环境初始化
服务器选购、SSH、防火墙、目录规划
ssh
、ufw、ssh-keygen
二:Nginx + MySQL + Redis
运行环境搭建、安全配置
nginx
、mysql_secure_installation、redis-cli
三:实战部署 .NET Web 应用
编译发布、systemd、进程管理
dotnet publish
、systemctl、journalctl
四:域名、HTTPS、CI/CD
DNS 解析、SSL 证书、自动部署
certbot
、GitHub Actions
五:性能优化、监控与日志
监控、日志管理、安全加固、备份
netdata
、logrotate、fail2ban

写在最后

从买服务器到配环境,从部署应用到绑定域名,从手动更新到自动发布,从裸奔到安全加固——这五篇文章带你走完了一个项目的完整部署生命周期。

记住三个核心原则:

  1. 安全第一
    :密钥登录、防火墙、Fail2ban、定期备份,少一步都不行
  2. 自动化
    :能用脚本就别手动,能用 CI/CD 就别 SSH 上去敲命令
  3. 监控预警
    :出了问题不可怕,可怕的是出了问题不知道

部署运维不是一次性的工作,而是持续的过程。希望你掌握了这些技能后,能更自信地管理自己的服务器和项目。


如果你在操作过程中遇到任何问题,欢迎在评论区留言交流!

📌 IT在线自学,陪你从菜鸟到大神,关注我第一时间获取最新教程!

最新文章

随机文章