上一篇文章我们过了 ls、cd、cp、mv、cat 这些最基础的指令,算是把 Linux 服务器的门推开了。今天这篇“基本指令(二)”就不再讲打开就能看懂的低级命令了,而是聊几个真正决定你能不能独立在 Linux 上干活的“高频实战指令”:find、sed、awk、scp、useradd,还有文件删错以后最快能做什么。
为什么单挑这几个出来?因为我在实际维护服务器和给组里新人做培训的过程中发现,绝大部分“事故现场”都集中在这几类命令上——要么是 find 条件写错把全盘扫了一遍拖垮负载,要么是 rm -rf 多敲了一个空格把不该删的删了,还有 scp 传文件传到一半断掉后不知道怎么续传、sed 改配置文件把编码搞乱导致服务起不来。这篇就是冲着这些场景来的,适合已经会 ls 和 cd、但想在真实服务器上独立排查问题的新手,也适合准备 Linux 相关面试但实际操作还差点意思的朋友。
1. 文件操作从“会删”到“删不后悔”:rm、软链接与硬链接
1.1 删除指令的“翻车现场”与安全删除方案
rm -rf 大概是 Linux 世界里被提起次数最多、也最容易造成事故的命令。先说一个我亲眼见过的真实案例:当时有个同事想清理某个应用目录下的临时文件,他写的命令是:
bash复制rm -rf /home/apps/tmp/*
结果执行前环境变量 $TMP_DIR 没取到值,脚本里被展开成了:
bash复制rm -rf /home/apps/tmp/
注意,这俩就差一个星号,但意思完全不一样。前者只删 tmp 目录里的内容,后者连 tmp 目录本身带里面所有的东西一起删掉。如果脚本跑在根目录下,变量为空时甚至可能变成 rm -rf /,那整个系统就直接废了。
我现在的习惯是给自己上一道保险:在所有生产服务器上给 rm 设置一个别名,让它在删除时强制确认:
bash复制alias rm='rm -i'
这个 -i 参数会在删除前逐条询问,虽然批量删除时有点烦,但关键时刻能救命。另外还有一个更稳妥的方案,就是不用 rm 删大目录,而是先 mv 到一个临时回收站目录,等过一段时间确认没问题后再统一清掉:
bash复制mkdir -p /opt/.trash
mv /home/apps/old_folder /opt/.trash/
这样既保留了一周后悔期,又不影响系统空间。等确认没用之后,再进 /opt/.trash 里手动删。
再说说为什么 rm 删掉的文件很难恢复。Linux 文件系统里删一个文件,本质上是做了三件事:把目录项标记为未使用、释放对应 inode 的引用计数、把数据块标记为可重用。文件内容本身没有立刻被清空,但那个数据块已经变成“自由状态”,随时可能被新写入的文件覆盖。所以一旦误删,立刻停止对这块磁盘的一切写入操作,再用 debugfs 这类工具尝试恢复还有一线生机,时间拖得越久希望越渺茫。这也是我把“删除前先确认、删除时用回收站、删除后马上停写”这三条当作铁律的原因。
1.2 软链接与硬链接:理解 ln 指令背后的文件系统逻辑
ln 指令在基本操作里看起来很简单,但能把它讲明白的人不多,因为它牵涉到 inode 的概念。
ln -s 创建的软链接,你可以直接理解成一个“快捷方式”。它本身是一个独立的小文件,里面存的是目标路径。目标文件被删了,软链接就变成红色断链,但链接文件本身还在。这是日常最常用的方式,比如我管理 Nginx 配置时,就常用软链接做版本切换:
bash复制ln -s /usr/local/nginx/conf/nginx.conf.v2 /etc/nginx/nginx.conf
这里有个关键点:ln -s 后面先写源文件,再写链接名,顺序和 cp 一样。我见过好几个人把顺序搞反,结果创建出来的链接指向一个不存在的路径。
而 ln 不加参数创建的硬链接,原理完全不同。硬链接不是“快捷方式”,而是给同一个 inode 起了另一个名字。这里打个比方:一个文件就像一个人,inode 是他的身份证号,目录项是他的名字,你可以有学名、小名、网名,但指向的都是同一个人。ln 就是给同一个人再增加一个名字:
bash复制ln /data/backup.tar.gz /data/backup_hard.tar.gz
执行之后,ls -l 能看到这两个文件的大小完全一样,inode 号也一样。你用任何一个名字修改内容,另一个名字的内容也会变,因为本质上就是同一个文件。硬链接不能跨文件系统创建,也不能给目录创建硬链接,这两个限制是文件系统的结构决定的。删除其中一个名字,只要还有另一个名字指向这个 inode,数据就还在。所以如果你有一个特别重要的文件,既怕手滑删掉,又不想做两份副本占空间,给它加个硬链接是成本极低的安全措施。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. find 指令:从“会查”到“精准定位”
2.1 find 的基本语法与高频参数
find 这个命令很容易被初学者忽略,因为它看起来就是“找文件”,用 ls -R 也能凑合。但真实服务器上文件数量动不动几十万上百万,ls -R 既慢又难过滤,这时候 find 就是唯一靠谱的选择。
find 的基本语法是:find [搜索路径] [匹配条件] [动作]。路径不写默认当前目录,条件不写等于全列出来,这两点要注意,路径写得越具体,扫描范围越小,执行越快。
我最常用的几个条件:
bash复制# 按文件名精确查找,-name 支持通配符
find /etc -name "nginx.conf"
# 按类型查找,f 是普通文件,d 是目录,l 是软链接
find /var/log -type f -name "*.log"
# 按修改时间查找,-mtime +7 表示超过 7 天没改过,-mtime -7 表示 7 天内有修改
find /data/logs -mtime +7 -name "*.log"
# 按文件大小查找,c 代表字节、k 代表 KB、M 代表 MB
find / -size +500M -type f
# 按拥有者或权限查找
find /home -user www
find /data -perm -002
这里解释一下 -mtime 为什么是加号和减号。+7 表示“修改时间距离现在超过 7 天”,也就是 7 天之前改过;-7 表示“7 天以内改过”。很多人死记硬背搞混,我自己的记法是:加号代表“更早”,减号代表“最近”。配合日志清理使用非常顺手:
bash复制# 找出 7 天前的日志文件并列出大小,确认后再删
find /var/log/nginx/ -name "*.log" -mtime +7 -exec ls -lh {} \;
注意 -exec 后面 {} 代表每一个找到的文件名,\; 是命令结束的标记,这个分号前面必须加反斜杠转义,不然 shell 会把分号当成自己的语法吃掉。你如果真的写漏了反斜杠,会看到 find: missing argument to -exec 的报错,这是新手特别容易踩的坑。
2.2 find 与 exec、xargs 的配合使用
find 的 -exec 可以直接对结果执行后续命令,但它有个性能问题:每找到一个文件就执行一次命令。比如你找到 1 万个文件要删,-exec rm {} \; 会启动 1 万次 rm 进程,效率很低。
更推荐的做法是配合 xargs:
bash复制find /data/logs -name "*.log" -mtime +7 | xargs rm -f
xargs 会把前面传过来的所有文件名攒成一批,然后一次性传给后面的命令。它内部还会自动处理参数长度上限,帮你分批执行,性能比 -exec 高很多。
但用 xargs 也有个隐患:如果文件名里有空格,直接传参会被拆成两个词。Linux 上的文件名我是强烈不建议用空格的,但万一你继承了别人留下的烂摊子,可以加 -print0 和 -0 这组参数来应对:
bash复制find /data -name "*.log" -mtime +7 -print0 | xargs -0 rm -f
-print0 让 find 用空字符分隔每个文件,xargs -0 按空字符识别,这样空格就不再是问题了。还有个日常高频操作是批量改权限:
bash复制find /home/apps/public -type d -exec chmod 755 {} \;
find /home/apps/public -type f -exec chmod 644 {} \;
两个命令分开跑,是因为目录和文件的权限通常需求不同。
2.3 find 与 grep 组合:定位代码和配置文件
find 只负责“找文件”,如果你还想知道哪些文件“内容里含有某个关键词”,就需要 find 和 grep 组合:
bash复制# 在 /usr/local/nginx/conf 下所有 .conf 文件里,找包含 proxy_pass 的行
find /usr/local/nginx/conf -name "*.conf" -exec grep -H "proxy_pass" {} \;
-H 让 grep 在输出时带上文件名,这样一眼就能看到是哪个文件命中了。如果不加,一行行的匹配结果看起来云里雾里。
还有一个更简洁的方式是直接 grep -r,但 find + grep 的优势在于可以组合非常精细的筛选条件,比如“只查 .conf 文件且修改时间在 3 天内”:
bash复制find /usr/local/nginx/conf -name "*.conf" -mtime -3 -exec grep -H "proxy_pass" {} \;
这两者的关系就像“用 grep -r 是开扫地机器人全屋扫一遍,用 find + grep 是划定了区域再扫”,哪个效率更高一目了然。我排查线上问题时,几乎都是先 find 缩小范围,再 grep 验证内容,两步配合基本能搞定九成的文件定位需求。
3. 文本处理三件套:grep、sed、awk 的日常救命用法
3.1 grep:筛选日志的第一手段
grep 这个指令本身就是“全局正则搜索并打印”的缩写,它做的事就是从文本里挑出匹配的行。
我在排查问题时最常用的几个场景:
bash复制# 从 Nginx 访问日志里统计某个接口被请求的次数
grep -c "/api/v1/user/login" /var/log/nginx/access.log
# 排除无关的内容,-v 是反选
grep -v "health_check" /var/log/app.log | grep "ERROR"
# 查某个关键词附近的内容,-A 2 显示匹配行后两行,-B 2 显示前两行
grep -B 2 -A 5 "OutOfMemoryError" /var/log/app.log
# 用正则匹配 IP,-E 开启扩展正则
grep -E "^192\.168\.1\.[0-9]+" /var/log/nginx/access.log
真要说效率的话,grep 本身很快,但如果日志文件特别大,几 GB 甚至几十 GB,建议先按时间范围用 sed 切一段再 grep,别上来就全文件扫描。这里的核心思路和写代码一样,先在入口处缩小数据量,再精查。
还有一个很容易被忽略的点:grep 在管道里出现时,前面命令的输出如果最后没有换行符,grep 可能会把最后一行吞掉。解决办法是在管线最后加一个 echo 或者用 grep -a 按文本处理。这个情况在解析某些不规范的配置文件时偶尔会遇到,知道有这回事就行。
3.2 sed:流式编辑与常见的乱码问题
sed 全称是“流编辑器”,它最大的特点是不用打开文件就能编辑内容。日常最常用的三个场景是替换、插入、删除。
替换的语法是:
bash复制sed 's/旧内容/新内容/g' 文件名
其中 s 是替换命令,g 表示行内所有匹配都替换,不加 g 就只替换每行第一个匹配。这行的输出会打印到屏幕,但不会真正改文件。如果要真正修改,加 -i:
bash复制# 把配置文件里的旧 IP 全部替换成新 IP
sed -i 's/192.168.1.100/192.168.2.100/g' /data/app/config.yml
这里必须提醒一句:-i 是危险的,它直接改原文件,没有备份。稳妥做法是让 sed 自动生成备份文件:
bash复制sed -i.bak 's/192.168.1.100/192.168.2.100/g' /data/app/config.yml
执行完你会看到目录里多了一个 config.yml.bak 文件,这就是原始内容。我现在每次用 sed -i 都会带上 .bak 后缀,虽然看起来多了一个文件,但回滚时你会感谢这个习惯。
还有一组思路不一样的用法:用 sed 做行号定位和打印:
bash复制# 只查看第 20 行到第 30 行
sed -n '20,30p' /var/log/app.log
# 删除第 5 行到第 10 行,并写入原文件
sed -i '5,10d' /var/log/nginx/error.log
热词里有人搜“linux sed 打印出来有乱码”,这个问题我也碰到过。sed 本身是按字节处理文本的,不会自动感知 UTF-8 的编码边界。如果你的文件本身是 GBK 或者 GB18030 编码,直接用 sed 替换中文的时候就可能在某个中文字符的中间切了一刀,导致替换结果乱码。
解决这个问题有一个标准流程:先 file config.yml 看文件编码,如果是 GBK 就先用 iconv 转成 UTF-8 再操作:
bash复制# 查看文件编码
file /data/app/config.yml
# 如果输出是 ISO-8859 或 GBK 这类编码,先转成 UTF-8
iconv -f GBK -t UTF-8 config.yml > config_utf8.yml
转完再跑 sed,就不会出现乱码了。这一步很多网上教程不提,但实际运维里碰到编码问题的人一抓一大把。
3.3 awk:提取字段的利器
awk 在文本处理里是一个偏“编程型”的工具,它的核心能力是按列提取和按条件统计。
最基础的用法是取列。默认按空格或 Tab 分隔:
bash复制# 打印 access.log 里的第 1 列(通常是 IP)和第 7 列(通常是请求路径)
awk '{print $1, $7}' /var/log/nginx/access.log
如果分隔符不是空白,用 -F 指定:
bash复制# 按逗号分隔,取 CSV 的第 2 列
awk -F',' '{print $2}' /data/export.csv
取列只是入门,awk 真正强大的地方是“统计”。比如我想知道访问日志里哪个 IP 请求量最大:
bash复制awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
这个管道链可以说是日志分析里最经典的组合拳。awk 提取 IP,sort 排序,uniq -c 统计次数,再按次数倒序,最后取前 20 名。一行命令完成一个简单的访问排行。
awk 还能做数值判断。比如日志最后一列是响应耗时,我想找出所有耗时大于 2 秒的请求:
bash复制awk '{if ($NF > 2.0) print $0}' /var/log/nginx/access.log
这里的 $NF 表示“每行的最后一个字段”。如果是逗号分隔的 CSV,整条记录长这样:order_id,amount,user_id,status,你用 $NF 就能直接取到 status,不用死记它是第几列,灵活很多。
awk 还有一个变量 NR 表示“当前读到了第几行”,可以用来跳过表头、统计总行数。它配合判断条件能做的统计比 grep 多得多,比如统计所有 4xx 状态码的请求占比:
bash复制awk '{if ($9 ~ /^4/) count4++ ; total++} END {print "4xx占比:", count4/total*100, "%"}' /var/log/nginx/access.log
这个例子里的 END 关键字意思是所有行处理完之后执行一次,逻辑上就是先累计变量再算比例。awk 的内容其实可以单独写一本书,日常用得最多的还是取列、按条件过滤、按行号打印这三板斧,把这几个练熟就足够应付绝大多数场景了。
4. 用户管理与权限:新建用户背后的完整流程
4.1 useradd 新建用户的完整操作
热词里大量出现“linux新建用户”,说明这是很多人实际工作的硬需求。新建用户在 Linux 上不是简单敲一句 useradd 用户名 就完事,需要考虑很多东西。
一条比较标准的建号命令是这样:
bash复制useradd -m -s /bin/bash -G docker,devops deploy
-m 表示创建用户的同时创建家目录 /home/deploy,-s 指定登录 shell,-G 表示把用户加入附加组,这样它就能使用 docker 命令或同时拥有多个组的权限。
如果你不给 -m,某些 Linux 发行版默认是不会自动创建家目录的,导致用户登录后 cd ~ 会直接进入根目录或者报 No such file or directory,而且 HOME 环境变量是空字符串,很多程序会因此出问题。我第一次用 CentOS 的极简安装版时就在这里吃过亏,建了一个用户后发现家目录不存在,还要手动 mkdir 和 chown 修正。
创建完用户马上要设置密码:
bash复制passwd deploy
运行后会提示输入两次密码。passwd 命令本身不会回显输入内容,这是正常现象,别以为键盘失灵了。
还有一种场景是给某个应用创建服务账号,该账号只需要运行程序,不需要登录系统。这时候用:
bash复制useradd -M -s /sbin/nologin app_service
-M 表示不创建家目录,/sbin/nologin 表示禁止登录。这样即使有人尝试 su 到这个账号,也会被拒绝,安全性和规范性都更好。现在常见的 Nginx、MySQL 等软件安装后自动创建的用户就是这个套路,你可以去 /etc/passwd 文件里看看,最后一行类似 nginx:x:997:995:Nginx web server:/var/lib/nginx:/sbin/nologin,一眼就能理解。
4.2 用户删除与家目录处理的讲究
删除用户有两条路线:
bash复制# 只删用户,保留家目录和文件
userdel deploy
# 连用户的家目录和邮件池一起删
userdel -r deploy
这两个选择不是随意的。如果保留家目录,后续你可以用 root 权限去 /home/deploy 里抢救重要数据。如果确定这个用户彻底没用了,就直接 -r 删干净,避免留下一个没人维护的目录占用空间。
删除前还应该做两件事:一是确认没有进程还在以这个用户身份运行,二是确认没有文件仍属于这个用户。检查进程用:
bash复制ps -u deploy
检查文件归属用:
bash复制find / -user deploy -type f 2>/dev/null
如果直接 userdel 而进程还在跑,可能会出现所谓的“僵尸 uid”,就是系统里看到一个数字用户 ID 但没有对应的用户名,查起来特别头大。所以删用户之前的检查不能省。
4.3 权限模型与 sudo 的最小化授权
Linux 权限模型里,每个文件有三个身份级别:属主 u、属组 g、其他人 o;每种身份有三个权限:读 r(4)、写 w(2)、执行 x(1)。数字权限就是这三者加和,比如 755 是属主可读写执行、属组可读可执行、其他人可读可执行。
日常改权限用得最多的两类:
bash复制# 把目录交给某个用户,-R 递归处理子目录
chown -R deploy:devops /data/app
# 赋权:目录给 755,文件给 644
chmod -R 755 /data/app
find /data/app -type f -exec chmod 644 {} \;
目录需要有执行权限才能进入,所以你把目录设成 644 后自己都会进不去,报 Permission denied。这个坑我见过不少人踩过,给目录赋权时千万不要只给读权限。
再说 sudo。很多人图省事,直接给一个用户所有 root 权限:
bash复制usermod -aG wheel deploy
在 CentOS 系里,加入 wheel 组就等于默认能用 sudo 执行所有命令。但生产环境我建议做最小化授权,只开用户真正需要的命令,用 visudo 编辑 /etc/sudoers 文件:
bash复制deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx
这句话的意思是:允许 deploy 用户在任意主机上,不用输密码就能执行 systemctl 重启和重载 Nginx 这两条命令,其他命令不行。这样即使这台服务器被攻破或用户乱操作,损伤范围也控制在最小。最小权限这个原则,在 Linux 运维里值得反复强调,真正生产中遇到的安全问题,大部分都是权限给得太宽造成的。
4.4 组与用户切换的使用场景
组的核心作用是把权限批量授给一类人。你不需要逐个给十个用户配权限,只要把这十个人加进同一个组,再对这个组授权一次就行。
日常操作:
bash复制# 把用户加入容器管理组
usermod -aG docker deploy
# 查看用户所属的所有组
groups deploy
注意 -aG 的 -a 表示追加,如果不加 -a,新指定的组会覆盖用户的原有附加组,这个副作用很容易忽略。
切换用户的指令也一并说一下。su - username 会切换到目标用户并加载目标用户的环境变量,sudo -i 则是直接获得 root 的登录 shell。两者在脚本自动化里用得很多,但要注意无论哪种方式,都要明确当前身份,别在一个会话里切来切去搞混了。查看当前身份用 whoami,这条命令虽然简单,但关键时刻能帮你确认自己到底是谁。
5. 远程传输:scp 与 rsync 的实操对比
5.1 scp 的基本用法与免密配置
在服务器之间传文件,最直接的指令就是 scp。它的底层走的是 SSH 协议,本身是加密的,所以跨节点传文件时不需要额外装服务端,只要对方开了 SSH 就行。
推文件到远端:
bash复制scp /data/backup.tar.gz root@192.168.2.10:/data/
从远端拉文件到本地:
bash复制scp root@192.168.2.10:/data/backup.tar.gz /data/
如果远端 SSH 端口不是默认的 22,要用 -P 指定端口,注意是大写 P:
bash复制scp -P 2222 /data/backup.tar.gz root@192.168.2.10:/data/
很多新手在用 scp 时习惯用小写 -p,但这个参数表示“保留文件的时间戳”,和端口没关系,会被忽略甚至报错。
传整个目录要加 -r:
bash复制scp -r /data/app_code root@192.168.2.10:/data/
免密登录是提高 scp 效率的关键。先在本机生成密钥对:
bash复制ssh-keygen -t ed25519
生成过程中一路回车即可,默认存放在 ~/.ssh/id_ed25519。然后把公钥传到目标机器:
bash复制ssh-copy-id -i ~/.ssh/id_ed25519.pub root@192.168.2.10
执行一次后,以后 scp 和 ssh 就不需要再输密码了。这个操作对自动化脚本特别重要,因为脚本里写密码既不安全也不会被系统认可,而密钥认证是天生的脚本友好方式。
5.2 rsync 增量同步
scp 在传大文件或大目录时的短板是:如果传输中断,就得从头再来。rsync 正是为此而生,它最大的特点是“增量传输”,只会传输两个目录之间有差异的部分。
一个常用的同步命令:
bash复制rsync -avz --progress /data/app_code/ root@192.168.2.10:/data/app_code/
-a 是归档模式,保留权限、时间戳、软链接等信息;-z 开启压缩,传到远端再解压;--progress 显示传输进度。
需要注意尾部斜杠的含义。rsync /data/app_code/ 目标 表示同步目录内的内容,而 rsync /data/app_code 目标 表示把整个目录作为一层放进去。这个区分和我之前讲软链接顺序一样,都是文档里写得隐晦、实际踩坑无数的地方。在写定时同步任务前,最好先 rsync -avz --dry-run 跑一遍预览一下,确认同步范围再真正执行。
如果目标是让两端目录完全一致,加 --delete:
bash复制rsync -avz --delete /data/root_dir/ root@192.168.2.10:/data/root_dir/
--delete 的意思是远端多了而本地没有的文件会被删除,让远方完全镜像本地。这个参数非常有用,但也非常危险,一不小心会把远端大量文件清掉。我会在首次使用 --delete 前,先在本地做一次完整测试,或者先备份远端目录。生产环境里因 --delete 用错导致远端目录被清空的案例不少,谨慎为主。
5.3 传输中断的排查思路
scp 或 rsync 传到一半失败,不要急着重跑。先确认几个方面:
一是目标磁盘是否满了,看 df -h,如果 Use% 接近 100%,那肯定写不进去,先把空间清出来再续传。
二是网络稳定性。大文件传几个 G 时,网络抖动会导致 SSH 连接断开。这时如果用的是 rsync,直接重新执行同样的命令就行,它会自动跳过已经传完的部分,不会从头再来。scp 则没有这个能力,所以我个人传超大文件时首选 rsync。
三是权限问题。目标目录如果不是当前用户可写的,会报 Permission denied,可以先用 ls -ld 确认目标目录的权限和属主。
四是看看是不是 SSH 服务端的连接数限制。如果并发连接太多,偶尔会被拒绝,查看服务端日志 /var/log/secure 或 /var/log/auth.log 能确认。
6. 常见问题速查与排查技巧实录
我把实操里反复出现的问题整理成了一个表格,方便各位按图索骥:
| 常见问题 | 现象 | 排查思路 |
|---|---|---|
| rm -rf 误删文件 | 目录消失、服务异常 | 立即停止对该分区的一切写入,尝试用 debugfs 等工具恢复;后续启用回收站习惯 |
| find 查找太慢 | 命令长时间无输出 | 把搜索路径尽量收窄,不要把 / 当路径一上来就全盘扫描 |
| sed 替换后中文乱码 | 替换结果变成 ?? 或乱字符 |
先用 file 查编码,GBK 文件先 iconv 转成 UTF-8 再操作 |
| scp/rsync 传输中断 | 进度条卡住或报 connection reset | 确认磁盘空间、网络稳定性、目录权限;用 rsync 断点续传 |
| useradd 后没有家目录 | 用户登录提示无 HOME | 创建时加 -m,或事后 mkdir -p /home/用户 并 chown |
| 权限不足 Permission denied | 无法读文件或进目录 | 检查文件属主、目录执行权限、当前用户是否在对应组里 |
| grep 搜到了但看不见文件名 | 多文件匹配时不知道哪个文件命中 | 加 -H 或 -l,一个显示文件名加内容,一个只显示文件名 |
还有一个经常被问到的:find、grep、sed、awk 哪个更厉害?我的回答是,它们不是替代关系,而是流水线关系。find 负责找文件,grep 负责筛行,sed 负责按规则改,awk 负责按列统计。真正要解决问题时,几乎都是几个命令用管道串起来一起用。
日志分析的一个综合例子,把访问量最大的 10 个 IP 和它们访问的路径一起列出来:
bash复制awk '{print $1, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
这套组合我已经用了很多年,基本涵盖了日常运维和排查问题的真实需求。如果哪一天你在服务器上执行命令报错了,也别慌,先仔细看报错信息,Linux 的命令行报错其实已经写清了九成的原因,剩下的就是去查英文单词。
还有一个技巧收尾时顺便说一下:如果记不住某个命令的参数,在命令后面加 --help 通常会给出简明的用法说明,配合 man 命令查看完整手册,比到处搜索快得多。Linux 的文档体系和命令帮助信息就在系统里,只要你愿意看,它就是你最好的老师。
