Skip to content

查看与编辑文本 ​

tail -f 和 vi 是运维使用频率最高的两条命令。前者有个日志切割后失效的坑,后者有"怎么退出"的经典问题。

一、整体查看 ​

bash
cat -n /etc/hosts
tac /var/log/boot.log | head
wc -l /etc/nginx/nginx.conf
file /data/app.jar
text
     1	127.0.0.1   localhost localhost.localdomain
     2	::1         localhost localhost.localdomain
     3	10.0.0.31   kafka-1
     4	10.0.0.32   kafka-2

148 /etc/nginx/nginx.conf
/data/app.jar: Java archive data (JAR)

cat 只适合小文件。几百 MB 的日志用 cat 会把终端卡死几十秒。

二、less:看大文件 ​

bash
less /var/log/messages
按键作用
空格 / b下一页 / 上一页
g / G开头 / 结尾
/keyword向下搜索,n 下一个,N 上一个
?keyword向上搜索
F实时跟随(类似 tail -f),Ctrl+C 退出跟随
-S不折行(长行横向滚动)
q退出
:n打开下一个文件(多文件时)

less +F file 直接进入跟随模式,比 tail -f 更好的地方是可以随时 Ctrl+C 回去翻历史。

三、head / tail ​

bash
head -20 app.log
tail -20 app.log
tail -n +100 app.log        # 从第 100 行开始到结尾
tail -c 1k app.log          # 最后 1KB(按字节)
tail -f app.log             # 跟随
tail -F app.log             # 跟随,文件被轮转后自动重开
text
2026-10-27 21:14:02 INFO  health check ok
2026-10-27 21:14:07 INFO  health check ok

日志切割后 tail -f 会失效

logrotate 把 app.log 重命名成 app.log.1、再建一个新的 app.log 时,tail -f 仍然盯着旧 inode,你会看到日志"不再更新"。

用 tail -F(大写 F,等价于 --follow=name --retry)会自动检测文件被替换并重新打开。生产环境一律用 -F。

常用组合:

bash
# 只跟某个关键字
tail -F app.log | grep --line-buffered -i error

# 跟多个文件,带文件名前缀
tail -F app.log error.log

# 时间范围(需要日志里有时间戳)
tail -F app.log | grep '2026-10-27 21:'

grep 不加 --line-buffered 时输出会被缓冲,看起来像"卡住"。管道接 grep 一定要加。

四、vi 生存指南 ​

打开:

bash
vi /etc/nginx/nginx.conf

三种模式:

text
普通模式(默认)  --i / a / o-->  插入模式
      ^                              |
      |                              |
      +------ Esc -------------------+
      |
      +-- : /  --->  命令/搜索模式(Esc 返回)

常用操作 ​

操作作用
i光标前插入
a光标后插入
o下一行插入
Esc回到普通模式(先按这个再做别的)
:w保存
:q退出(未修改时)
:wq 或 ZZ保存并退出
:q!不保存强制退出(改错了用它)
dd删除当前行
yy + p复制当前行 + 粘贴
u撤销
/keyword搜索,n 下一个
gg / G文件头 / 文件尾
:%s/old/new/g全文替换
:set nu显示行号

卡在 vi 里出不来

按 Esc,再输入 :q! 回车。如果提示 E37: No write since last change,说明有未保存修改,:q! 就是丢弃修改退出。

如果连 Esc 都没反应,可能是终端问题:按 Ctrl+C,再 Esc,再 :q!。

配置文件改之前留个备份:

bash
cp -a nginx.conf nginx.conf.$(date +%F-%H%M)
vi nginx.conf

改完先验证再 reload,比如 nginx -t、sshd -t。

五、diff:改了什么 ​

bash
diff -u nginx.conf.orig nginx.conf
diff
--- nginx.conf.orig	2026-10-27 21:14:02
+++ nginx.conf	2026-10-27 21:18:41
@@ -12,7 +12,7 @@
 http {
     include       mime.types;
     default_type  application/octet-stream;
-    sendfile        off;
+    sendfile        on;
     keepalive_timeout  65;
 }

-u 是 unified 格式,- 行是被删的,+ 行是新增的。-y 并排显示,-r 递归比较目录。

bash
diff -r /etc/nginx /data/backup/nginx-2026-10-27
vimdiff a.conf b.conf          # 可视化对比

六、编码与换行 ​

bash
file -i app.conf
text
app.conf: text/plain; charset=iso-8859-1
bash
# 转编码
iconv -f GBK -t UTF-8 app.conf -o app.conf.utf8

# 看有没有 Windows 换行
file app.sh
cat -A app.sh | head -3
text
app.sh: ASCII text, with CRLF line terminators

#!/bin/bash^M$
echo hello^M$

^M 就是 CR。Shell 脚本带 CRLF 会报 bash: ./app.sh: /bin/bash^M: bad interpreter。

bash
# 去掉 CR
sed -i 's/\r$//' app.sh
# 或
dos2unix app.sh

在 Windows 上编辑过的脚本

用 Notepad、VS Code 默认可能存成 CRLF。放到 Linux 上执行前先 file 看一下,或者用 dos2unix 批量处理:

bash
find /opt/app/scripts -name '*.sh' -exec dos2unix {} +

七、快速查某个配置在哪 ​

bash
grep -rn 'worker_connections' /etc/nginx/
grep -rn --include='*.conf' 'proxy_pass' /etc/nginx/
text
/etc/nginx/nginx.conf:14:    worker_connections  1024;

-r 递归,-n 带行号。比 find | xargs grep 更直接(且不会因为文件名有空格而炸)。

八、踩过的坑 ​

现象根因处置
tail -f 日志不动了日志被轮转,盯的是旧 inode用 tail -F
tail -f | grep 看起来卡住grep 输出缓冲grep --line-buffered
cat 卡住几分钟文件太大或二进制用 less / head
vi 里输入 :wq 没反应还在插入模式先 Esc
脚本报 bad interpreter: ^MCRLF 换行dos2unix
改了配置不生效忘了 reloadnginx -t && nginx -s reload
diff 全是改动一边文件是 CRLFdos2unix 后再比