CodeIgniter 的 $this->dbutil->backup() 仅返回 SQL 字符串,不自动上传 FTP;需手动写入文件并调用 PHP 原生 FTP 函数上传,且无内置 FTP 类,连接、传输、校验、关闭等均需自行实现。

CodeIgniter 本身不提供 FTP 自动同步能力,也不能直接“远程备份应用”——它只负责生成备份内容(如 SQL 字符串或 ZIP 文件),后续的上传、压缩、定时、权限控制都得靠你自己补全。
为什么 $this->dbutil->backup() 不会自动上传到 FTP
这个函数只返回一个 SQL 格式的字符串,不是文件,更不涉及网络传输。很多人调用后发现服务器上没生成任何文件,是因为漏了两步:write_file() 写磁盘 + 手动 FTP 上传逻辑。
-
$this->dbutil->backup()是纯内存操作,返回值是 string,不落盘也不联网 - CI 没有内置 FTP 客户端类;
ftp_connect()等原生 PHP 函数需自己封装 - FTP 登录失败时通常静默失败,建议用
@ftp_login()+ftp_pwd()显式校验连接状态 - 别把 FTP 密码硬编码在控制器里,应从配置文件或环境变量读取
怎么用 PHP 原生 FTP 实现上传备份文件
先确保本地已生成压缩备份(比如 backup_2026-04-21.sql.gz),再用 FTP 传到远程服务器。关键点不在 CI,而在 PHP 的 FTP 流程是否健壮:
- 连接前设超时:
ftp_set_option($conn, FTP_TIMEOUT_SEC, 30) - 上传后务必检查返回值:
ftp_put($conn, $remote_path, $local_path, FTP_BINARY) === true - 上传完成立即关闭连接:
ftp_close($conn),否则可能耗尽 FTP 连接数 - 路径注意斜杠方向:Windows 下
\backups\在 FTP 里要写成/backups/
示例片段(非完整类):
if ($conn = ftp_connect('ftp.example.com')) {
if (@ftp_login($conn, 'user', 'pass')) {
ftp_pasv($conn, true);
ftp_put($conn, '/backups/' . $filename, './backups/' . $filename, FTP_BINARY);
ftp_close($conn);
}
}
用 zip 类打包整个 application/ 目录再上传可行吗
可以,但风险极高——application/ 里包含数据库配置、密钥、日志等敏感内容,一旦 FTP 账号泄露或路径可遍历,等于把后门钥匙交出去。
- CI 的
$this->zip类只能添加文件或目录,不能排除子路径,得先scandir()过滤掉config/database.php、logs/、cache/ - 打包后文件体积大,PHP 默认执行时间 30 秒大概率超时,必须加
set_time_limit(0) - 不要用
$this->zip->download()替代上传——这是发给浏览器的,不是传到 FTP - 更安全的做法是:只同步
application/controllers/和views/,其他由部署脚本重建
真正可靠的远程备份该怎么做
绕过 CI 做底层操作更稳定。比如用系统级方案替代 PHP 脚本:
- 用
mysqldump+tar+rsync写 shell 脚本,通过cron每天执行,比 PHP 更抗超时 - 备份目标改用 S3 或腾讯云 COS,用
aws-cli或coscli上传,比 FTP 权限更细、日志更全 - 如果必须走 CI 控制台触发,至少把 FTP 上传抽成独立命令行工具,用
exec()调用,避免 PHP 内存和超时限制 - 所有备份文件名必须含时间戳,且上传前校验 MD5,防止传一半中断导致损坏
最常被忽略的一点:FTP 上传成功 ≠ 备份可用。你得在远程服务器上定期跑 gunzip -t 和 mysql --no-defaults -e "source backup.sql" 做恢复验证——否则等到真出事那天,才发现 gzip 文件早坏了。


















