
先说一个我印象很深的场景刚接触Linux的时候终端里敲一个ls看到一堆花花绿绿的名字完全不知道哪个文件该放哪儿、哪个目录能不能删。后来做了一段时间运维又碰到同事在服务器上敲了rm -rf /home/$user/结果变量没赋值Slash后面直接成了根目录——那一瞬间我才意识到文件与目录这堂课如果只是背命令迟早要出事。这篇文章不打算列一份“Linux常用命令大全”给你背。我想把文件与目录的底层结构、路径的运行逻辑、以及日常管理中最容易踩坑的指令场景串起来讲。适合刚入门想建立完整认知体系的新人也适合已经能干活但总在路径、权限、磁盘占用上栽跟头的中级使用者。看完之后你至少能回答这几个问题为什么/etc不能乱动、绝对路径和相对路径到底怎么选、/usr和/home为什么会出现在各种报错里、以及find和du怎么配合才能快速定位问题文件。1. 整体设计思路Linux的文件系统为什么是一棵树1.1 从“根”开始一切皆文件的设计哲学Windows用户习惯把每个磁盘分区当成独立的入口C盘、D盘、E盘各自为政。Linux不一样整个文件系统只有一个入口就是/叫根目录。根目录下面挂着/etc、/home、/usr这些下级目录而你的数据盘、U盘、光驱甚至CPU的内核参数、正在运行的进程信息都可以“挂”在某个目录节点上通过路径去访问。这就是Linux最核心的设计理念——一切皆文件。设备是文件、管道是文件、socket是文件连进程的运行状态都映射在/proc目录下的文件里。你可以用cat /proc/cpuinfo看CPU信息用ls /dev/sda查看块设备这些操作本质上都是在“读文件”。理解了这一点你会突然明白为什么很多Linux工具那么“简单粗暴”既然一切都是文件那就用统一的打开、读取、写入、关闭这套模型去处理所有东西。还有一点值得注意Linux的文件系统是动态拼接出来的。你在/下看到的目录可能来自多个不同的物理磁盘或网络存储。开机时内核挂载根文件系统然后通过/etc/fstab里的配置把其他分区挂载到指定目录。这也是为什么明明磁盘没满某个目录却写不进文件——它可能挂在一个容量很小的分区上。1.2 FHS标准目录结构不是随便定的很多人刚看Linux目录会觉得乱/bin和/usr/bin里都有命令/lib和/usr/lib里都有库/tmp和/var/tmp好像都差不多。这其实是历史包袱叠加的结果但为了兼容性Linux社区搞出了一个叫FHSFilesystem Hierarchy Standard的标准把每个目录的职责大致约定下来。FHS最大的价值在于软件安装时知道该把二进制放到/usr/bin把配置文件放到/etc把日志写到/var/log运维排查问题时知道日志在哪个目录、配置在哪个目录、临时文件在哪个目录。如果没有这个约定每个软件各自造一套目录那系统早就乱成一锅粥了。不过FHS只是一个标准不同发行版会有细微差异。比如/bin在多数现代发行版里是指向/usr/bin的软链接/sbin也是/usr/sbin的软链接。我刚接触的时候被这个搞糊涂过后来习惯了就觉得这是好事——把所有二进制统一放到/usr下备份和迁移反而方便。1.3 挂着“虚拟”名字的真目录/proc、/sys、/dev这里必须单独提一类目录它们不占磁盘空间数据是内核实时生成的很多人头一回看到会怀疑人生——/proc目录里的文件大小明明写着0但cat /proc/meminfo能读出一大串内存信息/sys目录里那些文件写一个值进去硬件参数立刻就变了。/dev目录也很有意思。它负责呈现系统中的设备节点/dev/sda代表第一块SATA/SCSI磁盘/dev/null是著名的“黑洞”。你把任何输出重定向到/dev/null数据就被直接丢弃。运维排查硬件问题、调整内核参数经常要跟这三个目录打交道。2. 关键目录逐个拆解出了问题知道上哪儿找2.1 系统基础目录/bin、/sbin、/lib、/etc/bin和/sbin放的是系统启动和基础管理需要的命令。/bin里有ls、cat、cp、mv这些普通用户也要用的命令/sbin里的fdisk、mkfs、mount通常需要root权限才能执行。注意很多发行版现在直接把这两个目录做成软链接指向/usr了你在CentOS 7上看/bin是个目录在CentOS 8上再看就变成符号链接这不影响使用但用ls -l /的时候别懵。/lib是系统启动需要的动态链接库。比如/lib/x86_64-linux-gnu/libc.so.6就是最核心的C库。现代发行版同样把它合并进了/usr/lib。这里有个容易被忽略的点如果你手动编译了一个软件报“error while loading shared libraries”往往就是它依赖的库不在默认路径里需要借助ldd命令查一下依赖再配置动态链接器搜索路径/etc/ld.so.conf或LD_LIBRARY_PATH环境变量。/etc是配置文件的集中营重要性排在所有目录前列。系统的用户信息在/etc/passwd、密码哈希在/etc/shadow、网络配置在/etc/network/interfaces或/etc/sysconfig/network-scripts/、软件源在/etc/apt/sources.list或/etc/yum.repos.d/。这个目录里的文件几乎都是纯文本所以运维的第一课就是学会用Vim看配置、改配置。记住一条铁律改动/etc下的关键文件之前先备份。2.2 用户与数据目录/home、/root、/opt、/var、/srv/home是所有普通用户的主目录所在地。每个用户默认在这里有一个以用户名命名的文件夹存放个人文件、配置和缓存。你敲cd ~就是回到当前用户主目录~就是这个意思。/root是root用户的主目录它不在/home下原因很简单如果系统因为异常无法挂载/home分区root还需要一个地方登录并修复系统。/opt用来放第三方软件很多商业软件、IDE默认安装到这里。我自己装JetBrains全家桶习惯解压到/opt/idea这种路径因为/opt逻辑上就是“可选应用程序”不像/usr那样有严格的目录约束。/var是容易膨胀的目录。/var/log存放系统日志/var/cache存放缓存/var/mail存放用户邮件/var/tmp存放比/tmp存活时间更长的临时文件。运维排查磁盘告警时/var往往是第一嫌疑。日志切割工具logrotate配得好不好直接关系到/var会不会爆掉。/srv用于存放系统对外提供的服务数据比如/srv/www放网站文件。不过实际生产环境里很多人不用它而是自定义应用目录比如/data或者/app。这不算错FHS只是建议不是强制。2.3 临时与虚拟目录/tmp、/run、/dev/tmp是大家都爱用的临时目录普通用户也能写。但这个目录有个特点可能被系统定期清理也可能重启后清空。有些发行版还会用tmpfs把/tmp挂到内存里速度快但一重启就什么都没了。把重要数据放在/tmp绝对是不靠谱的行为。/run是较新引入的目录存放系统运行时产生的临时数据比如进程PID文件、socket文件。/var/run通常是指向/run的软链接。检查某个服务是否启动时我们经常看/run/进程名.pid存不存在。2.4 软件与依赖的存放逻辑/usr的学问/usr是Linux目录结构里最复杂的部分。/usr/bin存放普通用户可执行的程序/usr/lib存放程序依赖的库文件/usr/share存放架构无关的共享数据比如文档、图标、时区数据。还有个/usr/local是管理员手动编译安装软件的默认前缀它的内部结构跟/usr一样。为什么单独拎出/usr/local说因为如果你用./configure --prefix/usr/local安装软件所有文件都会放到/usr/local/bin、/usr/local/lib这些路径下和系统自带的软件区分开互不污染。很多踩坑案例里用户手动编译了新版软件但系统还在调用旧版命令多半是PATH环境变量里没把/usr/local/bin排在前面。3. 路径体系与搜索逻辑找得到文件才算入门3.1 绝对路径与相对路径什么时候用哪个绝对路径从根目录/开始写比如/var/log/nginx/access.log。它的好处是唯一且确定不管当前在哪个目录敲下去就是同一个文件。脚本、配置、cron任务里写路径我强烈建议全部用绝对路径因为脚本的执行目录经常不可控相对路径容易踩坑。相对路径是相对于当前工作目录的路径。比如你在/var/log下敲ls nginx实际列出的是/var/log/nginx。它的好处是简洁适合交互式操作。但代价是上下文相关换个目录结果就变了。这里有一个经验在终端里人机交互时多用相对路径省事在脚本、服务配置、文档中一律写绝对路径。两条规则都不绝对但按这个思路走可减少大部分路径错误。3.2 特殊路径符号. .. ~ - 的含义这几个符号看着简单但用法有讲究。.代表当前目录..代表上一级目录~代表当前用户主目录-代表上一次所在的目录。cd -能在两个目录之间快速切换我刚工作时觉得这个技巧很酷后来频繁在配置文件目录和日志目录之间跳转才意识到它是真香。还有个小技巧ls .和ls的结果是一样的但ls ./nginx比ls nginx更能明确表达意图尤其在文件名容易混淆时。写脚本时任何用户输入的路径前面最好都加上./或明确的绝对路径前缀防止变量为空导致的意外行为。3.3 PATH环境变量“command not found”的真相你在终端敲vimshell怎么知道要执行哪个文件答案是查PATH环境变量。echo $PATH看一下输出是一串用冒号分隔的目录列表比如/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin。shell按顺序在列表里找名为vim的可执行文件找到第一个就执行。因为这个机制两个典型的坑就出现了。第一个你装了某个软件但敲命令时说not found很可能它的安装路径不在PATH里需要自己加export PATH/opt/myapp/bin:$PATH想永久生效就写进/etc/profile或~/.bashrc。第二个如果某个目录在PATH顺序中排在前面里面又有同名但版本不同的命令你会被“旧命令”坑得莫名其妙。排查这类问题用which或type能看到命令最终指向哪个文件。3.4 动态链接器搜索路径编译软件时的必修课写完C程序或者手动编译了某个依赖库运行时经常报“libxxx.so: cannot open shared object file”。这是动态链接器找不到库文件导致的。搜索顺序大致是环境变量LD_LIBRARY_PATH、缓存文件/etc/ld.so.cache、默认目录/lib和/usr/lib。排查手段很直接ldd /path/to/程序能看到它依赖哪些共享库以及各自的解析路径。如果某个库显示“not found”说明搜索路径里没有它。解决办法有两个临时设置export LD_LIBRARY_PATH/usr/local/lib或者永久修改/etc/ld.so.conf.d/下的配置加一行库所在目录然后跑ldconfig刷新缓存。这个知识点在自行编译部署Java、数据库、GPU相关服务时特别常见。4. 文件与目录管理指令实操从查看到批量处理4.1 查询类指令ls、file、stat、du、treels无疑是最常用的命令。但它有很多细节值得打磨ls -l列出权限、属主、大小、时间ls -a显示隐藏文件ls -lh把文件大小以人类可读方式显示ls -lt按修改时间排序。一个很有用的组合是ls -l --time-stylelong-iso把时间显示成2025-01-01 12:00这样的标准格式脚本处理时更好解析。如果想知道一个文件到底是什么类型不要凭扩展名猜。Linux的文件类型不看后缀file /usr/bin/vim会告诉你它是ELF可执行文件、脚本还是符号链接。stat能看到文件更完整的元数据包括inode号、访问时间、修改时间、状态改变时间这对排查为什么某个文件“没变但被备份了”很有帮助。du用于统计目录或文件占用的磁盘空间du -sh *能列出当前目录下所有文件/目录的总大小是找大文件的首选命令。tree不一定预装但装上了之后能以树状图看清目录层级学习阶段非常直观。4.2 创建与复制touch、mkdir、cp、rsynctouch不只是创建空文件它真正的用途是更新文件时间戳。一个骚操作是touch -d 2024-01-01 10:00把文件时间改成指定日期配合日志切割或备份策略时有妙用。mkdir -p创建多级目录是我眼里最被低估的指令之一。你要创建/data/project/logs如果父目录/data和/data/project都不存在普通mkdir会报错加个-p直接一路建到底。它还有个隐藏特性目录已存在时返回0不报错所以脚本里经常用mkdir -p保证某个目录一定存在。cp复制时要注意cp -r递归复制目录cp -a归档模式复制保留权限、属主、时间戳等所有属性适合做目录级别的完整复制。如果跨越文件系统复制大目录我更喜欢用rsync -av它能断点续传、增量同步而且复制到一半出现问题时重新执行一遍就能接着来。4.3 移动与删除mv、rm、rename及一个真实事故还原mv用于移动或重命名。它的核心行为是同一个文件系统内是纯“改名”速度快跨文件系统时是“复制删除”耗时与文件大小相关。所以移动大文件到另一个挂载点用户会觉得卡顿这很正常。rm -rf是事故高发区。举一个我亲眼见过的案例某同事想清理/home/app/tmp目录脚本里写了rm -rf /home/$dir/结果$dir没有赋值成功命令展开后变成rm -rf /home/。更致命的是他在root用户下执行等于试图递归删除整个/home分区。虽然因为权限问题没有完全删干净但大量数据已经受损。我把这类事故总结成三个防线第一生产环境慎用rm -rf能用find加-delete就用find能先mv到回收目录就先mv第二变量在传入rm之前做非空判断第三操作敏感目录前先ls确认路径再执行。rename命令按批量重命名也有自己的语法但更稳妥的方案是用mv写循环配合basename和模式匹配。4.4 链接与快捷方式ln -s软链接vs硬链接Linux里有两种“快捷方式”。ln -s 目标文件 链接名创建软链接它保存的是目标文件的路径目标被删除后链接就失效而且可以跨文件系统可以对目录创建。软链接通俗说就是“路径的引用”在ls -l输出里能看到-指向的原始路径。硬链接则完全不同。ln 目标文件 硬链接名创建的是同一个inode的另一个目录项。你可以理解成同一个文件有两个门牌改内容两边都变删掉任何一个门牌都不影响另一个访问而且不能跨文件系统也不能对目录创建。我平时用软链接更多因为改配置文件时可以直接ln -s /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf这种思路把分散的配置统一软链到一个地方统一管理。遇到一个常见问题程序通过软链接启动后它的工作目录和可执行文件路径怎么定位用pwd -P可以看到物理路径readlink -f能解析出最终的绝对路径排查“入口脚本被替换但行为没变”的玄学问题时这两条命令能救命。4.5 查找文件find、locate、whereis、which的组合用法find是查找文件的主力。基本套路find /var/log -name *.log按名字找-type f或-type d限定类型-mtime 7找7天前修改的文件-size 100M找大于100MB的文件。搜索时可以用-exec对结果执行命令比如清空历史日志find /tmp -name *.log -mtime 7 -exec rm {} \;注意结尾的{}和\;不能省。locate基于数据库查找速度极快但数据库不是实时更新需要跑updatedb。whereis查找命令的二进制、源码和帮助文档位置which只告诉你当前shell会执行哪个可执行文件。我自己的习惯是交互式快速定位用which和whereis精确筛选、批量操作一律用find。5. 权限与安全rwx不是三个字母那么简单5.1 权限位与目录权限的特殊性ls -l输出的第一列比如drwxr-xr-x拆开看第一个字符是文件类型d目录、-普通文件、l链接后面每三个字符是一组权限分别对应属主、属组、其他人。r读、w写、x执行。数字法也很好用rwx是7、rw-是6、r-x是5、r--是4所以chmod 755 file就是属主全权限属组和其他人有读和执行权限。目录权限有一个坑必须讲清楚目录的r权限只代表能列出目录里的文件名w代表能创建和删除文件x代表能进入目录、能访问目录中的具体文件。只要没有x就算有r也只能看到名字却无法进入这对日常排查“为什么能浏览文件名但cat不了”很有用。5.2 chmod、chown、umask实操chmod修改权限chown修改属主和属组。一个综合场景部署Web应用时需要让nginx进程能读取静态文件目录。常见做法是chown -R www-data:www-data /var/www/html再配合合适的chmod比如目录755、文件644。umask决定了新建文件默认的权限。系统默认umask 022所以新建文件是644、新建目录是755。这是用“最大权限”减去umask值得到的。如果想让新建文件对属主完全可控而其他用户什么都做不了可以设置umask 077这在处理敏感脚本目录时很实用。5.3 特殊权限位SUID、SGID、Sticky数字权限的第四位藏着三个特殊标志。SUIDchmod 4755让用户以文件属主的身份执行文件著名的/usr/bin/passwd就是例子——普通用户通过它临时获得root权限去修改/etc/shadow。SGIDchmod 2755用在目录上时能让新建文件自动继承目录的属组这多用于多人协作的共享目录。Sticky位chmod 1777最出名的载体是/tmp。它允许所有用户写入和创建文件但只有文件的属主或root能删除自己的文件。所以即使/tmp是1777A用户也不能删除B用户的临时文件。排查“为什么/tmp所有用户都能写但不让删别人的文件”答案就是粘滞位。6. 常见问题与排查技巧这些坑我替你踩过了6.1 “Permission denied”的排查思路文件明明给了755为什么还是权限不够第一步看属主属组ls -l输出第三列和第四列第二步看当前用户id命令确认是不是被sudo切换过去了第三步看父目录有没有x权限这一步最隐蔽。我遇到过一次用户对子目录有完全权限但父目录权限是drwx------导致子目录内容也访问不了。还有SELinux也会制造“Permission denied”但没有SELinux的报错提示时最难判断这时候ausearch -m avc查下拒绝记录或者临时setenforce 0验证一下能快速定位。6.2 “command not found”的快速解决三类原因最常见软件没装、软件装了但路径不在PATH里、命令名字记错。先which 命令看有没有没有就用yum provides 命令CentOS/RHEL或apt-file searchDebian/Ubuntu反查该命令属于哪个包。如果命令存在但不在PATH里先echo $PATH确认然后用绝对路径执行或者临时加PATH。不要一上来就yum install有时只是PATH配置问题。6.3 磁盘满的排查实测df与du的配合磁盘告警时先df -h看哪个分区满了。注意“/dev/sda1 20G 20G 0G 100%”和“/run 2G 1.8G 200M 90%”是不同概念前是真的满了后者可能是tmpfs内存文件系统。然后du -sh /home/*逐级往下找或者直接du -ah /var | sort -rh | head -20列出最大的几个文件。这里有个经典陷阱df显示满了但du统计的目录总大小对不上通常是有进程在写一个已经删除的文件。因为文件被删除但进程仍持有文件描述符空间不会释放。用lsof | grep deleted找到进程重启它或kill掉空间才会回来。6.4 文件名带空格和特殊字符的处理Linux文件名可以包含空格、括号、-开头等各种怪异字符。处理时最容易踩的坑就是忘记引号或转义。比如删除名为a b.txt的文件rm a b.txt会试图删两个文件。正确做法是rm a b.txt或rm a\ b.txt。文件名以-开头时尤其坑因为命令会把它当成选项解决办法是在路径前加--rm -- -file.txt或者用./-file.txt。批量处理带奇怪文件名的文件时find -print0配合xargs -0是稳定方案能避免空格导致的裂开。6.5 Windows与Linux路径的思维转换在Windows下用习惯了反斜杠路径切到Linux或者用PowerShell处理Linux路径时很容易出问题。Linux统一用正斜杠/没有盘符概念Windows的C:\Users\admin对应Linux的/home/admin。还有npm这类工具在Windows PowerShell里经常报“无法加载文件*.ps1因为在此系统上禁止运行脚本”这是PowerShell执行策略限制不是Linux问题但很多刚跨平台的人会被搞懵。处理方法是先理解两个系统对路径和脚本执行策略的不同再按各自规则办事。比如在Windows上要么调整执行策略Set-ExecutionPolicy RemoteSigned要么改用cmd执行在Linux上则要确保脚本有-x权限且用./script.sh执行。跨平台项目里尽量别写硬编码路径多利用$HOME、相对路径或者环境变量。6.6 根据错误码定位路径的方法网上的报错信息五花八门但定位问题路径的思路是一致的。第一步看完整报错不要只盯最后一句话。比如Nginx报404要看access.log里的请求URL和文件路径再看root和alias指令指向的目录是否真实存在。第二步用lsof查看进程打开的文件strace跟踪系统调用能看出程序实际访问了哪些路径。第三步联想FHS目录约定日志在/var/log配置在/etc临时文件在/tmp向这些默认路径排查往往命中率高。有个实用技巧把报错信息里的路径片段复制到搜索引擎往往能直接找到同款问题。但更重要的是形成自己的排查路径模板——看到“cannot open shared object file”就想起ldd和LD_LIBRARY_PATH看到“Permission denied”就按权限五步走看到“No such file or directory”就先确认路径拼写和父目录是否存在。这套文件与目录的认知框架是我这几年在服务器上“折腾”出来的。坦率说刚开始时我也觉得记目录结构很无聊后来才发现几乎所有Linux问题最终都能归结到“哪个文件、哪个目录、哪个路径权限”这三大问。建议你在日常操作中刻意训练每次报错都问自己出问题的文件在哪、它在系统目录结构里的位置合不合理、是不是权限和路径组合出了问题。先在虚拟机里多复制几次目录、多删几个文件再恢复踩过几次坑之后你对Linux文件系统的掌控感会比背一百条命令都来得扎实。