head 默认取前10行,不识别空行或注释;tail -f 需改用 tail -F 防 inode 失效;组合使用 tail -n +N | head -n M 实现精准行段提取,避免内存浪费。

head 默认只看前10行,但实际常用场景远不止这个数
很多人输完 head filename 就以为“看完了”,结果发现关键信息在第12行——head 真的只取前10行,不多不少。它不识别空行、注释或逻辑段落,就是纯按行号切。
实操建议:
- 要查前 N 行:直接加
-n N,比如head -n 50 access.log查请求头50条 - 想排除文件头(比如 CSV 的表头)再看内容?用
head -n +20是错的——+20表示“从第1行到第20行”,和-n 20效果一样;真要跳过前2行再取20行,得组合:tail -n +3 filename | head -n 20 -
head -c 100按字节截,适合二进制或超长无换行日志,但注意中文会截断 UTF-8 编码导致乱码
tail -f 不是万能实时监控,卡住或丢行很常见
tail -f 看日志时突然不动了?不是程序停了,大概率是文件被 logrotate 重命名或清空了——tail -f 会继续盯原 inode,而新日志已写进新文件。
实操建议:
- 生产环境务必用
tail -F(大写 F),它会在文件被删/重命名后自动重新打开新文件,比-f多一层 inode 检测 - 如果日志写入极快(如每秒千行),
tail -f可能因缓冲滞后几秒,这不是 bug,是内核 page cache 和 stdio 的正常行为;加--line-buffered(部分 GNU 版本支持)可缓解,但不保证实时 -
tail -n 0 -f是安全起点:只输出新增行,不刷屏旧内容
head/tail 组合用比单用强得多,但管道顺序不能反
想看一个大 JSON 文件的中间某段?别先 head 再 tail,顺序错了就白忙。真实需求常是“跳过前X行,取Y行”,这本质是 tail 的事,head 只负责收尾。
实操建议:
- 查第 100–150 行:
tail -n +100 filename | head -n 50——tail -n +100表示“从第100行开始往后全部”,再用head截长度 - 反过来写
head -n 150 filename | tail -n 50也能得到同样结果,但内存占用高:前者流式处理,后者先把150行全读进内存 - 处理压缩文件?别解压:
zcat logfile.gz | tail -n 20直接管道,省空间又快
大文件下性能差异明显,别让 head/tail 成瓶颈
对几百 MB 的日志跑 head -n 1000000?命令本身秒出,但背后是顺序读——它不会跳过前面内容,只是读到第100万行就停。如果文件真有上千万行,开头几万行全是空行或注释,head 还是得一行行扫过去。
实操建议:
- 确认文件是否真需要“行”语义:如果是固定长度记录(如某些导出数据),用
dd+skip比head/tail快几个数量级 - 频繁查同一文件不同段?先用
wc -l知道总行数,再决定用tail -n +N还是sed -n 'N,Mp'(后者在小范围精准定位时更稳) - 脚本里别写
head -n 1 file | grep ...去判断文件类型——用file或head -c 100看 magic bytes 更准也更快
真正麻烦的是那些没换行符的大 blob,或者日志轮转策略不统一的系统——这时候 head 和 tail 的“行”概念本身就失效了,得先搞清楚数据到底怎么组织。

















