部署与维护

恭喜你完成了PHP项目的开发!现在让我们学习如何将项目部署到服务器,并进行日常维护。本章将详细介绍从开发环境到生产环境的完整流程。

学习目标

完成本章后,你将能够:

  • 选择合适的 hosting 服务商
  • 配置生产环境的服务器
  • 使用 Git 进行版本控制部署
  • 实施自动化部署流程
  • 监控和维护线上项目
  • 处理常见的服务器问题

部署前的准备工作

1. 项目检查清单

在部署之前,让我们确保项目已经准备就绪:

功能完整性检查

## 功能检查清单

### 核心功能
- [ ] 用户注册和登录功能正常
- [ ] 密码重置功能可用
- [ ] 邮件发送功能正常
- [ ] 文件上传功能安全可靠

### 安全检查
- [ ] SQL注入防护已实施
- [ ] XSS攻击防护已开启
- [ ] CSRF保护已配置
- [ ] 密码已正确加密存储
- [ ] 敏感信息已移出代码

### 性能优化
- [ ] 数据库查询已优化
- [ ] 图片文件已压缩
- [ ] 静态资源已合并/压缩
- [ ] 缓存机制已实现

### 配置文件
- [ ] 数据库配置正确
- [ ] 错误报告已关闭(生产环境)
- [ ] 日志记录已启用
- [ ] 时区设置正确

安全配置检查

// config/security.php - 安全配置示例
<?php
return [
    // 强制HTTPS
    'force_https' => true,

    // 安全头设置
    'security_headers' => [
        'X-Frame-Options' => 'SAMEORIGIN',
        'X-XSS-Protection' => '1; mode=block',
        'X-Content-Type-Options' => 'nosniff',
        'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains'
    ],

    // Session安全
    'session' => [
        'cookie_httponly' => true,
        'cookie_secure' => true,
        'use_strict_mode' => true,
        'gc_maxlifetime' => 1440 // 24分钟
    ],

    // 文件上传限制
    'upload' => [
        'max_size' => 5 * 1024 * 1024, // 5MB
        'allowed_types' => ['jpg', 'jpeg', 'png', 'gif', 'pdf'],
        'path' => '/var/www/uploads/'
    ]
];

2. 代码优化

关闭调试模式

// 环境检测和配置
define('ENVIRONMENT', isset($_SERVER['ENVIRONMENT']) ? $_SERVER['ENVIRONMENT'] : 'development');

if (ENVIRONMENT === 'development') {
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
    define('DEBUG', true);
} else {
    error_reporting(0);
    ini_set('display_errors', 0);
    define('DEBUG', false);
}

// 错误处理函数
function handleError($errno, $errstr, $errfile, $errline) {
    if (!DEBUG) {
        // 生产环境记录错误到日志
        error_log("Error [$errno]: $errstr in $errfile on line $errline");
        // 显示友好的错误页面
        include __DIR__ . '/views/errors/500.php';
        exit();
    }
}

set_error_handler('handleError');

优化数据库配置

// config/database.php - 生产环境数据库配置
<?php
return [
    'host' => $_ENV['DB_HOST'] ?? 'localhost',
    'port' => $_ENV['DB_PORT'] ?? '3306',
    'database' => $_ENV['DB_NAME'] ?? 'myapp',
    'username' => $_ENV['DB_USER'] ?? 'root',
    'password' => $_ENV['DB_PASS'] ?? '',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',

    // 生产环境优化配置
    'options' => [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false, // 防止SQL注入
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",
        PDO::ATTR_PERSISTENT => true // 使用持久连接
    ]
];

选择合适的托管方案

1. 共享主机 (Shared Hosting)

适合初学者和小型项目:

优点

  • 价格便宜(通常每月 $5-$20)
  • 无需服务器管理经验
  • 提供控制面板(cPanel/Plesk)
  • 技术支持

缺点

  • 资源受限
  • 性能不稳定
  • 自定义配置受限
  • 安全性较低

推荐服务商

1. Bluehost
   - 价格:$2.75/月起
   - 特点:WordPress优化,免费SSL

2. HostGator
   - 价格:$2.75/月起
   - 特点:无限带宽,45天退款保证

3. SiteGround
   - 价格:$3.99/月起
   - 特点:优秀的客服,每日备份

2. VPS (Virtual Private Server)

适合中型项目和有一定技术基础的开发者:

优点

  • 独立的资源
  • 完全的控制权
  • 更好的性能
  • 可扩展性强

缺点

  • 需要技术知识
  • 需要自己管理服务器
  • 价格较高

推荐VPS提供商

1. DigitalOcean
   - 价格:$5/月起
   - 特点:简单易用,文档丰富

2. Linode
   - 价格:$5/月起
   - 特点:高性能,24/7支持

3. Vultr
   - 价格:$2.50/月起
   - 特点:全球多数据中心

3. 云服务

适合大型项目和高可用性要求:

AWS (Amazon Web Services)

// AWS部署脚本示例
<?php
// deploy-aws.sh
#!/bin/bash

# 1. 安装LAMP栈
sudo apt update
sudo apt install -y apache2 mysql-server php libapache2-mod-php php-mysql

# 2. 配置Apache
sudo a2enmod rewrite
sudo systemctl restart apache2

# 3. 配置MySQL
sudo mysql -e "CREATE DATABASE myapp;"
sudo mysql -e "CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'securepassword';"
sudo mysql -e "GRANT ALL PRIVILEGES ON myapp.* TO 'appuser'@'localhost';"

# 4. 部署代码
sudo git clone https://github.com/username/myapp.git /var/www/html/
sudo chown -R www-data:www-data /var/www/html/

echo "AWS部署完成!"

服务器环境配置

1. LAMP 环境搭建

安装 Apache

# Ubuntu/Debian
sudo apt update
sudo apt install -y apache2

# 启用必要模块
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers

# 配置虚拟主机
sudo nano /etc/apache2/sites-available/myapp.conf

Apache虚拟主机配置:

# /etc/apache2/sites-available/myapp.conf
<VirtualHost *:80>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com

    DocumentRoot /var/www/myapp/public

    <Directory /var/www/myapp/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # 日志配置
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # 安全头
    Header always set X-Frame-Options DENY
    Header always set X-Content-Type-Options nosniff
    Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>

# HTTPS配置
<VirtualHost *:443>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com

    DocumentRoot /var/www/myapp/public

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/yourdomain.crt
    SSLCertificateKeyFile /etc/ssl/private/yourdomain.key

    # 安全配置
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
</VirtualHost>

启用站点:

sudo a2ensite myapp
sudo a2dissite 000-default
sudo systemctl reload apache2

安装 PHP

# 安装PHP和常用扩展
sudo apt install -y php php-cli php-fpm php-mysql php-curl php-gd \
    php-mbstring php-xml php-zip php-intl php-bcmath

# 配置PHP
sudo nano /etc/php/8.0/apache2/php.ini

PHP生产环境配置:

# /etc/php/8.0/apache2/php.ini
; 基本设置
max_execution_time = 30
max_input_time = 60
memory_limit = 128M

; 错误显示
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log

; 文件上传
upload_max_filesize = 5M
post_max_size = 6M
max_file_uploads = 20

; Session配置
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_strict_mode = 1

; OPcache优化
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60

安装和配置 MySQL

# 安装MySQL
sudo apt install -y mysql-server

# 安全配置
sudo mysql_secure_installation

# 登录MySQL创建数据库
sudo mysql -u root -p

MySQL安全配置:

-- 创建专用数据库用户
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON myapp.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

-- 导入数据库结构
USE myapp;
SOURCE /path/to/your/database.sql;

2. Nginx + PHP-FPM 配置

安装 Nginx:

sudo apt install -y nginx php-fpm

Nginx配置文件:

# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    root /var/www/myapp/public;
    index index.php index.html;

    # SSL配置
    ssl_certificate /etc/ssl/certs/yourdomain.crt;
    ssl_certificate_key /etc/ssl/private/yourdomain.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # PHP处理
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS on;
    }

    # 静态文件缓存
    location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 禁止访问敏感文件
    location ~ /\. {
        deny all;
    }

    location ~ /(config|\.env) {
        deny all;
    }
}

启用配置:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

SSL证书配置

1. 使用 Let's Encrypt (免费)

安装 Certbot:

sudo apt install -y certbot python3-certbot-apache
# 或
sudo apt install -y certbot python3-certbot-nginx

获取并安装证书:

# Apache
sudo certbot --apache -d yourdomain.com -d www.yourdomain.com

# Nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# 自动续期
sudo crontab -e
# 添加:0 12 * * * /usr/bin/certbot renew --quiet

2. 手动配置SSL证书

生成CSR:

# 生成私钥
sudo openssl genrsa -out yourdomain.key 2048

# 生成CSR
sudo openssl req -new -key yourdomain.key -out yourdomain.csr

# 将CSR提交给CA购买证书

安装证书:

# 将证书文件复制到服务器
sudo cp yourdomain.crt /etc/ssl/certs/
sudo cp yourdomain.key /etc/ssl/private/

# 设置权限
sudo chmod 644 /etc/ssl/certs/yourdomain.crt
sudo chmod 600 /etc/ssl/private/yourdomain.key

域名和DNS配置

1. 域名购买与配置

推荐域名注册商

1. Namecheap
   - 价格:$8.98/年起
   - 特点:免费WHOIS隐私保护

2. GoDaddy
   - 价格:$12.99/年起
   - 特点:世界最大注册商

3. Cloudflare
   - 价格:免费注册
   - 特点:集成CDN和DDoS防护

2. DNS记录配置

## 基本DNS记录

@ (A) 服务器IP地址
www (A) 服务器IP地址
mail (A) 邮件服务器IP
* (CNAME) yourdomain.com

## 邮件记录(如果需要)
@ (MX) mail.yourdomain.com (优先级 10)

## 验证记录
@ (TXT) "v=spf1 include:_spf.google.com ~all"

## 安全记录
@ (DMARC) "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com"

部署流程

1. 使用 Git 部署

初始化Git仓库:

# 在本地项目目录
git init
git add .
git commit -m "Initial commit"

# 添加远程仓库
git remote add origin https://github.com/username/myapp.git
git push -u origin master

服务器配置:

# 登录服务器
ssh user@yourserver

# 克隆代码
cd /var/www
sudo git clone https://github.com/username/myapp.git
sudo chown -R www-data:www-data myapp

2. 自动化部署脚本

创建部署脚本:

#!/bin/bash
# deploy.sh

# 配置变量
PROJECT_DIR="/var/www/myapp"
BACKUP_DIR="/var/backups/myapp"
BRANCH="main"
COMMIT_HASH=$(git rev-parse HEAD)

echo "开始部署项目..."

# 1. 备份当前版本
if [ -d "$PROJECT_DIR" ]; then
    echo "备份当前版本..."
    sudo cp -r $PROJECT_DIR $BACKUP_DIR/backup-$(date +%Y%m%d-%H%M%S)
fi

# 2. 拉取最新代码
echo "拉取最新代码..."
cd $PROJECT_DIR
sudo git pull origin $BRANCH

# 3. 安装依赖
if [ -f "composer.json" ]; then
    echo "安装PHP依赖..."
    sudo composer install --no-dev --optimize-autoloader
fi

# 4. 运行数据库迁移
if [ -f "database/migrate.php" ]; then
    echo "运行数据库迁移..."
    sudo php database/migrate.php
fi

# 5. 清除缓存
echo "清除缓存..."
sudo rm -rf cache/*
sudo chmod -R 755 cache/

# 6. 设置权限
echo "设置文件权限..."
sudo chown -R www-data:www-data $PROJECT_DIR
sudo find $PROJECT_DIR -type d -exec chmod 755 {} \;
sudo find $PROJECT_DIR -type f -exec chmod 644 {} \;

# 7. 重启服务
echo "重启服务..."
sudo systemctl reload apache2
# 或 sudo systemctl reload nginx

echo "部署完成!Commit: $COMMIT_HASH"

3. 使用 Composer 进行依赖管理

创建 composer.json:

{
    "name": "yourname/myapp",
    "description": "My PHP Application",
    "require": {
        "php": ">=7.4",
        "phpmailer/phpmailer": "^6.5",
        "vlucas/phpdotenv": "^5.4",
        "twig/twig": "^3.3"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.5",
        "squizlabs/php_codesniffer": "^3.6"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "scripts": {
        "deploy": [
            "composer install --no-dev --optimize-autoloader",
            "php -v"
        ]
    }
}

生产环境安装:

# 只安装生产依赖,优化自动加载
composer install --no-dev --optimize-autoloader

# 更新依赖
composer update --no-dev

监控和维护

1. 日志管理

配置日志轮转:

# /etc/logrotate.d/myapp
/var/www/myapp/logs/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 www-data www-data
    postrotate
        systemctl reload apache2
    endscript
}

查看日志:

# Apache访问日志
sudo tail -f /var/log/apache2/access.log

# Apache错误日志
sudo tail -f /var/log/apache2/error.log

# PHP错误日志
sudo tail -f /var/log/php_errors.log

# MySQL日志
sudo tail -f /var/log/mysql/error.log

2. 性能监控

创建监控脚本:

<?php
// monitor.php - 服务器状态监控
class ServerMonitor
{
    private $thresholds = [
        'cpu_usage' => 80,        // CPU使用率阈值
        'memory_usage' => 85,     // 内存使用率阈值
        'disk_usage' => 90,       // 磁盘使用率阈值
        'load_avg' => 5.0         // 负载平均值
    ];

    public function checkSystem()
    {
        $checks = [
            'cpu' => $this->checkCpuUsage(),
            'memory' => $this->checkMemoryUsage(),
            'disk' => $this->checkDiskUsage(),
            'load' => $this->checkLoadAverage(),
            'services' => $this->checkServices()
        ];

        $this->sendAlert($checks);

        return $checks;
    }

    private function checkCpuUsage()
    {
        $load = sys_getloadavg();
        return [
            'current' => $load[0],
            'threshold' => $this->thresholds['load_avg'],
            'status' => $load[0] < $this->thresholds['load_avg'] ? 'OK' : 'CRITICAL'
        ];
    }

    private function checkMemoryUsage()
    {
        $free = shell_exec('free -m');
        $lines = explode("\n", $free);
        $memory = explode(" ", $lines[1]);
        $memory = array_filter($memory);
        $memory = array_values($memory);

        $total = $memory[1];
        $used = $memory[2];
        $usage = ($used / $total) * 100;

        return [
            'current' => round($usage, 2),
            'threshold' => $this->thresholds['memory_usage'],
            'status' => $usage < $this->thresholds['memory_usage'] ? 'OK' : 'WARNING'
        ];
    }

    private function checkDiskUsage()
    {
        $diskFree = disk_free_space('/');
        $diskTotal = disk_total_space('/');
        $usage = (($diskTotal - $diskFree) / $diskTotal) * 100;

        return [
            'current' => round($usage, 2),
            'threshold' => $this->thresholds['disk_usage'],
            'status' => $usage < $this->thresholds['disk_usage'] ? 'OK' : 'CRITICAL'
        ];
    }

    private function checkServices()
    {
        $services = ['apache2', 'mysql', 'nginx'];
        $results = [];

        foreach ($services as $service) {
            $status = shell_exec("systemctl is-active $service");
            $results[$service] = trim($status) === 'active' ? 'OK' : 'DOWN';
        }

        return $results;
    }

    private function sendAlert($checks)
    {
        foreach ($checks as $check => $value) {
            if (is_array($value)) {
                foreach ($value as $service => $status) {
                    if ($status === 'CRITICAL' || $status === 'DOWN') {
                        $this->sendEmail("$check: $service is $status");
                    }
                }
            }
        }
    }

    private function sendEmail($message)
    {
        // 发送告警邮件
        mail('admin@yourdomain.com', '服务器监控告警', $message);
    }
}

// 运行监控
$monitor = new ServerMonitor();
$results = $monitor->checkSystem();

// 输出JSON格式供API调用
header('Content-Type: application/json');
echo json_encode($results, JSON_PRETTY_PRINT);

3. 自动化任务(Cron Jobs)

设置定时任务:

# 编辑crontab
crontab -e

# 每天凌晨2点备份数据库
0 2 * * * /usr/bin/mysqldump -u appuser -p'password' myapp | gzip > /var/backups/myapp/db-$(date +\%Y\%m\%d).sql.gz

# 每小时检查服务器状态
0 * * * * /usr/bin/php /var/www/myapp/monitor.php >> /var/log/monitor.log 2>&1

# 每天清理临时文件
0 3 * * * /usr/bin/find /tmp -type f -mtime +7 -delete

# 每周重启服务(可选)
0 4 * * 0 /usr/sbin/service apache2 restart

4. 数据库维护

自动备份脚本:

#!/bin/bash
# backup.sh

# 配置
DB_NAME="myapp"
DB_USER="appuser"
DB_PASS="password"
BACKUP_DIR="/var/backups/myapp"
RETENTION_DAYS=30

# 创建备份目录
mkdir -p $BACKUP_DIR

# 生成备份文件名
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/db_backup_$DATE.sql"

# 备份数据库
mysqldump --single-transaction --routines --triggers -u$DB_USER -p$DB_PASS $DB_NAME > $BACKUP_FILE

# 压缩备份文件
gzip $BACKUP_FILE

# 删除旧备份
find $BACKUP_DIR -name "db_backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete

# 上传到云存储(可选)
# aws s3 cp $BACKUP_FILE.gz s3://your-backup-bucket/

echo "数据库备份完成: $BACKUP_FILE.gz"

安全加固

1. 防火墙配置

使用 UFW (Ubuntu):

# 安装UFW
sudo apt install ufw

# 默认策略
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 允许SSH
sudo ufw allow ssh

# 允许HTTP和HTTPS
sudo ufw allow 80
sudo ufw allow 443

# 启用防火墙
sudo ufw enable

# 查看状态
sudo ufw status

2. 防止DDoS攻击

Nginx限制请求率:

# 在nginx.conf的http块中
limit_req_zone $binary_remote_addr zone=limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
    # 应用限制
    limit_req zone=limit burst=20 nodelay;
    limit_conn addr 10;

    # 其他配置...
}

3. 文件权限安全

设置正确的文件权限:

#!/bin/bash
# set-permissions.sh

PROJECT_DIR="/var/www/myapp"

# 设置目录权限
find $PROJECT_DIR -type d -exec chmod 755 {} \;

# 设置文件权限
find $PROJECT_DIR -type f -exec chmod 644 {} \;

# 特殊权限设置
chmod 600 $PROJECT_DIR/config/database.php
chmod 600 $PROJECT_DIR/.env
chmod 755 $PROJECT_DIR/storage
chmod 755 $PROJECT_DIR/cache
chmod 755 $PROJECT_DIR/uploads

# 设置所有者
chown -R www-data:www-data $PROJECT_DIR

echo "文件权限设置完成!"

性能优化

1. 数据库优化

创建索引:

-- 为常用查询字段添加索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_posts_created_at ON posts(created_at);
CREATE INDEX idx_comments_post_id ON comments(post_id);

-- 复合索引
CREATE INDEX idx_posts_status_created ON posts(status, created_at);

-- 分析查询性能
EXPLAIN SELECT * FROM posts WHERE status = 'published' ORDER BY created_at DESC LIMIT 10;

2. 缓存优化

OPcache配置:

; /etc/php/8.0/mods-available/opcache.ini
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.save_comments=1

3. 静态资源优化

Nginx静态资源缓存:

# 缓存图片、CSS、JS等静态文件
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header Vary Accept-Encoding;
}

# 启用Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/xml+rss
    application/json;

故障排除

1. 常见问题诊断

502 Bad Gateway

# 检查PHP-FPM状态
sudo systemctl status php8.0-fpm

# 查看PHP-FPM日志
sudo tail -f /var/log/php8.0-fpm.log

# 重启PHP-FPM
sudo systemctl restart php8.0-fpm

数据库连接错误

<?php
// debug-db.php - 数据库连接测试
try {
    $pdo = new PDO(
        "mysql:host=localhost;dbname=myapp",
        "appuser",
        "password"
    );
    echo "数据库连接成功!";

    // 测试查询
    $stmt = $pdo->query("SELECT COUNT(*) FROM users");
    echo "用户总数:" . $stmt->fetchColumn();

} catch (PDOException $e) {
    echo "数据库连接失败:" . $e->getMessage();

    // 检查常见问题
    if (strpos($e->getMessage(), "Access denied") !== false) {
        echo "\n提示:检查用户名和密码";
    } elseif (strpos($e->getMessage(), "Unknown database") !== false) {
        echo "\n提示:数据库不存在,需要创建";
    }
}

文件权限问题

# 检查文件权限
ls -la /var/www/myapp/

# 修复权限
sudo chown -R www-data:www-data /var/www/myapp/
sudo chmod -R 755 /var/www/myapp/

2. 日志分析

创建日志分析脚本:

<?php
// log-analyzer.php - 分析Apache访问日志
class LogAnalyzer
{
    private $logFile;
    private $analysis = [];

    public function __construct($logFile)
    {
        $this->logFile = $logFile;
    }

    public function analyze()
    {
        $lines = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

        foreach ($lines as $line) {
            $this->parseLine($line);
        }

        return $this->generateReport();
    }

    private function parseLine($line)
    {
        // Apache log格式: IP - - [date] "method url protocol" status size "referer" "user-agent"
        if (preg_match('/^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) \S+" (\d+) (\d+) "([^"]*)" "([^"]*)"/', $line, $matches)) {
            $ip = $matches[1];
            $date = $matches[2];
            $method = $matches[3];
            $url = $matches[4];
            $status = $matches[5];
            $size = $matches[6];
            $referer = $matches[7];
            $userAgent = $matches[8];

            // 统计状态码
            $this->analysis['status_codes'][$status] = ($this->analysis['status_codes'][$status] ?? 0) + 1;

            // 统计热门页面
            $this->analysis['popular_pages'][$url] = ($this->analysis['popular_pages'][$url] ?? 0) + 1;

            // 统计IP访问
            $this->analysis['ip_visits'][$ip] = ($this->analysis['ip_visits'][$ip] ?? 0) + 1;

            // 检测可疑活动
            if ($status >= 400) {
                $this->analysis['errors'][] = [
                    'ip' => $ip,
                    'url' => $url,
                    'status' => $status,
                    'time' => $date
                ];
            }
        }
    }

    private function generateReport()
    {
        // 排序
        arsort($this->analysis['popular_pages']);
        arsort($this->analysis['ip_visits']);

        // 生成报告
        $report = [
            'total_visits' => array_sum($this->analysis['ip_visits']),
            'unique_ips' => count($this->analysis['ip_visits']),
            'errors' => count($this->analysis['errors'] ?? []),
            'top_pages' => array_slice($this->analysis['popular_pages'], 0, 10),
            'top_ips' => array_slice($this->analysis['ip_visits'], 0, 10),
            'status_codes' => $this->analysis['status_codes']
        ];

        return $report;
    }
}

// 使用示例
$analyzer = new LogAnalyzer('/var/log/apache2/access.log');
$report = $analyzer->analyze();

echo "访问日志分析报告\n";
echo "==================\n";
echo "总访问次数:{$report['total_visits']}\n";
echo "独立IP数:{$report['unique_ips']}\n";
echo "错误数:{$report['errors']}\n\n";

echo "热门页面(Top 10):\n";
foreach ($report['top_pages'] as $page => $count) {
    echo "  $page: $count 次\n";
}

应急响应

1. 网站被黑处理

应急处理步骤:

#!/bin/bash
# emergency-response.sh

echo "开始应急响应..."

# 1. 立即备份现场
echo "1. 备份当前数据..."
mkdir -p /var/backups/emergency/$(date +%Y%m%d_%H%M%S)
cp -r /var/www/myapp /var/backups/emergency/$(date +%Y%m%d_%H%M%S)/

# 2. 暂停网站访问
echo "2. 暂停网站服务..."
sudo systemctl stop apache2

# 3. 检查最近修改的文件
echo "3. 检查可疑文件..."
find /var/www/myapp -type f -mtime -7 -ls

# 4. 检查可疑PHP文件
echo "4. 搜索可疑PHP代码..."
grep -r "eval\|base64_decode\|shell_exec\|passthru" /var/www/myapp/ --include="*.php"

# 5. 清理缓存
echo "5. 清理缓存..."
rm -rf /var/www/myapp/cache/*

# 6. 重置密码
echo "6. 重置所有密码..."
sudo mysql -e "ALTER USER 'appuser'@'localhost' IDENTIFIED BY 'NewStrongPassword123!';"

echo "应急响应完成!请手动审查代码后恢复服务。"

2. 数据恢复

从备份恢复:

#!/bin/bash
# restore.sh

BACKUP_FILE=$1
DB_NAME="myapp"
DB_USER="appuser"

if [ -z "$BACKUP_FILE" ]; then
    echo "用法: ./restore.sh backup_file.sql.gz"
    exit 1
fi

echo "开始恢复数据库..."

# 1. 创建当前数据库备份
mysqldump -u$DB_USER -p $DB_NAME > /var/backups/emergency/current_backup.sql

# 2. 恢复数据库
gunzip -c $BACKUP_FILE | mysql -u$DB_USER -p $DB_NAME

# 3. 检查数据完整性
mysql -u$DB_USER -p $DB_NAME -e "SELECT COUNT(*) FROM users;"

echo "数据库恢复完成!"

总结

通过本章的学习,你掌握了:

部署技能

  • 选择合适的托管方案
  • 配置生产环境服务器
  • 使用Git进行代码部署
  • 配置SSL证书
  • 管理域名和DNS

维护技能

  • 监控服务器性能
  • 管理日志文件
  • 自动化备份
  • 性能优化
  • 安全加固

应急处理

  • 诊断常见问题
  • 处理安全事件
  • 数据恢复

持续改进

部署不是结束,而是开始。持续改进你的运维技能:

  1. 学习自动化工具:Ansible, Puppet, Chef
  2. 掌握容器化:Docker, Kubernetes
  3. 使用CI/CD:Jenkins, GitLab CI
  4. 监控和告警:Prometheus, Grafana
  5. 云服务:AWS, Google Cloud, Azure

记住,一个稳定的生产环境需要持续的关注和维护。不断学习新的技术和最佳实践,让你的PHP应用运行得更稳定、更安全!


恭喜完成所有章节的学习! 你现在已经从一个PHP初成长为具备完整项目开发、部署和维护能力的PHP开发者了!

继续探索PHP的世界,创造更多精彩的应用吧!🎉