1. 文件操作指令:日常用的最多,也最容易翻车
1.1 ls、du、df 三兄弟:磁盘与文件信息的正确打开方式
接触Linux的第一天,基本都会跟ls打交道。但很多人用了好几年,始终只会在终端敲ls或ls -l,等到磁盘爆了、文件找不到的时候才手忙脚乱。先说一个我见过太多次的场景:有同事反馈服务器磁盘满了,我登录上去执行df -h,发现根分区确实100%,但用du -sh /home一个个目录排查,愣是没找到什么大文件。最后一查,发现是某个日志服务把输出重定向到了一个隐藏目录下的文件,而这个文件恰好被进程删除了,但进程还开着文件句柄,所以空间一直没有被释放。这个案例有个专门的排查方法,就是用lsof | grep deleted查看被删除但仍在占用的文件。
ls、du、df这三个命令的定位完全不同。ls是看文件列表和基础属性,du是统计目录和文件实际占用的磁盘块大小,df是看文件系统的总容量、已用和可用空间。很多人用ls -l看到的文件大小去判断磁盘占用,大部分时候是准的,但当遇到稀疏文件、空洞文件、或者文件被删除但句柄未释放的情况,就得靠du和lsof了。
日常使用中,我习惯给ls配个别名:
bash复制alias ll='ls -alF --color=auto'
这样能看到隐藏文件,并区分目录、可执行文件和软链接。du比较常用的是du -sh *和du -h --max-depth=1,前者看当前目录下每个子目录和文件的整体大小,后者适合一层一层往下找大目录。而df -h是最直观的,-h参数输出人类可读的格式,这一条命令几乎是排查服务器问题的第一步。
1.2 find:不只是"找文件",更是一台微型筛选引擎
find在面试题里出现频率极高,但日常很多人只会find / -name "xxx"这种最基础的用法。之前热搜词里也有"linux find"和"linux find用法"单独出现,说明大家对它的需求是真实的。find真正的强大之处在于它的条件组合能力,比如按时间找、按大小找、按权限找,还能直接对结果执行操作。
举几个我实际用过的例子:
- 找最近7天内修改过的文件:
find /var/log -mtime -7 -type f - 找超过500M的大文件:
find / -size +500M -exec ls -lh {} \; - 找权限配置异常的文件:
find /home -type f -perm 0777 - 批量删除5天前的临时文件:
find /tmp -name "*.tmp" -mtime +5 -delete
这里重点说两个坑。第一个坑是-exec和管道xargs的区别。find -exec是逐条执行,参数里用{}占位符代表找到的每个文件,命令以\;结束。这种方式安全但慢,因为每条文件都会fork一次子进程。find ... | xargs rm -f这种方式效率高,但如果文件名里有空格或换行,就会被拆分成多个参数,造成误删或报错。稳妥做法是find ... -print0 | xargs -0 rm -f,用\0作为分隔符,就不会被空格干扰。第二个坑是忘记限定-type f,结果把目录也匹配进去,执行rm -rf的时候直接把目录树给删了。
提示:
find的-delete参数不会删除非空目录,所以不用担心一条命令把整个目录结构端掉。但用-exec rm -rf {} \;就要格外小心,建议先不加-exec,跑一遍纯查询,把结果列出来确认无误后再加。
1.3 tar、zip、rsync:打包压缩与同步的实操细节
打包压缩这块,最常见的误区是把tar -czvf和tar -xzvf的参数弄混。拆开来看其实很简单:c是create创建,x是extract解压,z代表gzip压缩,v是verbose显示过程,f指定文件名。所以创建压缩包是tar -czvf archive.tar.gz /path,解压是tar -xzvf archive.tar.gz。但f必须写在最后,而且后面紧跟文件名,因为tar认为f后面的内容就是文件名,如果写成tar -cvfz,它会尝试用z作为文件名,命令直接报错。
rsync是我用来替代scp的主力工具,尤其是需要断点续传或增量同步的场景。基础用法是rsync -avz source/ user@host:/dest/,注意source目录末尾的斜杠很有讲究:带斜杠表示同步目录内的内容,不带斜杠表示把目录本身也同步过去。这个细节很多人踩过坑,同步完发现目标机器上多了一层目录,或者少了一层。
rsync还有两个非常实用的参数:--progress显示进度,--exclude排除不需要同步的目录。比如同步代码时排除node_modules和.git,能省下大量时间。做数据迁移之前,我一般会先跑一遍rsync -avz --dry-run,只看对比结果,确认无误后再正式执行,这个操作习惯帮我避免过好几次误删和同步错方向的事故。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统状态与网络排查:不要再用"猜"来排查问题了
2.1 端口、进程、网络连接:一条命令看清全貌
热搜词里有"linux的9090端口什么再用"、"linux tcp协议栈数据流走读"、"linux多进程通信框架",说明大家在网络排查方面有真实的痛点。其实大多数端口问题,用ss或netstat就能定位。以9090端口为例,先执行ss -lntp | grep 9090,-l表示监听状态,-n显示端口号而不是服务名,-t限定TCP,-p显示进程PID和名称。如果端口被占用,输出里会直接给出PID和进程名,接下来ps -ef | grep PID能看到完整命令行,基本就能确定是谁在占用。
物理机时代,netstat用得多一些,现在很多新版系统已经不再预装netstat,改用ss。ss的性能更好,查询大量连接时不容易卡住。如果遇到"端口明明没监听,但telnet还是通"的情况,一般不是端口问题,而是防火墙或负载均衡在后端做了转发。此时要查iptables -L -n或firewall-cmd --list-all,看看是否有DNAT规则。之前帮人排查一个"端口通但服务连不上"的问题,查了所有网络配置,最后发现是服务监听的IP是127.0.0.1,只允许本机访问,改成0.0.0.0后就好了。
2.2 进程管理与日志定位:top、ps、journalctl的配合
top是看系统负载和资源占用的首选工具。但很多人只看那个load average,不知道怎么看具体进程。进入top界面后,按P按CPU排序,按M按内存排序,按c显示完整命令行,这些快捷键用熟了,定位问题比鼠标点半天快得多。如果某个进程CPU飙到100%以上,多半是代码里有死循环或高密度计算,先用top -Hp PID查看该进程下的线程,再用jstack(Java场景)或gdb attach(C/C++场景)抓线程栈,才能定位到具体是哪行代码出问题。
日志排查方面,journalctl在systemd系统上已经逐渐取代了/var/log/messages的部分功能。journalctl -u nginx.service --since "1 hour ago"可以查看某个服务的近期日志,journalctl -f可以像tail -f一样实时跟踪。但systemd日志是二进制存储的,占磁盘空间容易失控,建议设置SystemMaxUse限制日志容量,比如限制为500M,避免日志把分区填满。
2.3 权限与用户管理:新建用户不只是useradd那么简单
热搜词里"linux新建用户"出现的频率很高,但很多人只知道useradd testuser,然后passwd testuser设个密码就结束了。其实这样建出来的用户有很多隐患——没有家目录,没有默认shell,无法登录图形界面,甚至无法正常使用sudo。
规范操作应该是:
bash复制useradd -m -s /bin/bash testuser
passwd testuser
-m创建家目录,-s指定登录shell。如果需要让该用户有sudo权限,还要执行usermod -aG wheel testuser或编辑/etc/sudoers添加相应配置。这里推荐用visudo命令编辑,因为退出时会检查语法,防止改错导致整个sudo系统崩溃。我见过有人直接vi /etc/sudoers,改错后所有用户都无法提权,只能进单用户模式修复。
权限这块,chmod和chown是双胞胎,一个改权限,一个改属主属组。常见误区是只改权限不改属主,或者只改属主忘了组。比如部署web服务时,代码目录需要让nginx用户可读,正确做法是chown -R nginx:nginx /var/www/html,然后chmod -R 755。如果目录里还有需要写入的文件(比如上传目录),那这个目录权限要设成775或g+w,而不是简单粗暴地chmod -R 777。777意味着任何人都能读写执行,对生产环境来说是一种慢性中毒。
3. 高频误区拆解:为什么你总在rm、scp、chmod上翻车
3.1 rm -rf 的恐怖之处与安全自救
"linux删除文件夹命令"和"linux 删除文件夹"的相关搜索一直很多,说明很多人对rm的认知停留在表层,甚至只知道rm -rf,但不知道它为什么危险。rm -rf拆解来看:rm是删除,-r是递归删除目录及其内容,-f是强制删除不提示。合在一起就是"不问你同不同意,把目录里所有东西全部删光"。
最经典的翻车事故是这种操作:
bash复制cd /var/log
rm -rf $LOG_DIR/*
如果$LOG_DIR没有定义,shell会把它替换成空字符串,命令就变成了rm -rf /*,直接把整个根目录下面的内容全部删除。这个场景在菜鸟教程里被反复提及,但在真实环境中仍然不断重演。我自己的规避方法是:
- 删除之前先
ls或find查看匹配结果,确认无误再删 - 使用
rm -i(交互式)或rm -I(只删除一次确认,比-i温和一些) - 对重要目录设置alias,比如
alias rm='rm -I' - 在脚本中使用
set -u,防止未定义变量被当成空字符串
如果你确实容易手滑,可以试试把/bin/rm改名,自己写一个包装脚本,先判断路径是否为根目录或/home等关键路径,如果匹配就拒绝执行。这些做法看起来繁琐,但关键时刻能救命。
3.2 scp的常见坑:断点续传、目录斜杠、端口号
scp是跨机器拷贝文件最常用的命令,但它的坑也不少。最经典的是目录拷贝时漏了-r参数:scp user@host:/dir /local_dir只会报错,提示你-r没加。还有一些人会搞混本地路径和远程路径的顺序,把本地的文件覆盖到远程时,写成scp remote_path local_path,结果一路报错"Connection refused",还以为是网络问题。
端口号是非默认端口场景最常见的坑。如果服务器改了SSH端口,比如从22改成2222,就必须用scp -P 2222指定端口。注意是小写-p在scp里表示保留文件属性(时间戳、权限),大写-P才是指定端口,这和ssh命令是反的——ssh用大写-p?不对,ssh正好相反,ssh的小写-p是端口号。我在这上面栽过好几次,每次都要想一下。
断点续传是scp解决不了的场景,scp不支持断点续传。如果传一个很大的文件到一半断网了,只能重新传。这时候应该用rsync -avzP,其中-P相当于--partial --progress,可以保留已传部分并显示进度,重新执行时只传剩余部分。之前同步一个20G的数据库备份文件,scp断了三次,最后换rsync一次搞定。数据量越大,rsync相对scp的优势就越明显。
3.3 grep、管道、重定向的隐形陷阱
grep是所有基础指令中被误解最多的一个。它本身不是"查询文件内容",而是"从输入流中过滤文本行"。理解了这一点,才能理解为什么ps -ef | grep nginx能看到nginx进程,也才能理解下面这条命令为什么那么危险:
bash复制ps -ef | grep some_process | awk '{print $2}' | xargs kill -9
这条命令的本意是杀掉名为some_process的进程。但问题在于:如果some_process没匹配到任何进程,管道是空的,xargs不会执行,这没问题。但如果匹配错了,比如grep自己也被匹配进结果里,就会把grep的PID也kill掉。更常见的坑是:ps -ef | grep -v grep这个组合,很多人不知道为什么要加| grep -v grep,其实就是把grep进程本身从结果中过滤掉,否则你看到的结果里永远会有一行grep命令本身。
管道和重定向的区别也需要理清楚:管道|是把前一个命令的stdout接到后一个命令的stdin;重定向>是把输出写到文件,>>追加到文件,<从文件读取输入;2>重定向stderr。常见误区是把2>&1写成2>1,后者会把stderr写到名为"1"的文件里,而不是合并到stdout,排查半天日志为什么不在预期位置,最后发现是重定向写错了。
3.4 环境变量与PATH的常见误解
很多新手在安装完软件后,直接执行命令提示command not found,第一反应是"软件没装成功",其实多半是PATH没配置。比如装了Python 3.9到/usr/local/python3,但系统默认PATH里没有这个目录,直接输入python3就找不到。解决方法是修改/etc/profile或~/.bashrc,添加export PATH=/usr/local/python3/bin:$PATH,然后source ~/.bashrc生效。
环境变量这块有几个容易搞混的点。第一,修改/etc/profile影响所有用户所有shell,修改~/.bashrc只影响当前用户;第二,source和直接执行脚本有区别,source是在当前shell里执行,变量会保留,直接执行是开子shell,变量不会回传;第三,永久生效和临时生效的区别:命令行直接export只对当前shell有效,关掉终端就没了。之前有同事配置了Java环境变量,改完/etc/profile没source,直接开新终端还是java: command not found,最后发现是没执行source /etc/profile,这个细节虽然基础,但实战中经常碰到。
4. 一些可以显著提升效率的进阶习惯
4.1 巧妙使用history和快速跳转
多数人敲命令靠记忆,不靠历史。但Linux的history命令用好了,效率能提升一个量级。history会显示之前执行过的所有命令,配合!符号可以快速复用,比如!!执行上一条命令,!ssh执行最近一条以ssh开头的命令。更实用的是Ctrl+r反向搜索历史命令,输入关键字回车即可执行,这个快捷键掌握后,基本不需要反复敲长命令了。
目录跳转方面,cd -可以回到上一个目录,对于在/etc和/var/log之间来回切换的场景很实用。pushd和popd虽然用的人少,但在写脚本时是切换目录的好帮手,可以维护一个目录栈,比cd来回切更方便。另外,配置autojump或zoxide这类工具后,只要输入z proj就能直接跳到/home/user/work/project,跳转效率提升非常明显。我一直觉得这些看似花哨的小工具,才是真正提升工作流顺畅度的关键。
4.2 配置自己的环境:alias、vimrc、gitconfig
基础指令说到底都是固定的,真正拉开效率差距的是"环境配置"。alias可以定义很多自己的快捷指令,比如:
bash复制alias grep='grep --color=auto'
alias ll='ls -alF'
alias ..='cd ..'
alias pd='pushd'
vim的配置也值得花一点时间。/etc/vimrc是全局配置,~/.vimrc是个人配置。最基础的几项:set nu显示行号,set ts=4设置tab为4个空格,set expandtab把tab替换为空格,syntax on开启语法高亮。这些配置看着零碎,实际写脚本时体验天差地别。
git配置同样重要。git config --global user.name和user.email是提交代码的基础,alias也能给git配,比如git config --global alias.st status,以后直接git st就行。git config --global core.editor vim可以设置默认编辑器。对于常写shell脚本的人来说,提前配好这些环境,比临时查文档快得多。
4.3 查看命令帮助的"正确姿势"
很多新手遇到不认识的命令,第一反应是百度或者翻书。但Linux本身自带了丰富的帮助系统,学会自己查帮助,是摆脱"新手感"的关键一步。
man:最详细的命令手册,比如man ls会解析所有参数的含义,按q退出--help:大多数命令支持这个参数,快速查看用法和参数,比如ls --helpinfo:比man更详细的文档系统,但界面交互不如man友好type:查看命令是内建命令还是外部命令,比如type cd会输出"cd is a shell builtin"which:查看外部命令的路径,比如which python3
man的输出有时候很长,定位具体内容可以按/搜索关键字,然后按n跳到下一个匹配项。这些操作虽然基础,但能让查文档的效率提升很多倍。真正的高手不是记得所有参数,而是知道用什么工具找到自己想要的参数。
5. 从"会敲命令"到"能定位问题":一套实用的排查思路
5.1 磁盘空间不足:一次完整的排查链路
磁盘空间不足是最常见的服务器问题,但排查的思路和命令顺序比单独记忆某个命令更重要。我一般按以下顺序排查:
df -h查看各分区的使用率,确认哪个分区满了du -sh /分区下各目录从根开始层层往下找大目录find / -size +500M -exec ls -lh {} \;找出超大文件lsof | grep deleted排查已删除仍被占用的文件journalctl --disk-usage检查systemd日志是否占用过大
之前遇到过一个案例,df -h显示根分区满了,但用du -sh /*看了一遍,所有目录加起来不到总用量的一半。后来用lsof | grep deleted才发现,有个服务持续写一个已经被删除的日志文件,空间全部被隐藏占用了。这种情况有两种解法:重启服务释放句柄,或者直接> /proc/PID/fd/1清空文件内容,前提是确认这个fd是日志输出。这个案例说明,排查问题的思路往往比单个命令的熟练度更重要。
5.2 端口冲突和服务启不来的排查链路
服务启动失败是另一个高频问题。systemctl start nginx报错"Address already in use",十有八九是端口被占用。排查步骤:
ss -lntp | grep 端口号查找占用端口的进程ps -ef | grep PID查看进程详情,确认是否是自己启动的旧服务kill PID或kill -9 PID清理占用进程- 再启动目标服务
但有一种特殊情况:端口占用方是内核线程或者另一个服务的子进程,杀了之后还会自动重启。这时要顺着进程树往上找父进程,确认是不是被supervisor或systemd托管了。如果服务本身无状态,最简单的方案是换端口,改配置重启。我见过为了抢一个端口跟旧服务对线半小时的,最后换了个端口一秒钟解决,排查问题要有取舍,不要跟环境死磕。
5.3 日志文件太大、查看不方便的处理方式
日志文件膨胀也是一个很常见的运维问题。tail -f /var/log/nginx/access.log就能实时跟踪日志,但很多人的日志文件有几十个G,tail打开都很慢。此时应该用tail -n 100指定读取最后100行,而不是从头加载整个文件。grep匹配大日志文件时,建议加上--color=auto高亮关键字,方便快速定位。
另一个实用的做法是less +F,它可以像tail -f一样追踪文件变化,但支持上下翻页查看历史内容。按Ctrl+c停止跟踪,按F恢复跟踪,这个工具在处理持续增长的日志时特别方便。处理老日志,可以用logrotate做轮转压缩,避免日志无限膨胀。配置/etc/logrotate.d/下的规则,按天或按大小轮转,保留最近几份,旧的自动压缩,这个属于Linux运维的必修课。
6. 写在最后的个人操作心得
做Linux运维和开发这些年,踩过的坑不少,这里分享几点自己的感受。
第一,尽量养成"先查后动手"的习惯。不管是删文件、改配置还是杀进程,先确认好影响范围再执行。删除之前ls一下,杀进程之前ps看一下,改配置之前备份一份,这些动作虽然多花几秒钟,但能避免大多数灾难性事故。
第二,不要过分依赖一条"万能命令"。很多人喜欢问"删除文件夹用什么命令",但真正的问题可能是"这个日志目录为什么越来越大"。命令只是工具,理解问题背后的原因才是关键。多问几个为什么,比学会一千条命令更有价值。
第三,养成写脚本和自动化的习惯。重复执行的命令,写成脚本保存下来;常用的排查流程,整理成checklist;每周手动执行的维护任务,用crontab定时自动化。刚开始可能觉得写脚本费时间,但长期来看省下的时间和避免的失误完全值得。
第四,遇到不确定的问题,先看官方文档和man手册。网上的博客可以帮你快速上手,但细节和边界情况一定要以官方文档为准。比如参数是-P还是-p,不同版本可能不一样,查man最保险。
Linux指令的学习没有捷径,我也不建议靠背各种"命令大全"。最好的方式是带着问题去学,遇到实际需求时查命令、用命令、总结命令,用过一遍就记住了。真正的高手不是什么命令都会,而是出了问题能用最短的时间找到根因,而这个能力只能在实战中慢慢培养。希望这篇文章能帮大家少走一些弯路。
