news 2026/10/21 4:30:51

Linux日志保存与屏幕录制:重定向、script、tmux、ffmpeg全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux日志保存与屏幕录制:重定向、script、tmux、ffmpeg全攻略

1. 先从一次翻车说起:为什么我把日志和录制放在一起

先讲个真实经历。之前排查一个服务半夜自动挂掉的问题,改了配置、加了监控、重启了进程,第二天一看还是挂了。折腾了三天,最后发现是启动脚本里某个环境变量在特定条件下被覆盖,但问题在于——我把当时的终端输出丢掉了,全靠回忆推演,绕了很大一圈。

从那次以后,我给自己定了一条规矩:凡是重要操作,日志必须留档,操作过程能录则录。这也是今天想聊的题目:Linux 下保存日志文件,以及把屏幕操作过程录制下来。两个能力看起来不相干,但本质上都在解决同一个问题——让发生过的操作可追溯、可回放、可复盘。

这篇东西适合谁?一线运维、后端开发、搞自动化的朋友,还有平时喜欢折腾 Linux 的玩家。你会用到script、tee、journalctl、logrotate、ffmpeg、tmux这些工具,学会之后,调试问题时能把“当时到底发生了什么”完整保存下来,而不是拍脑袋。

下面我按两条线展开:先讲日志怎么存、怎么转储、怎么不让磁盘爆掉;再讲屏幕录制,覆盖文字级录制和真视频录制;最后单独列一节常见问题,都是我自己踩过的坑。

2. 日志保存:从终端输出到落盘归档

2.1 最基础的重定向玩法,先把输出留住

先明确一个概念:Linux 下命令行的输出分两股,标准输出(stdout,文件描述符 1)和标准错误(stderr,文件描述符 2)。这个问题理解不到位,后面所有日志操作都是糊涂账。

最基础的用法:

# 只保存标准输出 ./deploy.sh > deploy.log # 只保存错误输出 ./deploy.sh 2> error.log # 两者分开存 ./deploy.sh 1> out.log 2> err.log # 混在一起存(最常见) ./deploy.sh > all.log 2>&1

2>&1的意思是“把 stderr 也喂给 stdout 现在指向的地方”。很多人一上来就背这个写法,不理解为啥要写成这个样子,稍微变个顺序就出错。

有个很容易犯的错:把重定向当摆设,因为程序自己往/dev/tty写东西。比如某些交互式脚本、需要输入密码的sudo命令、调用了dialog界面的安装程序,它们的输出根本不走标准输出。这种情况你用>重定向是截不到的,得用后面的script或者tmux来解决。

另一个基础操作是追加模式。跑定时任务、循环脚本时,千万别用>,每次都会把老文件清空重写,历史就没了。要用>>:

for i in $(seq 1 10); do echo "round $i" >> run.log ./task.sh >> run.log 2>&1 done

2.2 tee:既要文件保存,也要屏幕实时看

重定向有个体验问题:输出全进了文件,屏幕上啥都看不到。跑长任务的时候,人总不能一直干等盯着,但彻底不看又怕中途出错。tee就是干这个的:

./backup.sh 2>&1 | tee backup.log

等于给输出接了根分叉管,一路进终端,一路落文件。tee -a追加模式对应>>的语义,不加-a就相当于>,启动时会覆盖已有文件。

配合tee还有个玩得很熟的场景:不光保存输出,还要把执行过程中所有输入过的命令也留下来。这就要配合history或者审计工具,后面说script的时候会提到。

2.3 nohup 和后台任务的日志陷阱

跑后台任务,最典型的是nohup。很多人以为nohup会自动把输出写进文件,其实它的行为是:如果 stdout/stderr 没有显式重定向,就写到当前目录下的nohup.out。这文件很坑——不轮转、不清空、权限混乱,时间久了能飙到几个 GB,把磁盘打满。

所以正确姿势是显式重定向:

nohup ./app server > /var/log/app/$(date +%F).log 2>&1 &

加上日期后缀,按天切分,后面配合日志清理就很省事。

再补一个setsid的细节。nohup只是忽略挂断信号,进程还会在同一个终端会话里;setsid则是让进程真正脱离会话,换一个新会话。两者配合后台运行时,建议这么写:

setsid ./worker > /var/log/worker.log 2>&1 < /dev/null

上面这个< /dev/null很多人会漏掉。如果后台进程还留着 stdin 指向终端,某些情况下它会干扰终端的作业控制,甚至导致终端关闭时进程被连带杀掉。标准写法三件套:输出重定向、错误重定向、输入置空,一个都不能少。

2.4 journald 日志:systemd 托管服务的正确导出方式

如果服务是 systemd 托管的(.service单元),日志默认走journald,不会直接写文件。这是很多从 SysVinit 时代过来的人最容易懵的地方。systemctl status xxx能看到最近几行,但想看完整日志就得用journalctl。

日常我用得最多的日志导出命令:

# 查最近一小时 journalctl -u myapp.service --since "1 hour ago" # 根据日期范围导出 journalctl -u myapp.service --since "2024-06-01 00:00:00" --until "2024-06-01 23:59:59" > myapp_0601.log # 导出到文件 journalctl -u myapp.service -o short-precise > myapp_full.log # 实时跟踪 journalctl -u myapp.service -f

注意-o short-precise,这个格式会带微秒级时间戳,排查性能问题时特别有用。默认的short格式只到秒,一些偶发慢请求定位不到具体毫秒点。

journald 的日志不会无限增长,默认按文件大小上限(通常是所在文件系统的 10%)来限制。但有个坑:journalctl --vacuum-time和--vacuum-size只对已归档的日志生效,当前活跃的 journal 文件不会被清理。日常建议顺手设一下:

journalctl --vacuum-time=7d journalctl --vacuum-size=500M

2.5 logrotate:让日志文件自动轮转、压缩、清理

日志只存不转,迟早爆盘。logrotate是 Linux 下管理日志文件轮转的事实标准,但我发现很多开发机上压根没配,或者配了没生效。

典型配置文件写一个:

/var/log/myapp/*.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate }

每个参数解释一遍:

  • daily:按天轮转。
  • rotate 7:保留 7 份归档,超过就删。
  • compress:归档文件用 gzip 压缩。
  • delaycompress:刚切出来的上一份不立即压缩,等下次轮转再压。原因是有进程还握着旧文件句柄在写,立即压缩会压到不完整内容。
  • missingok:日志文件不存在时不报错。
  • notifempty:文件为空就不轮转。
  • copytruncate:先复制当前内容到归档,再清空原文件。这样进程不用重启,对于不支持 reopen 日志句柄的程序特别重要。

手动测试配置是否正确:

logrotate -d /etc/logrotate.d/myapp logrotate -f /etc/logrotate.d/myapp

-d是调试模式只打印不执行,-f是强制执行。我第一次配 logrotate 的时候,忘了给/var/log/myapp目录配权限,日志文件是 root 创建的,服务以普通用户跑,轮转时直接权限报错。这事排查了半小时才发现。

还有一点,logrotate 本身由 cron 或 systemd 定时触发,但默认触发频率是每天一次。如果你在配置里写的是hourly,要确认/etc/cron.hourly/logrotate或对应 systemd timer 存在,否则配置写了不生效,白白等待。

3. 屏幕录制:利用现成工具把操作过程完整留档

3.1 script 命令:终端会话的文字级录制

script是 util-linux 自带的命令,绝大多数发行版都预装了,它的作用是把一次终端会话里所有的输入输出完整记录到一个文件。它不是录画面,而是录文字。

用法:

script -t 2> timing.log -a session.log

-t输出时间间隔数据到 timing 文件,-a追加模式保留历史。退出录制用exit或者 Ctrl+D。

录完之后用scriptreplay回放:

scriptreplay -t timing.log session.log

回放时会按原始时间间隔重放,基本还原当时的操作节奏。这个能力在以下场景里特别有用:

  • 故障排查复盘:技术会议上回放自己当时的操作,比口述“我好像敲了什么”清楚得多。
  • 教学演示:录一份命令操作过程,配合回放比录屏视频文件更小更快。
  • 操作审计:配合时间戳,知道每条命令是什么时候执行的。

script有个限制要注意:它只记录终端上的字符流,不记录窗口大小变化。如果你的终端窗口在录制过程中变了大小,回放时排版可能错位。建议录制前把窗口固定一下。

还有一个容易被忽略的细节:script默认生成的文件是明文文本,里面可能包含密码(如果操作中输过明文密码)。归档这类文件时要记得权限收紧,或者用chmod 600。

3.2 tmux:比 script 更稳的长时间录制方案

如果你要录的是持续数小时甚至数天的部署过程,script会随着终端断连而中断,而tmux可以完美规避这个问题。

tmux 是终端复用器,核心价值是“会话在,任务就还在”。具体到录制场景,玩法是:开启一个 tmux 会话,执行你的长任务,然后录制整个会话的输出。

tmux new -s deploy # 在 tmux 会话里 ./deploy.sh 2>&1 | tee /var/log/deploy/live.log

然后断开但不结束会话:Ctrl+B再按D。这时候 ssh 断开、终端崩溃,tmux 里的任务照常跑。重连后:

tmux attach -t deploy

这个方案的日志连续性比nohup更好:nohup一旦写错日志路径,想临时改很麻烦,tmux 会话里随时可以操作,还能看到当前进度。

tmux还自带pipe-pane,可以直接把当前窗格的所有内容实时同步到文件,不用在会话里边敲命令边挂tee:

tmux pipe-pane -o 'cat >> /tmp/tmux_$(date +%F).log'

注意pipe-pane录的是屏幕缓冲区里滚过的一行行内容,它保留的是终端渲染后的文本,样式字符(颜色控制符)也会夹杂在文件里,阅读时需要清理。文本搜索基本没问题。

3.3 ffmpeg:真正录屏,把图形界面和声音都留下来

文字录制解决“界面输出”的问题,但有些场景必须录像素画面,比如配置某个图形工具、演示 Web 界面操作、或者录一个只有 GUI 能复现的 bug。这时候靠ffmpeg。

X11 桌面录屏的基本命令:

ffmpeg -f x11grab -video_size 1920x1080 -framerate 30 -i :0.0 \ -f pulse -i default \ -c:v libx264 -preset ultrafast -crf 23 \ -c:a aac -b:a 128k \ output.mkv

拆开解读:

  • -f x11grab -video_size 1920x1080 -framerate 30 -i :0.0:从 X 显示器的:0.0抓取画面,尺寸 1080p,帧率 30。-framerate不是越高越好,网络传输和编码开销线性上升,日常演示 15 就够,录游戏才需要 60。
  • -f pulse -i default:从 PulseAudio 默认源录声音。如果不想录音,去掉这段即可。
  • -preset ultrafast:编码速度快,但体积会比medium大一截。隐私和数据量权衡下,录制长时间操作建议用veryfast或fast。
  • -crf 23:恒定质量因子,数值越小画质越高,23 是 x264 的常见平衡值。

录制区域不想全屏,可以用-video_size 1280x720 -i :0.0+100,50,其中+100,50表示从屏幕 (100,50) 坐标开始抓取。多显示器环境,注意:0.0后面加+x,y选对显示器。

录到一半发现磁盘快满了,想临时调整码率怎么办?ffmpeg是实时编码,没法中途改参数。我会习惯性加一句:

ffmpeg -f x11grab ... -t 3600 output.mkv

-t 3600限时 1 小时自动停止,避免挂机录穿磁盘。

补一个 Wayland 的坑:现在的很多桌面已经改用 Wayland 而不是 X11,x11grab在 Wayland 下直接抓不到画面。这种情况可以先开一个 XWayland 的 X 会话,或者改用wf-recorder这类专门为 Wayland 设计的录制工具。

3.4 录制文件的命名、整理和快速检索

录制文件不整理,过两个月就变成一堆output.mkv、session.log、timing.log,根本分不清哪个是哪个。我现在的习惯是约定式命名:

录屏/时间_项目_环节_结果.扩展名 2024-06-01_备份脚本_首次部署_失败.mkv 2024-06-03_日志排查_误删文件_已解决.mkv

日志文件也按日期分目录:

/var/log/myapp/2024/06/01/app.log

检索方面,文本日志直接grep:

grep -n "ERROR" /var/log/myapp/2024/06/01/app.log # 显示上下文 grep -n -B 5 -A 10 "ERROR" /var/log/myapp/2024/06/01/app.log

视频录制没法 grep,要快速定位关键画面,可以用ffmpeg抽帧做缩略图索引:

mkdir thumbnails ffmpeg -i output.mkv -vf fps=1/60 thumbnails/%04d.jpg

每隔 60 秒抽一帧,形成一张时间轴,想看某个时间点做了啥,翻图比拖进度条快得多。这个办法很土,但实测有效。

4. 常见问题与排查技巧实录

实际用下来,几个问题反复出现,这里把我踩过的坑一并整理出来。

4.1 日志文件写到一半就打不开了 / 文件里全是空行

典型场景:用>重定向启动了程序,但程序运行过程中崩溃、或者重启后重新打开了日志文件,之前的句柄失效。这时候tail -f看不到新内容,文件却还在增长。

排查思路:先看进程实际打开的文件句柄:

ls -l /proc/<pid>/fd/1 ls -l /proc/<pid>/fd/2

如果发现 fd 指向的文件名后面带(deleted),说明文件被重新创建过,旧句柄还挂着。解决方案就是上面提到的copytruncate,或者让进程自己支持重新打开日志文件。

4.2 script 录制文件里的中文乱码

script录制文本是原始字节流,不感知字符集。如果你的终端是 UTF-8,但某些命令输出 GBK 编码(比如老旧的 Windows 兼容程序),录下来的文件直接打开就是乱码。

处理办法:录制时统一终端语言环境:

export LANG=C.UTF-8 export LC_ALL=C.UTF-8

回放时如果还是乱码,用iconv转码:

iconv -f GBK -t UTF-8 session.log > session_utf8.log

4.3 tmux 回放耗时太长,1 小时录像要看 1 小时

scriptreplay是按时序回放的,没有倍速参数。可以手动调大间隔倍数:

# 用 awk 调整 timing 文件中的时间戳倍数 awk '{print $1 * 0.5, $2}' timing.log > timing_0_5.log scriptreplay -t timing_0_5.log session.log

把时间戳乘以 0.5,等于 2 倍速播放。我把这招叫作“人工倍速回放”,实测很好使。

4.4 ffmpeg 录到一半没声音

检查 PulseAudio 是否被系统静音、以及 ffmpeg 是否权限不足。如果程序以 root 运行,要带-xauth或者使用当前用户的 XAUTHORITY 文件。录声音先测试:

ffmpeg -f pulse -i default -t 5 test.m4a

能录出声音再挂完整录制命令,不然画面录了一小时、音轨全静音,白忙活。

4.5 日志轮转没有按预期执行

排查顺序:

  1. 看配置文件语法:logrotate -d /etc/logrotate.d/myapp
  2. 看 systemd timer 是否启用:systemctl status logrotate.timer
  3. 看状态文件:/var/lib/logrotate/status,里面有每个日志文件的最后轮转时间,对比一下就知道到底有没有触发。

常见问题集中在权限或路径拼写错误。比如配置里写的路径和实际服务写日志的路径不一致,轮转的永远是空文件。

5. 组合起来用的高效场景

工具单独用容易忘记,组合起来用才是精髓。这套组合拳我在实际项目里反复使用。

5.1 部署脚本的“操作 + 日志”双轨记录

部署经常是多个阶段:拉代码、构建、重启服务、验证探活。我的做法是:

# 1. 开启 tmux 会话 tmux new -s deploy_$(date +%F_%H%M) # 2. 在会话内记录整段操作,同时 tee 日志文件 script -t 2> /var/log/deploy/timing.log -a /var/log/deploy/session.log ./deploy.sh 2>&1 | tee /var/log/deploy/live.log # 3. 服务起来后 curl 探活,把响应也 log 下来 curl -sS -w "HTTP %{http_code}\n" http://localhost:8080/health | tee -a /var/log/deploy/live.log # 4. 退出录制 exit

这套下来,每次部署产生三个文件:命令时序(timing)、完整会话文本(session)、应用实时输出(live)。以后部署出问题,拿这三个文件对着看,几秒钟就能定位到是哪条命令在哪个时刻出的错。

5.2 远程操作审计:谁在什么时间做了什么

多人在同一台服务器上操作时,想保留“操作过程 + 时间线”的记录。方案是让每个用户进入时自动执行script:

在/etc/profile.d/audit_session.sh里写:

if [ -z "$AUDIT_SESSION" ]; then export AUDIT_SESSION=1 script -t 2> /var/log/audit/$(date +%F)_${USER}_$$.timing -a /var/log/audit/$(date +%F)_${USER}_$$.session exit fi

这样每个 SSH 登录用户都会自动挂上录制,退出时记录结束。注意$$是 Shell PID,用它区分同一用户同一天多次登录的会话文件。

这种做法适合临时性的操作审计,比商业堡垒机轻量得多,但对于大多数中小团队来说已经够用。

5.3 远程协助排障:让对方把自己看到的录下来

帮别人远程排查问题,文字描述半天说不清楚,不如让对方自己录一段。没有桌面环境的情况下,一条命令:

script -t 2> $(hostname).timing -a $(hostname).session

然后把session和timing两个文件传回来,你用scriptreplay回放,能完整看到对方敲过的每个命令和输出,比截图效率高太多。

6. 写在最后:关于日志与录制,我的一些体会

玩 Linux 这么多年,最大的感受就是:排查问题的速度,取决于你有多少现场记录。很多诡异的 bug,都是“当时能看到,事后查不到”的状态下最难搞。日志文件、录制文件不是给自己添麻烦的,是给自己留后路的。

几个从实践里沉淀下来的习惯,值得分享一下:

第一,交付任何脚本之前,先想清楚它的输出落到哪里。哪怕一个简单的curl请求,也加一句| tee -a $LOG。这句话的成本几乎为零,但排障时它可能帮你省掉一晚上。

第二,日志文件一定要有轮转和清理策略。一次把磁盘写满造成更大事故的教训,比日志丢失还惨。logrotate 配置别偷懒,写完用-d验证一下。

第三,重要的操作录音前,先做一次 10 秒的试录,确认格式、声音、编码都正常,再开始正式录制。

最后,记录不是万能的,它不能帮你自动找到问题根因,但它能让你少走 90% 的弯路。我现在处理线上问题,第一件事就是先把当前所有的日志、会话状态存档,再动手操作——动手前存一份,动手后再存一份,对比着看,很多所谓“玄学问题”其实都在对比中自己现出原形了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 4:30:51

数据管道中JSON编码问题:无效UTF-8字节的排查与清洗实践

做云平台数据网关的这些年&#xff0c;被JSON编码的坑绊倒的次数一只手数不过来。最典型的一次线上故障&#xff0c;是凌晨三点多某上游系统上报的订单数据在解析环节批量失败&#xff0c;错误日志清一色指向同一个问题&#xff1a;JSON编码无效UTF-8字符。如果你也写过API对接…

作者头像 李华
网站建设 2026/10/21 4:30:18

AI决策链风险监测:认知锚定与路径锁死的量化分析

如果你的AI服务在某个凌晨批次任务里&#xff0c;把十几条本应“谨慎通过”的申请全部改判为“拒绝”&#xff0c;你会先从哪一步查起&#xff1f;以我盯AI风险系统这几年的经验&#xff0c;先把整条AI决策链拉出来看。这类事故极少出在某个单一模型步的准确率上&#xff0c;而…

作者头像 李华
网站建设 2026/10/21 4:30:05

Llama-Guard 3垂直行业微调实战:QLoRA降低误伤率与漏报率的完整方案

做内容安全的人&#xff0c;迟早都会碰到同一个尴尬&#xff1a;通用守卫模型 Llama-Guard 3 分类能力强&#xff0c;但放在垂直行业里&#xff0c;要么把正常业务话术拦成一堵墙&#xff0c;要么对行业黑话视而不见。给它做行业化微调&#xff0c;是我认为性价比最高的一条路。…

作者头像 李华
网站建设 2026/10/21 4:28:46

SSM与Django双版本订餐系统开发实战:从数据库设计到部署交付

1. 项目缘起&#xff1a;这套订餐系统到底做了什么我最近刚结束一个颇为典型的项目——给某高校做的一套订餐管理系统&#xff0c;完整交付内容包括源码、论文文档、调试文档和讲解演示。这套系统的亮点在于同时给甲方做了Java SSM版和Python Django版两套后端&#xff0c;前端…

作者头像 李华
网站建设 2026/10/21 4:28:46

目标检测数据集实战:1483张遛狗嘴套佩戴检测图片(VOC+YOLO)

养狗这件事在社区管理里越来越绕不开一个细节&#xff1a;遛狗时到底有没有给狗戴嘴套。靠人眼盯着不现实&#xff0c;物业、文明养犬巡查、甚至一些公共场所的入口管理&#xff0c;都需要一个能自动判断“狗戴没戴嘴套”的小工具。我今天要分享的就是针对这个场景做的一个目标…

作者头像 李华
网站建设 2026/10/21 4:28:29

Hive逻辑优化进阶:动态分区裁剪、子查询重写与CBO实战

提到Hive的逻辑优化&#xff0c;已经是第六篇了&#xff0c;说明前面几篇已经把SQL解析、基础执行流程、甚至第一波优化规则都过了一遍。我在这篇里把逻辑优化剩下的几个硬骨头集中聊透&#xff1a;动态分区裁剪、子查询重写、Join顺序重排&#xff0c;以及被很多同学当成“黑盒…

作者头像 李华