JavaScript 应用跑在 Ubuntu 上,日志往往同时承担排障、审计和运行留痕三种职责,但很多团队直到磁盘打满、日志误删或排错追不到历史记录时,才意识到备份策略的重要性。下面按“怎么备份、怎么自动化、出了问题怎么恢复”三个方向展开,把手工命令、定时脚本、logrotate 配置和恢复技巧串成一套能直接落地的做法,读完后你可以判断自己更适合临时备份、定时归档,还是直接交给系统轮转工具管理。
手动备份:适合临时归档和快速上手
如果当前只是想先把日志安全留存下来,最直接的办法就是手动备份。对于 JavaScript 应用来说,日志目录通常位于 /var/log/js-app/,也可能是应用自己定义的路径。手动方式的优点是简单、可控,适合临时操作、迁移前留档,或者线上排障前先做一次快照。
用 tar 打包完整日志目录
tar 适合把整个日志目录压缩成一个带日期的归档文件,便于长期保存和后续恢复。示例命令如下:

sudo tar -czvf js_app_logs_$(date +%Y%m%d).tar.gz /var/log/js-app/
这条命令会把 /var/log/js-app/ 打包成一个以当天日期命名的压缩文件,例如按日期生成归档,后续查找也更直观。对于日志量不大的应用,这种方式足够直接。
用 rsync 做增量同步
如果日志目录较大,或者你不想每次都重新打包全部文件,可以改用 rsync 做增量备份,只同步发生变化的内容:
sudo rsync -a vz /var/log/js-app/ /backup/js-logs/
相比完整压缩,rsync 更适合频繁备份,尤其是在本地备份目录已经存在历史数据时,能明显减少耗时和重复写入。
不过,手动备份的限制也很明显:它依赖人去执行,临时操作可以,长期依赖就容易漏做。只要应用日志持续增长,后续就应该考虑自动化。
自动化备份:用脚本和 cron 固定执行
当日志需要每天、每周稳定归档时,手动执行就不够用了。更实用的方式是把备份命令写进 Shell 脚本,再交给 cron 定时运行。这样既保留了 tar 的归档能力,也能顺手处理过期清理。
备份脚本怎么写
下面这段脚本把日志目录压缩到备份目录,并自动删除 7 天前的旧备份:
#!/bin/bash
LOG_DIR="/var/log/js-app"
BACKUP_DIR="/backup/js-logs"
TIMESTAMP=$(date +%Y%m%d)
tar -czvf "$BACKUP_DIR/logs_backup_$TIMESTAMP.tar.gz" "$LOG_DIR"
find "$BACKUP_DIR" -type f -name "*.tar.gz" -mtime +7 -exec rm {} ;
脚本里的几个关键点需要明确:
LOG_DIR指向实际日志目录;BACKUP_DIR指向备份落盘位置;TIMESTAMP=$(date +%Y%m%d)用于生成日期后缀,例如logs_backup_20250926.tar.gz;find ... -mtime +7负责清理 7 天前的压缩包,避免备份目录无限膨胀。
如何让脚本定时执行
脚本保存为 backup_js_logs.sh 后,先增加执行权限:
chmod +x backup_js_logs.sh
然后通过 crontab -e 增加定时任务:
0 1 * * * /path/to/backup_js_logs.sh
这表示每天凌晨 1 点执行一次脚本。对于大多数业务系统,这个时间点比较适合做归档,不容易和白天的高峰写日志冲突。
这种方案的核心优势在于:命令仍然是你熟悉的 tar 或 rsync,但执行已经变成固定流程。对于还没有集中日志平台的小型或中型部署,这通常已经够用。
工具化管理:用 logrotate 做日志轮转与压缩
如果你不只是想“备份一份”,而是希望日志每天自动轮转、旧文件自动压缩、保留周期自动控制,那么 Ubuntu 自带的 logrotate 更适合承担这件事。它不是单纯的归档工具,而是面向日常日志生命周期管理的系统组件。
logrotate 配置示例
可以创建一个 /etc/logrotate.d/js-app 配置文件,加入如下规则:
/var/log/js-app/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 640 root adm
}
这些配置分别意味着什么
daily:每天执行一次轮转;rotate 7:最多保留 7 份历史日志;compress:对旧日志进行压缩,减少磁盘占用;delaycompress:延迟一轮再压缩,避免刚轮转的文件立刻被压缩;missingok:即使日志文件不存在,也不要报错中断;notifempty:空日志不轮转;create 640 root adm:轮转后创建新日志文件,并设置权限和属主属组。
这套规则适合稳定运行的 JavaScript 服务,尤其是 Node.js 应用已经持续输出本地日志文件时。它的重点不在“额外复制一份”,而在于把日志文件本身管理好,避免单文件不断变大,也避免历史日志散乱难查。
上线前先测试
配置完成后,建议先做两步验证:
sudo logrotate -d /etc/logrotate.d/js-app
这条命令用于调试配置,先看规则是否符合预期。
sudo logrotate -f /etc/logrotate.d/js-app
这条命令会强制执行一次轮转,方便确认压缩、保留和新文件创建都没有问题。对线上环境来说,这一步很重要,因为日志权限设置错误,往往会直接导致应用后续无法继续写入。
日志恢复:从备份包到误删除抢救
备份策略是否可靠,最终还是要看恢复是否顺畅。Ubuntu 上的 JavaScript 应用日志恢复,大体可以分成两类:一类是从已有备份恢复,另一类是日志被误删但进程还没退出时的紧急挽回。

从 tar 或 rsync 备份恢复
如果之前使用的是 tar 归档,恢复时直接解压到原日志目录即可:
tar -xzvf /backup/js-logs/logs_backup_20250926.tar.gz -C /var/log/js-app/
如果之前使用的是 rsync 同步,那么恢复方式就是反向同步:
rsync -a vz /backup/js-logs/ /var/log/js-app/
这两种方式本身都不复杂,真正需要注意的是恢复路径和目录权限。尤其是线上恢复时,如果目标目录写错,或者直接覆盖了当前正在写入的新日志,反而会制造新的排障问题。
日志误删后,如何从运行中的进程抢救
有一种常见而危险的情况是:日志文件已经被删除,但应用进程仍然持有文件描述符,数据实际上还没完全丢失。这时可以借助 lsof 和 /proc 做恢复。
先找出被删除但仍被进程占用的日志文件:
sudo lsof | grep deleted | grep js-app.log
假设输出里找到了对应的进程 PID 和文件描述符,例如 PID 为 1234、描述符为 5,就可以执行:
sudo cp /proc/1234/fd/5 /var/log/js-app/app.log
这一步本质上是从进程仍然打开的文件句柄中,把内容复制回新的日志文件。恢复完成后,再重启日志相关服务:
sudo systemctl restart rsyslog
这样系统会重新建立正常写入流程。这个方法特别适合误删后立即处理的场景,时间拖得越久,成功找回的概率越低。
查看与提取日志:恢复之外的日常排障手段
并不是每次遇到日志问题都需要恢复文件。很多时候,日志还在,只是需要快速查看、过滤或提取关键信息。这时可以同时利用 journalctl 和普通文本查看命令。
用 journalctl 查 systemd 管理的服务日志
journalctl 是 systemd 的日志查询工具,适合按服务、时间范围和日志级别进行筛选。常见命令包括:
journalctl -u js-app.service
journalctl -n 50
journalctl -p err
journalctl -u js-app.service:查看指定服务的日志;journalctl -n 50:查看最近 50 条记录;journalctl -p err:只筛选错误级别日志。
如果应用是以 systemd 服务方式运行,这通常比直接翻文件更快,因为它天然适合按条件过滤。
直接查看应用日志文件
对于仍然写入 /var/log/js-app/app.log 这类文件的应用,也可以继续使用 tail、grep 等命令进行定位。它们虽然简单,但在查看实时输出、筛选关键词时依然非常高效。实际工作里,很多故障排查往往就是先用 journalctl 确认服务层状态,再回到应用日志文件定位具体报错内容。
整体来看,Ubuntu 上 JavaScript 应用的日志管理没有唯一答案。临时需求可以先用 tar 或 rsync,要稳定执行就配合脚本和 cron,而需要长期规范化管理时,logrotate 更适合成为默认方案。至于恢复环节,提前验证命令和路径,比事后补救更关键。







