很多人学 Linux 基本指令的时候,第一周背完 ls、cd、cp、mv、rm,觉得自己已经入门了;真到了要处理一个实际任务,比如找一个大文件、批量改配置、给同事开个账号、把本机文件传到服务器,就发现自己除了 cd 和 ls 几乎帮不上忙。这篇是 002-Linux 基本指令(二),我打算换一种讲法:不按命令手册顺序往下背,而是围绕真实使用场景,把高频的 Linux 基本指令拆开讲清楚,重点放在 find、grep、sed、awk、useradd、scp、ss 这一批你迟早会用到的命令上。如果你已经会了 ls、cat、mkdir,但面对上面那些任务还很懵,这篇就是写给你的。我不会把它写成命令大全,只想把那些真正卡过人的地方讲透。
1. 从"删库"到"找文件":rm 和 find 的正确打开方式
先回答一个常年霸榜的问题:怎么删文件夹。热搜里“linux 删除文件夹命令”几乎是长年置顶,说明很多人第一次认真使用 Linux 命令,就是从删东西开始的。删文件夹这件事,在 Linux 里有两套答案:一套是 rmdir,一套是 rm -r。rmdir 只能删空目录,里面但凡有一个文件就会报错;rm -r 是递归删除,能一路删到底,配合 -f 就是强制删除。两个命令的差别,本质上就是“只删外壳”和“连内容一起删”的差别。
1.1 rm、rmdir 与 rm -rf 的边界,以及删错之后的急救思路
先说清楚 rm -rf 为什么危险。-r 表示递归,只要给了这个参数,rm 会一层一层进入子目录把所有文件清掉;-f 表示 force,文件不存在时不报错、不询问、直接过。结合起来就是一个“不问任何意见、一路全删”的执行者。现代发行版对 rm -rf / 有保护,不会允许你一句命令把整个系统清空,但 rm -rf ~、rm -rf ./*、rm -rf /data/ 这种写法,一旦在错误的目录下执行,代价完全可能是整个家目录或者整个数据盘。
我见过太多因为在路径末尾多打了一个空格,或者把 ./ 写成了 ../ 导致的删错事故。所以个人习惯是:涉及递归删除的操作,先在前头加 echo 跑一遍,比如 echo rm -rf ./xxx,确认输出里是你要删的那条路径再真正执行。或者在目录里先 ls -la 看一眼,确认自己在哪,再动手。
如果真的删错了,普通文件在 ext4、xfs 这类文件系统上恢复成本很高,最要紧的是立刻停止往这个分区写入新数据,越晚动手,被覆盖的痕迹越少。有一个现实的急救场景可以记住:如果文件还被某个正在运行的进程占用,lsof | grep deleted 能看到残留的文件描述符,可以到 /proc/PID/fd/ 路径下把内容拷回来。这条命令不算基础,但当删错的文件恰好是正在运行的日志或者临时文件时,它真的能救命。如果你的文件没有被任何进程占用,那就只能考虑 extundelete 这类工具,并且前提是分区已经不再写入。这里不建议新手一上来就折腾恢复工具,多数情况下你会花掉大量时间却一无所获,养成删除前确认的习惯远比学会恢复重要。
1.2 find 的日常用法:按名称、时间、大小找到你要的文件
find 的基本格式是 find 路径 条件,它从指定路径开始,一层一层往下走,把符合条件的文件全部列出来。理解这一点很重要,因为 find 的输出经常是一长串路径,而不是单个结果。
举一个真实的例子。上周我在一台服务器上发现磁盘快满了,df -h 显示根分区已经用了 92%。我没有靠肉眼去翻目录,而是直接用 find 按大小筛:
bash复制find / -xdev -type f -size +500M -exec ls -lh {} \;
解释一下这条命令:-xdev 表示不要进入其他文件系统,避免把 /proc、/sys 这些虚拟目录也遍历一遍,也避免去扫挂载的其他磁盘;-type f 限定只找普通文件;-size +500M 就是大于 500M 的文件;后面的 -exec ls -lh {} \; 把每个找到的结果交给 ls -lh 显示出来,这样你能直接看到是哪些大文件占满了磁盘。结果一出来,膨胀的日志文件、上传的临时包立刻暴露无遗。
按时间查找也很常用。比如我想找 /home 下最近 7 天改过的所有 .conf 配置文件:
bash复制find /home -name "*.conf" -type f -mtime -7
-mtime -7 是修改时间在 7 天之内,如果你想找 7 天前改过的旧文件,就用 +7。对应的还有 -atime(访问时间)、-ctime(状态变化时间),日常用得最多的就是 -mtime。文件名匹配的关键点在于通配符一定要加引号,find -name 后面的 "*.conf" 如果不用引号包起来,shell 会在 find 执行前就尝试展开通配符,结果和你预期的完全不一样。
这里可以整理一个 find 条件速查表,方便日常查阅:
| 场景 | 命令 |
|---|---|
| 按名字找文件 | find /path -name "*.log" |
| 忽略大小写找名字 | find /path -iname "readme*" |
| 按修改时间找 7 天内的文件 | find /path -mtime -7 |
| 按大小找大于 500M 的文件 | find /path -type f -size +500M |
| 只找目录或只找文件 | find /path -type d / find /path -type f |
| 找到后查看详情 | find /path -exec ls -lh {} \; |
1.3 把 find 与 rm 结合起来的安全姿势
很多教程会把 find 和 -delete 放一起讲,比如清空 30 天前的日志:
bash复制find /var/log/nginx -name "*.log" -mtime +30 -delete
这条命令本身没问题,但我强烈建议新手先不写 -delete,改成 -print 预览一遍:
bash复制find /var/log/nginx -name "*.log" -mtime +30 -print
看到输出的每一行都是你有意要删的文件,再补上 -delete。这个习惯能在批量删除里帮你避开大多数误删事故。因为 -delete 一旦执行,find 会一边遍历一边删,中途发现不对想按 Ctrl+C 已经来不及了。这里的原理是 find 的 -exec 和 -delete 都具备“对结果执行操作”的能力,所以它不仅是查找命令,也是批处理命令。理解到这一层,你才算真正用到 find 的核心价值。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文本处理三件套:grep、sed、awk 的分工与配合
在 Linux 命令行干活,最大的舒适区是你几乎不用打开编辑器,就能在管道里对文本做筛选、修改、统计。基本指令里,grep、sed、awk 这三条必须过一遍。用一个生活化的类比来区分它们:grep 是筛子,把要的行留下来;sed 是手术刀,对文本做精准的修改;awk 是计算器,把文本拆成列后做统计和汇总。
2.1 grep:在日志和输出里快速筛出关键行
grep 的作用是行过滤,输入多少行,符合条件就留下哪些行。十万行的日志交给它,它也能按行扫完,把匹配的行输出。这是排查日志最基础也最高效的方式。
一个常见问题:nginx 报错日志里出现大量 500,我想看最近的错误上下文。直接 grep 500 /var/log/nginx/error.log 会把所有带 500 的行打出来,但如果我想知道这个错误是在什么请求、什么上游状况下出现的,就需要带上上下文:
bash复制grep -n -B 2 -A 5 "500" /var/log/nginx/error.log
-B 2 表示同时打印匹配行的前 2 行,-A 5 表示打印后 5 行,-n 显示行号。排查问题时,上下文往往比匹配行本身更有价值,你能一眼看到出错前的请求路径和出错后的处理结果。
其他几个高频参数也值得记熟:
-i忽略大小写:grep -i error file,Error、ERROR、error都能匹配上。-v反向匹配:grep -v "^#" /etc/nginx/nginx.conf,去掉注释行,看有效配置。-c计数:grep -c "timeout" access.log,直接得到出现次数。-r递归:grep -r "password" /etc/nginx/,遍历目录下所有文件。
很多人第一次用 ps aux | grep nginx 时,会发现输出里多了一条 grep nginx 进程。这是因为 grep 在运行时命令行里也带着 nginx 字样,所以它自己也被匹配到了。解决方法要么是 grep -v grep,要么直接改用 pgrep -l nginx,后者更干净,后面讲进程时再展开。
2.2 sed:在流里替换、删除、输出指定行
sed 的全称是 stream editor,流编辑器。它和 vim 这类交互式编辑器的区别是,它不需要把整个文件打开,而是“读一行处理一行,然后输出”,因此特别适合在管道里做批量文本修改。
最常见的用途是替换。比如我想把 nginx 配置里的端口从 8080 改成 9090:
bash复制sed 's/8080/9090/g' nginx.conf
这个命令会把输出里的所有 8080 替换成 9090,但不会改原文件。真正要落盘,需要加 -i:
bash复制sed -i 's/8080/9090/g' nginx.conf
注意 sed -i 是原地修改,而且默认不备份,一旦替换表达式写错,配置就被改坏了。稳妥做法是先不加 -i 预览输出,确认无误后再加;或者用 sed -i.bak 's/8080/9090/g' nginx.conf,这样会生成一个 nginx.conf.bak 备份文件。另外要注意,GNU sed 和 BSD sed 在 -i 后面接不接后缀的行为有差异,在 macOS 上写 sed -i .bak 和 Linux 上的 sed -i.bak 经常不通用,跨平台时尽量先验证一下。
sed 还能按行号操作。查看第 10 到第 20 行:
bash复制sed -n '10,20p' /etc/passwd
-n 是安静模式,不输出每一行;最后的 p 是打印,两个配合才有显示指定行的效果。没有 -n 时,sed 默认会重复打印内容,输出会很乱,这个组合一定记牢。
2.3 awk:按列拆分和简单统计,让输出变成数据
awk 的定位是“按列处理的编程语言”,但在基本指令阶段,你只需要掌握几个套路就够用了。
第一,取列。用默认空白分隔符,打印第 1 列和第 3 列:
bash复制awk '{print $1, $3}' /etc/passwd
如果分隔符不是空格,比如 /etc/passwd 用的是冒号,需要 -F 指定:
bash复制awk -F: '{print $1, $7}' /etc/passwd
这样就能把用户名和登录 shell 拉出来。命令里 $1 代表第 1 列、$7 代表第 7 列,NF 代表当前行总列数,这些都是 awk 的内置变量。
第二,统计。想知道一个文件有多少行,很多人会用 wc -l,awk 也能做:
bash复制awk 'END{print NR}' access.log
END 表示在所有行处理完之后执行一次,NR 是 awk 内置的“当前行号”,所以在 END 块里打印 NR 就是总行数。
第三,汇总统计。比如从一份 access 日志里统计各种状态码出现多少次:
bash复制awk '{print $9}' access.log | sort | uniq -c
把每行第 9 列(状态码)取出来,sort 排序后 uniq -c 统计次数。这四段简单指令串起来,就是一个极简的日志分析管道。同理你可以统计某个 IP 出现的次数、某个接口被调用多少次,把文本输出变成真正的数据。
3. 新建用户背后的权限体系:useradd 只是第一步
搜索词里“linux 新建用户”的热度一直很高,但实际工作中你很少只敲一条 useradd 就算完事。建用户只是开始,后面至少还要设置密码、分配组、限制权限、配置 sudo,这一串操作涉及好几条指令,而且发行版之间的行为差异很大。
3.1 useradd 与 adduser 的发行版差异
最容易被坑的一点:useradd 和 adduser 在 Debian/Ubuntu 系和 CentOS/RHEL 系的行为完全不同。
在 Debian/Ubuntu 上,adduser 是一个 Perl 脚本,它会交互式地问你密码、全名、要不要设置主目录,对新手很友好;而 useradd 是底层命令,执行后默认不创建家目录、不设置密码,只是创建一个“空壳用户”。在 CentOS/RHEL 上则反过来,useradd 默认会创建家目录,还会创建同名的基本组;adduser 只是 useradd 的符号链接,不提供交互式引导。
所以你在网上搜到的教程,如果不是同一个发行版,照抄很容易出问题。我的建议是:用 useradd 配合显式参数,行为最可控:
bash复制useradd -m -s /bin/bash zhangsan
passwd zhangsan
-m 创建家目录,-s 指定登录 shell,然后 passwd 设置密码。这一步做完,一个能登录的基本用户才算真正建好。
3.2 用户目录、sudo 授权和文件属主的联动关系
用户建好了,后面会遇到“给新用户加 docker 组”“把某个目录的属主改成这个用户”“设置目录权限”这一串。对应指令分别是 usermod、chown、chmod。
给用户加辅助组:
bash复制usermod -aG docker zhangsan
-aG 是追加组,注意一定要带 -a,否则会把用户从原来的组里清出来重设,这是一个非常隐蔽的坑。
修改文件属主和权限:
bash复制chown zhangsan:developers /data/project
chmod 750 /data/project
chown 把属主改为 zhangsan、属组改为 developers;chmod 750 表示属主可读可写可执行、属组可读可执行、其他人没有任何权限。数字权限的算法是 r=4、w=2、x=1,所以 7=4+2+1、5=4+1、0=0。这是 Linux 权限系统的基础,新手一定要自己手动算几轮,而不是遇到权限问题就 chmod 777。关于 777 多说一句:不是不能用,而是要想清楚“让所有用户都可读可写可执行”是不是你真正要的。在生产环境目录上无脑 777,等于绕过权限系统,出了问题很难追责。
3.3 visudo 授权和免密 sudo 的注意事项
给用户 sudo 权限,标准做法不是直接编辑 /etc/sudoers,而是用 visudo。因为 visudo 在保存时会做语法检查,语法错误会被拦住,不会把系统搞到 sudo 全部不可用。直接 vim /etc/sudoers 一旦写错格式,sudo 就全废了,必须进单用户模式修复,折腾很久。
在 Ubuntu/Debian 上,把用户加入 sudo 组是最简单的授权方式:
bash复制usermod -aG sudo zhangsan
在 CentOS/RHEL 上,对应的组名是 wheel:
bash复制usermod
