接触 Linux 命令行越久,我越发现,真正让你在服务器上从容工作的,不是背下来的命令数量,而是对几十条常用命令的理解深度。我见过不少新人,能把命令手册翻得很熟,可真到日志报错、磁盘占满、服务起不来这类场景,还是会手忙脚乱。这篇文章是我从日常运维和开发实战中筛出来的一份命令清单,覆盖文件操作、文本处理、权限与进程、网络调试、软件安装与日志排查,每条命令都说明它解决什么问题、有哪些容易踩的坑,以及值得写进脚本里的用法。无论你是刚装好 Linux 的初学者,还是有一定经验但想在细节上补课的开发者,都能在这里找到可以直接照着用的命令组合。
1. 文件与目录操作:日常使用最高的命令背后有哪些坑
1.1 ls 的完整用法:你以为只是一条目录列表命令
很多人初学 Linux 时,敲的第一个命令就是 ls,可大多数人的用法停留在“输入 ls 然后回车”,最多加一个 -l,后面就一概不知了。其实 ls 是参数最丰富、也最值得花几分钟研究的基础命令,因为它直接决定了你每天看到的文件信息量。我最常用的组合是 ls -lha。-l 以长格式输出,权限位、属主、属组、文件大小、修改时间一目了然;-h 会把文件大小自动转换成 12K、34M 这类易读单位,避免你看到一长串字节数时还要心算除以 1024;-a 则把隐藏文件一并显示出来。
隐藏文件通常不是安全机制,而是一种约定。家目录下的 .bashrc、项目目录下的 .git,平时不显示是为了不让视野被配置类文件干扰,但当你真正需要检查环境或项目状态时,看不到它们反而会出大问题。我还建议在 shell 配置里加一个别名,例如 alias ll='ls -lha',这样以后在任意目录下敲 ll,就能一次看到最完整的信息。如果遇到磁盘占满但不知道是什么文件导致的,可以用 ls -lhS 让文件按大小排序,最大的文件排在最前面,几分钟就能定位到是谁把存储空间撑满了。这个组合我在给同事讲问题时几乎每次都推荐,实践价值确实很高。
提示:ls 并不适合长期监控文件变化。要等日志文件开始写入,用 tail -f 更合适;要观察一个目录里不断生成新文件,可以用 watch -n 2 'ls -l /目录',命令每两秒自动刷新一次,比手动反复敲键盘强得多。
1.2 cd 与路径理解:相对路径和绝对路径的差距
cd 命令本身的语法很简单,真正的重心在于你对路径体系的理解。Linux 的目录结构是一棵从根目录 / 开始的树。绝对路径会从 / 开始一直描述到目标位置,写法固定,不受当前环境的影响;相对路径则以当前目录为参照,里面最常见的两个记号是 . 和 ..,分别表示当前目录和上一层目录。很多初学者会在这棵树上迷路,但解决路径问题有一个很笨但很有效的办法:打完 cd 之后,立刻按 Tab 键让 bash 自动补全。命令补全不仅能减少输入错误,更重要的是,它会展开目录名,让你在切换之前先看到接下来有哪些可选方向,手打路径最容易犯的错误在这里直接就被挡掉了。
有一个很多资料很少提到的细节:cd - 会在当前目录和上一个所在目录之间来回切换。当你在两个纵深很深的目录之间反复操作时,这个参数能省下大量输入长路径的时间。更现代一点的做法是使用 pushd 和 popd 维护一个目录栈,需要经常在多个目录间跳转时,先把这些目录压入栈中,随后用 popd 依次退回,处理多目录切换比单独依赖 cd 顺滑很多。路径相关的问题最怕的不是不会写,而是写错之后影响后续命令,所以养成“先补全、再回车”的习惯,长期来看能少踩很多无谓的坑。
1.3 cp、mv、rm:拷贝、移动、删除时最容易犯的错
cp 和 mv 日常用起来很简单,但细节上到处是坑。cp 默认只复制文件内容,不会原样保留时间戳和属主属性;如果你是在做备份,希望最终生成的文件跟原始文件保持相同的元数据,应该加上 -a 参数,或者退一步用 -p 保留基本属性。-a 还有一个好处,它会递归复制目录,并且尽可能保留符号链接和权限,所以很多人把 cp -a 当作整目录复制的首选。
mv 是另一个容易被低估的命令。在同一文件系统内,mv 的动作本质上是改一个目录项,几乎不会产生真正的数据拷贝,所以移动速度极快,即使是一个十几 GB 的文件也往往只是一瞬间的事。但如果你把文件从一个分区或者磁盘移动到另一个挂载点,两个文件系统不是同一个时,mv 就会自动退化成“先复制、后删除”两步操作,这时的耗时取决于文件大小和磁盘速度,很多人以为系统卡死,其实是在等 I/O 完成。
rm 更需要谨慎。让我用一个典型案例来说明问题:很多部署脚本里会写 rm -rf "$BACKUP_DIR" 来清理备份目录,可一旦上游配置读取失败,BACKUP_DIR 没有被赋值,这条命令在展开后就可能变成一个针对根目录的删除动作。哪怕现代系统自带的 rm 已经会对直接删根目录做出保护,这种写法也足以把运行环境里的重要目录清掉。我给自己定的规矩是:所有包含 rm 的脚本,执行前一定要判断变量是否为空,最好在运行时用 echo 先把即将执行的完整命令打印出来,确认路径没有被截断。这套习惯看着简单,关键时刻真能救命。
2. 查看与检索文本:让日志不再难读
2.1 cat、less、head、tail 怎么选
查看文件内容看起来是件再简单不过的事,但选错工具会让你浪费大量时间。cat 适合把短文件完整输出,最多只能配合管道向下传数据;一旦文件超过屏幕范围,cat 会把大量内容像瀑布一样滚过去,连最前面的内容都看不完整。对于日志、配置文件这类可能很大的文件,我很少用 cat,而是优先用 less。
less 允许用方向键翻页,用空格向后翻,用 / 输入关键词搜索,用 n 跳到下一处匹配,用 q 退出。最让我满意的是它打开大文件也很轻快,因为按需加载,不会把整个文件一次塞进内存。只要需要查看目录里的日志文件,我都会下意识敲 less。相比之下,如果只想看文件的开头或结尾几行,head -n 20 和 tail -n 20 更直接。head 常用于检查文件头部格式,tail 常用于确认最新追加的内容。
tail -f 是排查应用日志时的一个王牌选项。它会保持对文件的持续跟踪,文件新增一行,终端立刻打印一行,非常适合观察服务启动过程、请求报错等动态日志。以前我需要反复手动执行 tail 才能看到新日志,自从学会 tail -f 之后,就再也没用过那种笨办法。如果想在跟踪的同时保留一些历史内容,可以用 tail -n 100 -f app.log,它会显示最后 100 行后再继续跟随新增内容,这个组合非常实用。
2.2 grep:从关键字查找到递归搜索
grep 是我认为 Linux 文本处理里最值得首先掌握的命令,作用是在文件或输入流中按正则表达式查找匹配的行。最朴素的形式是 grep "ERROR" app.log,它会输出日志中所有包含 ERROR 的行。如果觉得默认输出太朴素,加 -n 让它显示行号,调试时就能直接从行号去源代码里定位上下文,效率完全不一样。
实际使用中还有几个高频场景。第一个是忽略大小写,日志里的 error、Error、ERROR 可能表达同一个意思,可默认 grep 是区分大小写的,少一个 -i 参数就可能漏掉一批关键日志。第二个是递归搜索目录,grep -r "某个配置项" /etc/某个服务/ 能找到相同配置出现在哪些文件里。但要注意,-r 在大量文件里搜索时性能不一定好,更好的做法是先确认目录范围,再用 --include 限制文件后缀,例如 --include="*.json",把不相干的二进制和其他类型文件过滤掉。
第三个场景是 grep 和管道结合,最典型的写法是 tail -f app.log | grep "timeout"。这样 tail 提供源源不断的输入,grep 只把包含 timeout 的行过滤出来,一配合就进入了“只关心想看内容”的工作状态。grep 还支持 -A、-B、-C 参数,分别显示匹配行之后、之前和两侧的上下文。定位异常时我通常用 -C 5,同时看前后各五行,避免只看单行导致误判前后语义。
2.3 awk 与 sed:用简单的文本处理解决复杂需求
awk 和 sed 是文本处理的两大工具,很多初学者一看到语法就发怵,但我建议先从最常见的场景入手。awk 的默认行为是按行读取,并按空白字符把一行拆成多个字段。一个经典应用是提取某列数据,比如 Web 访问日志里第 1 列是客户端 IP,第 7 列是请求路径,想统计某个接口的流量来源,可以用 awk '{print $1, $7}' access.log。这比打开文件逐行跑正则要直接太多。awk 还内置了简单的统计功能,比如对某列数字求和,虽然写法看起来有点绕,但不需要任何外部依赖就能在服务器上完成计算,这是它最大的价值。
sed 则主要负责文本替换。最常见的形式是 sed 's/旧内容/新内容/g' 文件名,其中 g 表示替换一行里的所有匹配项。如果不加 g,只有每行第一次匹配会被替换,实战里经常有人漏掉这个细节,结果脚本处理后的数据仍然残留旧值。我还要提醒一句:sed 默认只在终端输出结果,不会改动源文件;如果想保存修改,需要加 -i 参数。但加 -i 之后原始文件会被直接覆盖,建议先不带 -i 跑一遍输出,确认结果符合预期,再决定是否真正写入。需要同时做多处替换时,可以用 -e 把多个表达式串起来,例如 sed -e 's/a/b/g' -e 's/x/y/g',一次处理完。
3. 权限与进程:读懂 Linux 的权限和状态
3.1 chmod、chown:权限设置的正确姿势
Linux 的权限体系可以概括为:一个文件有所有者、所属组和其他用户三种身份,每一种身份对应读 r、写 w、执行 x 三类权限。在 ls -l 的输出里,权限位是一串字符,例如 -rw-r--r--,表示这是一个普通文件,拥有者能读能写,组用户和其他用户只能读。
修改权限最常用的方式有两种。符号模式用字母直接操作,比如 chmod u+x 脚本.sh 表示给当前用户增加执行权限,chmod g-w 数据.txt 表示去掉组用户的写权限。数字模式是把 r、w、x 分别看成 4、2、1,通过加和得到权限值,例如 chmod 755 表示拥有者为 7,组和其他用户为 5。记一个简单的换算:7 是完整权限,5 是读加执行,4 是只读。日常要让一个脚本能在服务器上直接运行,又不希望它被随意篡改,755 是很常见的选择。
chown 用来修改文件的所有者或所属组。交付应用给运维部署时,经常要执行 chown -R appuser:appgroup /opt/app,把整个应用目录的所有者改成运行服务的用户。这里的 -R 表示递归,文件和目录一起生效;少写 -R 就只会改最外层目录,导致服务仍然因为子目录权限不足而启动失败。这是我在部署实战里见到最多的权限类问题,很多人检查了目录权限没发现问题,却没意识问题正出在子目录这一层。
3.2 ps、top 与 kill:定位并处理异常进程
进程是 Linux 系统管理的核心概念之一。排查进程最常用的命令是 ps,ps -ef 会以全格式输出所有进程,每一行包含执行用户、PID、PPID、CPU 和内存占用百分比、启动时间以及执行命令。后台任务出现异常时,我一般先执行 ps -ef | grep 关键词 精确找到可疑进程的命令行,比如 ps -ef | grep java,能看到哪些 Java 进程在运行,各自启动参数是什么。
top 命令则是实时查看进程资源的首选。打开 top 后,默认界面显示 CPU 使用率、内存使用率、运行进程数等摘要信息,下面是按资源消耗排序的进程列表。如果发现某个应用把 CPU 打满,在 top 里按 P,进程会按照 CPU 排序;按 M 则按内存排序。刷新间隔可以按 s 再输入秒数,我不建议低于 1 秒,否则系统有限的资源都浪费在刷新界面上,反而干扰排查。
定位到异常进程,下一步通常是 kill。kill 本质上是向进程发送信号,默认信号是 SIGTERM,相当于给进程一个自行清理的机会;如果进程完全没有响应,再考虑 kill -9 发送 SIGKILL,强制内核直接结束进程。但 -9 是一把重锤,不该作为默认选项,因为强杀会让进程来不及保存状态,可能留下半写状态的文件,数据库这类场景下还会造成数据损坏风险。
3.3 df、du、free:磁盘与内存使用情况怎么看
磁盘问题和内存问题是最容易被低估的两类故障。df -h 会以易读单位显示每个挂载点的空间总量、已用、可用和使用率,排查“磁盘满了”这类问题,第一站就应该是它。看到某个分区使用率接近 100%,后续再去定位是哪个目录或文件占用了空间,用的是 du。du -sh /opt/* 可以查看每个子目录的总大小,-h 表示人类可读,--max-depth=1 可以控制输出深度。需要注意,du 在扫描超大目录时可能需要一段时间,因为它要真实统计目录下所有文件大小,并不是看一眼系统元数据就能立刻返回。
free 命令用于查看内存和交换分区使用情况。free -h 能方便地看到 total、used、free、buff/cache 等列。很多人看到 used 偏高就以为内存不够,其实内核会尽量把空闲内存用作缓存,真正可靠的指标通常看 available 这一列,它代表在不需要额外清理缓存的情况下,还能分配给新进程的内存量。这个理解差异在服务器调优时格外重要,不然很容易被表面上的 used 数字吓到,做出错误的扩容决策。
4. 网络与远端操作:排查连接问题的实用命令
4.1 ping、curl、wget:网络连通性与资源获取
排查网络故障,我一般会按照“通不通、通到哪、为什么不通”的顺序推进。ping 是第一步,它发起一个 ICMP 回显请求,测试目标是否可达,并显示往返时延。执行 ping -c 4 example.com 能只发送 4 个包就结束,避免陷入无限循环。有一点必须提醒:ping 不通并不等于服务不可用,因为很多服务器会直接丢弃 ICMP 包,防火墙规则可能把 ping 过滤掉了,但业务端口依然正常。所以 ping 不通只说明 ICMP 不通,真正的服务状态还要用端口或 HTTP 请求继续验证。
curl 和 wget 是访问 HTTP 服务最常用的两个命令。curl 更像一个客户端,可以自定义请求方法、请求头、请求体,适合接口调试;wget 偏向资源下载,如果目标 URL 指向一个文件,wget 更适合,它支持断点续传和递归下载。用 curl 快速测试服务是否正常,最方便的是 curl -I http://127.0.0.1:8080/,其中 -I 表示只获取响应头,响应头里的 HTTP 状态码能直接反映服务是否在监听。需要临时调试证书问题时,curl -k 可以跳过证书校验,但它只应该出现在临时验证环节,正式环境还是要先解决证书本身的问题。
4.2 ssh、scp:安全的远端登录与文件传输
ssh 是连接远端 Linux 主机最重要的通道,常规登录直接 ssh 用户@主机地址 即可。首次连接时,系统会提示确认主机指纹,这是为了防止连接被劫持。很多人贪图方便使用密码登录,但在真实生产环境下,我更推荐使用公钥认证。生成一对密钥之后,把公钥放到目标机器的 authorized_keys 文件中,登录就不再需要密码;你还可搭配 ssh-agent 管理密钥,减少每次输入密钥密码的麻烦。
scp 是基于 ssh 的文件复制命令,最常用于把本地文件推到远端,格式是 scp 本地文件 用户@主机:目标目录,例如 scp ./app.jar deploy@10.0.0.8:/opt/app/。拉取远端文件则把两个参数的顺序反过来。scp 默认走 22 端口,如果目标机器使用非标准端口,需要用 -P 指定。这里有个特别容易弄混的地方:ssh 指定端口是小写 -p,scp 指定端口是大写 -P,两边的开关不一样,我见过不止一个人因为这个小差异导致连接失败。
4.3 ss 与 netstat:查看端口和连接状态
端口和连接状态排查,在服务无法访问时非常关键。老牌工具 netstat 使用广泛,但很多新系统默认不安装,这时候可以优先看 ss。ss -lntp 能列出所有监听状态的 TCP 端口及对应进程,排查某服务是否在监听指定端口,这一条命令基本就能把问题定性。其中 -l 表示 listening,-n 表示直接显示端口数字,-t 只看 TCP,-p 显示进程信息。
当服务已经在监听端口、但客户端连接仍卡住时,需要看具体连接状态。ss -t state established 可以只显示已建立的连接,连接数或来源 IP 的变化能帮你在业务高峰期判断压力源头。如果系统里出现大量 TIME_WAIT,可以用 ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn 统计各类连接状态的数量,快速了解哪种状态占了大多数。单个连接状态看不出来的问题,汇总成分布表之后往往很快能看出规律。
5. 软件安装、服务与日志排查:日常维护的实用组合
5.1 apt 与 yum:软件安装与更新的两条主线
Debian 系的发行版标配 apt,RHEL 系则是 yum 或 dnf。最常用的命令无非是 apt update、apt install 软件名、apt upgrade。很多人刚装完系统不执行 apt update,就去安装某个软件包,然后报错“软件包不存在”,其实不是因为软件没有发布,而是本地软件源索引太旧。update 只是从远程仓库拉取最新索引,upgrade 才真正执行软件升级,两条命令分工完全不同。
yum 系也一样,yum install -y 包名 中的 -y 表示跳过确认交互。dnf 作为新一代包管理器,命令格式基本一致。无论在哪个发行版,我都建议在生产环境升级之前先查看更新内容,不要无脑执行 upgrade。跨版本或者涉及基础库的升级,兼容性风险永远存在,宁可先看变更说明,也不要贪一时省事。
5.2 systemctl:服务管理的基本操作
systemd 是当前主流 Linux 发行版的初始化系统,systemctl 则负责控制由它管理的一系列服务。最常用的操作包括 systemctl start 服务名、systemctl stop 服务名、systemctl restart 服务名和 systemctl status 服务名。每次修改服务配置文件之后,都要 restart 才能让新配置生效;systemctl enable 服务名 是设置开机自启,disable 则是取消。
排查服务起不来的问题时,status 的输出往往已经给了方向,比如配置文件语法错误、端口被占用、依赖服务没有启动。这些消息看起来零散,但结合日志可以很快定位。实际操作中,我习惯在重启服务之后立刻用 status 确认它的当前状态,再配合日志查看有没有新的报错,而不是只盯着进程是否出现。
5.3 journalctl:从系统日志中定位问题
systemd 会把大量服务日志和系统日志交给 journald 管理,查看这些日志不需要手动翻目录,直接使用 journalctl 就行。journalctl -u 服务名 可以查看某个系统服务的日志,配合 --since 参数筛选时间范围非常实用,例如 journalctl -u 服务名 --since "10 minutes ago",能避免浏览一整天甚至更久以前的无用记录。
如果希望日志持续滚动输出,journalctl -u 服务名 -f 的作用类似于 tail -f,会实时打印新产生的日志,适合在修改配置后重启服务的时刻使用。配合 grep 做关键字过滤,例如 journalctl -u 服务名 | grep "error",能快速筛选出问题相关行。还要注意 journald 日志默认有轮转上限,老日志会被自动清理;当你需要追查更早的历史记录时,最好在事发生时就及时把相关日志导出存档,否则可能过段时间就再也找不回来。
5.4 变量为空导致 rm 误删的完整复盘
这是一个很有代表性的脚本事故,值得拆开来看。某些自动化部署脚本里会写一段清理逻辑:先根据日期字符串拼出备份目录变量 BACKUP_DIR,然后执行 rm -rf "$BACKUP_DIR",计划清理当天的历史备份。正常情况下一切运转顺利,可如果上游配置读取失败,日期变量没有成功赋值,BACKUP_DIR 就变成了空字符串,删除命令展开后等级于向根目录发起了删除请求。即使新版本的 rm 对直接删除根目录已经做了保护,这种变量未保护导致的展开错误也足以把运行环境中的重要目录清理得面目全非。
复盘之后,我把这类问题的处理思路固定成三步。首先,不要在清理或删除脚本中使用未加保护的变量,可以对变量做显式判空,例如 if [ -z "$BACKUP_DIR" ]; then exit 1; fi。第二,尽量使用带固定前缀的路径,比如 rm -rf "/backup/${DATE}",而不是让整个路径都基于变量拼接。第三,在测试阶段先把 rm -rf 替换成 echo "rm -rf ...",输出即将执行的完整命令,人工确认后再切回真实执行。这三步虽然简单,却能挡掉绝大多数同类事故。
5.5 常见命令排查速查表
最后把这篇文章涉及的高频排查场景和对应命令整理成一张速查表,方便你遇到问题时快速找到参照。这张表不是为了让你背,而是给一个与真实需求直接挂钩的索引。
| 场景 | 常用命令 |
|---|---|
| 查看目录列表及隐藏文件 | ls -lha |
| 查看实时追加的日志 | tail -f 文件名 |
| 在日志中查找关键字 | grep -n "关键信息" 文件 |
| 读取大文件进行翻页搜索 | less 文件名 |
| 查看磁盘空间 | df -h |
| 查看目录大小 | du -sh 目录路径 |
| 查看内存状态 | free -h |
| 查看全部进程 | ps -ef |
| 实时查看进程资源 | top |
| 终止进程 | kill PID / kill -9 PID |
| 测试目标可达性 | ping -c 4 目标地址 |
| 测试 HTTP 服务 | curl -I http://地址 |
| 远端登录 | ssh 用户@主机 |
| 远端传输文件 | scp 文件 用户@主机:目录 |
| 查看端口监听 | ss -lntp |
| 查看服务日志 | journalctl -u 服务名 |
这些命令里,大部分不是每天都会出现在屏幕前,可只要出现一次,往往就是你最需要稳定操作、不能出错的时候。实际接触 Linux 命令行这几年,我最大的体会是不要刻意背命令,把命令放进场景里自然就容易记住。遇到磁盘告警,你亲手用 df -h 定位分区,再用 du -sh 扫描目录,最后发现是某个日志文件没有轮转把空间吃满。走完这么一轮,相关命令会比死记硬背牢固得多。我也越来越依赖把常用操作固化成脚本和别名,让自己不去重复踩同样的坑。如果你在使用中有自己的顺手命令,建议也整理成一张专属于你的速查表,长期积累下来会是一笔很宝贵的经验财富。