本文目录导读:

- 数据库存储的会话 (MySQL/PostgreSQL)
- Redis 存储的会话
- 文件存储的会话 (PHP原生)
- Node.js 应用(使用 express-session)
- 通用 cron 任务配置
- 最佳实践建议
- 注意事项
要清理过期会话,可以使用多种脚本方式,具体取决于你的会话存储位置(数据库、Redis、文件等),以下是几种常见场景的解决方案:
数据库存储的会话 (MySQL/PostgreSQL)
PHP 脚本示例
<?php // clean_expired_sessions.php require_once 'config.php'; // 清理过期会话 $sql = "DELETE FROM sessions WHERE expiry < NOW()"; $result = $db->query($sql); echo "已清理 " . $result->rowCount() . " 个过期会话"; ?>
Python 脚本示例
import mysql.connector
from datetime import datetime
db = mysql.connector.connect(
host="localhost",
user="root",
password="password",
database="your_database"
)
cursor = db.cursor()
cursor.execute("DELETE FROM sessions WHERE expiry < %s", (datetime.now(),))
db.commit()
print(f"已清理 {cursor.rowcount} 个过期会话")
cursor.close()
db.close()
Redis 存储的会话
Bash 脚本
#!/bin/bash
# clean_expired_redis_sessions.sh
# 方法1:使用 Redis 原生过期机制(推荐)
# 设置 TTL 后 Redis 自动清理
redis-cli KEYS "session:*" | while read key; do
ttl=$(redis-cli TTL $key)
if [ "$ttl" -le 0 ]; then
redis-cli DEL $key
echo "已删除过期会话: $key"
fi
done
# 方法2:更高效的方式
redis-cli --scan --pattern "session:*" | while read key; do
if [ $(redis-cli TTL $key) -eq -2 ]; then
redis-cli DEL $key
fi
done
Python 脚本(使用 Redis)
import redis
from datetime import datetime
r = redis.Redis(host='localhost', port=6379, db=0)
# 清理过期会话(Redis 自动管理)
# 只需要确保设置 EXPIRE 时正确设置过期时间
count = 0
for key in r.scan_iter("session:*"):
if r.ttl(key) == -1: # 没有设置过期时间
r.expire(key, 3600) # 设置1小时过期
elif r.ttl(key) == -2: # 已过期
count += 1
print(f"处理了 {count} 个会话")
文件存储的会话 (PHP原生)
Shell 脚本
#!/bin/bash # clean_php_sessions.sh PHP_SESSION_DIR="/var/lib/php/sessions" MAX_LIFETIME=1440 # 24分钟 find "$PHP_SESSION_DIR" -type f -name "sess_*" -mmin +$MAX_LIFETIME -delete echo "已清理过期PHP会话文件"
PHP 脚本
<?php
// clean_expired_sessions.php
// 手动清理PHP会话文件
$sessionDir = session_save_path();
if (empty($sessionDir)) {
$sessionDir = '/tmp';
}
$files = glob($sessionDir . '/sess_*');
$count = 0;
foreach ($files as $file) {
if (is_file($file)) {
// 超时时间(秒)
$maxLifetime = ini_get('session.gc_maxlifetime') ?: 1440;
if (time() - filemtime($file) > $maxLifetime) {
unlink($file);
$count++;
}
}
}
echo "已清理 {$count} 个过期会话文件";
?>
Node.js 应用(使用 express-session)
// clean_expired_sessions.js
const express = require('express');
const session = require('express-session');
// 清理过期会话
function cleanExpiredSessions() {
const store = new session.MemoryStore(); // 或其他存储方式
// 如果使用 connect-redis
const RedisStore = require('connect-redis')(session);
const store = new RedisStore({ client: redisClient });
// 清理过期会话
store.all((err, sessions) => {
if (err) throw err;
const now = Date.now();
let cleaned = 0;
Object.keys(sessions).forEach(key => {
const session = sessions[key];
if (session.cookie && session.cookie.expires) {
if (new Date(session.cookie.expires) < now) {
store.destroy(key);
cleaned++;
}
}
});
console.log(`已清理 ${cleaned} 个过期会话`);
});
}
// 每30分钟执行一次
setInterval(cleanExpiredSessions, 30 * 60 * 1000);
通用 cron 任务配置
Linux crontab 示例
# 每天凌晨2点清理过期会话 0 2 * * * /path/to/clean_expired_sessions.sh # 每30分钟清理一次 */30 * * * * /path/to/clean_expired_sessions.php
最佳实践建议
Redis 自动过期(推荐)
# 设置会话时指定过期时间
import redis
r = redis.Redis()
def create_session(session_id, data, expire_seconds=3600):
r.setex(f"session:{session_id}", expire_seconds, data)
# Redis 会自动清理过期数据
数据库自动清理(MySQL Event)
-- 创建定时事件
CREATE EVENT clean_expired_sessions
ON SCHEDULE EVERY 30 MINUTE
DO
DELETE FROM sessions WHERE expiry < NOW();
注意事项
- 性能考虑:不要在生产高峰期执行大规模清理
- 备份数据:清理前建议备份重要会话数据
- 日志记录:保留清理操作的日志
- 分批处理:大数据量时使用 LIMIT 分批删除
- 测试环境:先在测试环境验证脚本
选择哪种方法取决于你的会话存储方式和应用需求,对于生产环境,建议使用数据库或Redis的自动过期机制,而不是手动清理脚本。