ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux命令实战:从文件操作到运维排错的肌肉记忆训练手册

Linux命令实战:从文件操作到运维排错的肌肉记忆训练手册 1. 这不是一篇教程而是一份“肌肉记忆”训练手册我在一线做运维和开发支持差不多十年带过不少新人也见过太多“背命令”式学习的翻车现场。最常见的对话是新人拿着“Linux命令大全”背了一周问他tar怎么解压到指定目录他先愣三秒然后上网搜最后把包解到了当前目录还浑然不觉。Linux命令这东西本质不是靠背的是靠“用”的。你用它解决过一次真实问题这辈子都忘不掉你光靠看文档三天后全还给教程。所以这篇文章我不打算做那种“命令手册流水账”——那是man page该干的事而是挑出日常最常用、最容易踩坑、面试和实战里出现频率最高的命令每个都配上真实操作场景和输出示例告诉你为什么这么用以及哪些地方是新手必踩的坑。覆盖范围包括文件操作、系统状态排查、进程管理、网络分析、文本处理和Shell脚本基础基本是一线运维和开发每天都会摸到的家伙事儿。适合谁看刚入门Linux想体系化学习命令的同学工作一两年但发现自己是“百度运维”、离了搜索引擎就手生的朋友以及准备面试想快速盘一盘Linux基本功的候选人。有经验的老人也可以翻翻查漏补缺看看有没有你自己一直用反了的参数。开始之前先说明一点我的环境是 Ubuntu 22.04 LTS内核 5.15终端是 bash。绝大多数命令在所有主流发行版上通用个别路径和包名有差异我会单独标注。示例中的输出我都实际跑过不是从网上复制的理论输出。2. 学习命令的正确姿势先理解设计哲学再谈技巧2.1 一切皆文件这不是口号而是行为准则Linux命令看起来零散繁多但背后有一条主线一切皆文件。设备是文件/dev/sda、进程信息是文件/proc/cpuinfo、配置是文件/etc/nginx/nginx.conf、甚至是两个进程之间的管道也是文件描述符。理解了这条主线很多命令的行为就变得有逻辑可循了。比如df -h查看磁盘空间本质上就是在读取/proc/mounts和各个文件系统的元数据ps aux看进程root身份下就是去读/proc/目录下每个数字目录里的comm、stat、cmdline等文件。我见过一个老工程师排查进程异常直接ls -l /proc/PID/fd看进程打开了哪些文件比一堆监控工具都好使。这就是“一切皆文件”思维的实战价值。所以我的建议是学命令别一个一个零散地记而是按照“文件操作、进程管理、系统状态、网络通信、文本处理”这几个维度去建立知识树每棵树上的命令之间有内在关联。比如ps和top都看进程但侧重不同grep和awk都处理文本但定位完全不同。这样学下来你脑子里是一张网不是一盘散沙。2.2 命令帮助体系man、help、info 怎么选不少新手遇到不会用的命令第一反应是搜索引擎第二反应是“网上查”就是忘了系统自己带着帮助文档。作为过来人我强烈建议你养成先查本地文档的习惯。man是绝大多数命令的完整手册命令 --help或命令 -h是快速用法摘要info是比 man 更详细的文档体系。什么时候用哪个我的实践经验是记不住参数用-h想了解功能和设计思路用man。man 手册里除了参数说明还有EXAMPLES部分里面全是官方给的实用示例这是最容易被忽略的宝藏。比如man tar的示例部分甚至比我见过的大部分中文教程都完整。另外一定要学会在 man 页面里搜索按/输入关键词即可别再上下翻页找了效率差十倍。还有一个经验之谈man打开后默认用less分页器浏览按q退出按g跳首页按G跳末尾。你觉得这些不重要等你哪天面对几百行的手册页找某个参数时就知道搜索和跳转有多救命了。顺便说一句man的页码部分对新手不友好别较劲问题不大。2.3 别怕“命令太多记不住”先掌握20%就够用了很多新人被网上那种“700条Linux命令大全”吓住了觉得Liunx太庞大了。我直接给你交个底日常运维和开发场景中你真正高频使用的命令不超过50条能熟练使用其中30条就能覆盖90%的工作。二八法则在这里同样成立。我常用的思路是每次遇到一个需求先想“有没有现成的命令能一步搞定”想不起来就查查完记到自己的笔记里。用这种方式积累命令是你主动“捡”来的不是你被动“背”下来的记忆深度完全不同。我现在带新人最喜欢的考核方式是出实际场景题比如“找出系统里占用磁盘最大的5个文件”“杀掉所有僵死状态的进程”这类能立刻用命令解决的人基本功一定差不了。后面的章节里我每个命令都给应用场景和实操示例你照着练一遍基本就能形成初步的手感。3. 文件与目录操作入门第一课也是终身伴侣3.1 ls、cd、pwd三个最基础的命令反而最容易被忽视ls大概是每个Linux新手的第一条命令但你真的用对了吗大多数人只会ls和ls -l实际上ls的参数组合非常强大。我最常用的一组是ls -lah其中-l列出详细信息、-a显示隐藏文件、-h人性化显示文件大小。还有ls -t按修改时间排序、ls -S按文件大小排序配合head或tail使用能找到最新的或者最大的文件这在排查问题时非常实用。# 找出当前目录下最新的5个文件含隐藏文件 ls -lat | head -6 # 找出当前目录下最大的3个文件 ls -lS | head -4 # 递归列出目录结构 ls -Rcd虽然简单但也有几个容易忽略的技巧。cd不带参数直接回当前用户的家目录cd -在最近两次目录之间切换——我经常在/etc/nginx/和项目目录之间反复跳转全靠cd -省时间。cd ../..往上跳两级cd ~/work去指定用户目录下的work目录。还有个不太常见的CDPATH环境变量设置了之后cd可以像PATH一样在多个目录中搜索不过这个我用得少知道有这么回事即可。pwd也有个被忽略的兄弟参数pwd -P它显示物理路径而非符号链接路径。什么意思你在/var/run下执行pwd显示的是/var/run但pwd -P会告诉你实际上这里是/run。这在写脚本时特别有用因为脚本里如果用普通pwd获取路径遇到符号链接目录就会被误导。3.2 cp、mv、rm复制、移动、删除背后的细节决定成败cp命令我用得最多的是cp -a或者cp -rp用来完整保留文件的权限、时间戳、属主等信息。为什么要保留这些信息我做项目备份时如果cp出来的文件时间戳全是当前时间后续排查“这个配置是什么时候改的”就完全失去线索。特别是复制整个网站目录或者配置文件目录时-a参数几乎是必须的它是-dR --preserveall的合集。cp还有一个容易被忽略的选项-u只在源文件比目标文件新的时候才复制。我用它做简单的增量同步比如把开发机上的代码同步到测试服务器不用每次都全量复制cp -u /home/dev/project/*.py /home/test/project/mv表面上只是移动但它有个隐藏功能重命名。不少新手不知道mv oldname newname就是改文件名还专门去搜“Linux重命名命令”结果搜出个rename然后又纠结语法绕一大圈。mv在跨文件系统移动时有一个需要注意的行为它会变成“复制删除”速度明显变慢而且如果中途断开目标文件可能不完整。所以移动大文件到另一个挂载点之前先确认是不是同一个文件系统用df看挂载点即可。如果必须跨文件系统移动大文件用rsync更稳妥支持断点续传。rm是Linux里最危险的操作之一没有回收站。rm -rf这个组合能摧毁一切但很多人不知道rm -rf的-f参数其实是“强制删除且不提示”-r才是递归删除目录。如果你只是想删一个目录但不确定里面内容别加-f先rm -r它会逐个确认。还有个保命习惯重要目录的删除命令先ls检查路径再执行。我认识一个兄弟当年在公司服务器上执行rm -rf /var /www注意这个空格——他本来想删/var/www结果把/var目录全删了。网上段子不少但真实案例也很常见。我自己的做法是删除之前先echo $PWD看一眼当前目录再用which确认我命令指向的文件确实是我以为的那个文件。另外提一个重要参数rm -i每个文件删除前都会询问。有些发行版默认对rm做了别名比如alias rmrm -i但很多服务器的bashrc里不会配置。我建议你在自己的操作环境里把alias rmrm -i加到~/.bashrc这不是累赘这是保险。别嫌烦等你真的手滑过就会发现这几秒的确认时间非常值。3.3 find、locate、tree查找文件的三种思路find是Linux文件查找的王者命令但它的语法对新手来说稍显复杂。最常见的坑是很多人直接用find / -name xxx结果刷屏一堆Permission denied非常浪费时间。正确做法是把错误信息重定向掉# 在全盘范围查找名为 nginx.conf 的文件 find / -name nginx.conf 2/dev/null # 在当前目录下查找所有 .log 文件并对结果执行 ls -lh find . -name *.log -exec ls -lh {} \;find的-exec参数是我用得最多的高级功能之一。注意{}代表前面找到的每一个文件\;是执行命令的结束符。这里的空格和分号一个都不能少少了就直接报语法错误。写复杂find命令的时候我建议先不要加-exec先跑一遍纯查找看输出是否符合预期确认了再加执行动作。find按时间查找也是排查问题的利器。找出最近24小时内被修改过的文件find /var/log -mtime -1 -type f 2/dev/null这里的-mtime -1表示修改时间在1天以内1则是超过1天。还有个-mmin参数按分钟计。再做一次排查思路的举例如果系统异常发流量怀疑被植入后门我通常会找最近一段时间内被修改的可疑文件find /usr/bin /tmp /var/tmp -mtime -3 -type f 2/dev/null马上能锁定可疑目标。locate命令我不太推荐新环境直接使用因为它依赖一个定期更新的数据库updatedb刚装的系统上往往还没建索引。但它的速度确实快适合在你明确知道文件名关键词、又有索引的情况下快速定位。如果locate找不到但你确定文件存在先执行sudo updatedb强制更新数据库再试。tree命令则是以树状展示目录结构默认系统不自带sudo apt install tree装上之后看项目结构一目了然尤其在给别人讲解目录组织时特别好用。3.4 cat、less、tail、head阅读文件内容的组合拳查看文件内容四个命令各有适用场景。cat适合小文件全文查看less适合大文件分页浏览tail适合看文件尾部新增内容head适合看文件头部内容。我见不少新手拿cat去看几百MB的日志直接刷屏卡死终端最后只得强杀会话。这就是典型的“工具选型不当”。# 查看日志文件实时新增内容运维最常用的命令之一 tail -f /var/log/syslog # 查看最后200行 tail -200 /var/log/syslog # 查看日志中所有出现 ERROR 的行后面文本处理章节会细讲 grep ERROR /var/log/syslog | tail -20tail -f是跟踪文件的实时输出调试服务时开着它一眼就能看到日志滚动。想退出tail -f按CtrlC而不是q这是新手经常搞混的地方。less里则可以用ShiftF模拟实时跟踪类似tail -f的行为按CtrlC退出跟踪模式后还能继续翻页浏览。这两个技巧都很实用。文件阅读还有一个隐藏场景查看二进制文件中的可读字符串。用strings命令比如strings /usr/bin/nginx | grep version能直接提取出二进制文件中内置的版本信息。这个技巧在排查“系统里的这个程序到底什么版本编译的”这类问题时很管用。3.5 tar打包压缩不是“压缩打包”这么简单tar是Linux打包命令的标准答案但它的参数组合太多太杂很多人在这个地方栽过跟头。先说最常用的几个组合# 打包并压缩成 tar.gz tar -czvf backup.tar.gz /home/user/data # 解压 tar.gz 到指定目录 tar -xzvf backup.tar.gz -C /tmp/restore # 只查看压缩包内容不解压 tar -tzvf backup.tar.gz参数里的-c是create创建、-x是extract解压、-z是gzip压缩、-v是verbose显示过程、-f是file指定文件名。我教新人的记忆口诀是“c是造x是取z是gzipf是文件v是报幕”。特别提醒-f参数后面必须紧跟包文件名不能把-f放在很前面然后用完再加其他参数否则会出现“No such file or directory”的困惑报错。tar还有一个常见需求打包时排除某些目录。比如备份网站时要排除缓存目录tar -czvf site-backup.tar.gz --excludecache/* --excludelogs/* /var/www/site注意--exclude参数必须在源目录之前指定而且通配符不是绝对路径的话它会作用于所有匹配的路径层级。我把这个参数写进备份脚本之后备份体积小了差不多三分之一这是个有真实痕迹的经验。另外强烈推荐在写备份脚本时先在临时目录测试一遍解压流程确认备份还能顺利解出来不要等灾难发生时才后悔。有人喜欢用zip打包跨平台友好但在Linux上处理大目录时性能远不如tar gzip。二选一的话我的建议是Linux内部流转用tar需要传给Windows环境再考虑zip。4. 进程与系统状态运维的基本盘就是“看清楚”4.1 ps一分钟看懂所有进程ps命令是查看进程状态的必备工具但新手经常会看“输出好像很乱”。我告诉你一个最简单的招你日常只需要两个组合ps aux和ps -ef。这两个输出格式不同但信息基本等价习惯哪个用哪个。ps aux以用户视角显示进程ps -ef以完整格式显示二者都包含了进程的PID、父进程PPID、CPU占用、内存占用、启动命令等关键信息。# 查看所有进程包含完整命令行 ps aux # 按关键字过滤进程比如查nginx ps aux | grep nginx这里有个经典陷阱ps aux | grep nginx的结果里永远包含一条grep nginx本身的进程因为它带有关键字“nginx”也会被匹配进来。所以实战中在做进程是否存活的判断时要排除掉grep自己ps aux | grep nginx | grep -v grep更优雅的做法是直接用pgreppgrep -l nginxpgrep是专门按名称找进程的不会匹配自己还支持-u按用户过滤、-f按完整命令行匹配。检查服务进程状态时我用得非常多。如果你想马上杀掉匹配到的进程用pkill nginx注意这个命令比killall nginx更推荐因为pkill按名字部分匹配killall需要精确匹配进程名后者在某些场景下反而找不到目标。还有一个组合拳技巧ps -eo pid,ppid,cmd --sort-%mem | head -10按内存占用率降序排列加上head拿前10个一次看清哪些进程在吃内存。排查内存瓶颈时这是第一个命令。CPU同理把%mem换成%cpu。4.2 top与htop实时状态的两副面孔top是Linux内置的实时系统监控器打开后每3秒刷新一次。很多人看top只盯着CPU那一行实际上它的信息量远不止于此。顶部有负载均值load average三个数值分别是1分钟、5分钟、15分钟的平均负载这个数据在排查系统“到底是慢还是忙”时是金标准。负载值超过CPU核心数通常说明系统处于饱和状态。进程列表默认按CPU占用率排序按M键可以切换成按内存排序。不需要记住所有交互按键q退出、M内存排序、PCPU排序、k杀进程会提示输入PID这几个足够日常使用。1键还可以展开成多核视角看每个核的占用情况。htop是top的现代化替代品界面更友好、支持鼠标操作、还有彩色显示但它默认不会安装需要sudo apt install htop。我在自己电脑上必装htop但在生产服务器上通常会克制住不装第三方工具毕竟多一个软件就多一个潜在风险点。如果你在别人的服务器上临时看状态top就足够了。我讲一个真实场景有次生产环境CPU飙到100%我用top发现是PHP-FPM进程占用最高再按M发现内存也快满了初步判断是PHP脚本中有死循环加内存泄露。顺着PID找到对应的访问日志确认了具体请求最终定位到代码里一个while(true)忘写退出条件。整个排查过程从发现到定位不到10分钟全靠top这一个工具。4.3 kill、killall、pkill终止进程的三个武器信号signal是Linux进程通信的一部分kill命令本质不是“杀进程”而是发送信号。默认情况不指定信号发的是SIGTERM15请求进程自己友好退出如果你发现进程收到SIGTERM之后毫无反应再用-9发SIGKILL强制终结。很多新手一上来就kill -9这是坏习惯因为强制终结可能让进程来不及释放资源、保存状态甚至导致数据损坏。# 友好请求进程退出 kill 1234 # 强制终结进程 kill -9 1234 # 按名称匹配并终止注意pkill按名字部分匹配 pkill -f nginx: worker找出PID的方法可以用pgrep nginx | xargs kill配合xargs把前面的输出作为后面的参数这是Linux命令管道精神的经典体现。日常我推荐先pgrep -l确认匹配的进程是自己想要的再kill防止误伤。如果kill之后进程还在但变僵尸了ps状态显示为Z说明它还需要父进程回收kill僵尸进程本身无效要找它的父进程来处理。4.4 free、df、du、uptime硬盘、内存、负载的四件套系统状态排查里free、df、du、uptime这四个命令几乎可以覆盖“内存够不够、磁盘还有多少、目录占多大、系统开机多久负载如何”的全部核心信息。free -h是查看内存和交换分区使用情况最直接的方式-h参数把字节数换成人类可读单位。这里有一个容易误读的地方free输出的available一列才是真正可用于分配的内存而不是简单的free列。Linux内存管理会把空闲内存用作文件缓存buff/cache这部分内存在有进程需要时可以释放掉所以看“内存不够”不能只看free那一列要看available。我有次跟一个新手反复解释 “明明free显示内存快没了为什么系统还能跑” 就是这个原因。free -h # 输出示例简化 # total used free shared buff/cache available # Mem: 7.6Gi 3.2Gi 1.1Gi 12Mi 3.3Gi 4.1Gidf -hT查看磁盘分区使用情况-T显示文件系统类型这在排查“这个目录到底在哪个盘上”时特别有用。再加一个限制df -hT /etc只查看某个目录所在的分区情况。du -sh *则是查看当前目录下每个子目录的磁盘占用总和排查“磁盘空间被谁吃了”的必经之路。注意du不能加-hT它没有-T参数不要记混。uptime一条命令输出四个信息当前时间、系统运行时长、登录用户数、系统平均负载。它还被我用来判断服务器是不是重启过——如果uptime显示才跑了两分钟你排查“服务为什么没启动”时就要先确认是不是重启导致的配置没生效。排查问题的顺序有时候就藏在这种小细节里。5. 网络命令实战从“看得到”到“查得清”5.1 ping、telnet、nc三段式连通性排查网络问题排查有一套标准动作。第一棒是ping测两层三层连通性。注意ping不通不代表网络不通很多服务器故意禁了ICMP协议。我见过新人对着一台禁ping的服务器反复确认网络故障结果业务完全正常。所以ping通了说明网络大概率没问题不通还需要进一步用其他工具确认。第二棒是测端口连通性。老传统是telnet IP 端口但现代Linux默认往往没装telnet客户端。替代方案是ncnetcatnc -zv IP 端口-z不发送数据只检测端口开闭-v显示详细过程。第三棒是看应用层协议是否正常比如用curl -I http://ip:port获取HTTP头信息看服务是否正常响应。三段式排查下来基本就能把问题卡在物理链路、防火墙、服务监听这三个环路的层次上。# 检测端口是否开放 nc -zv 192.168.1.100 22 # 用curl检查HTTP服务返回头 curl -I http://192.168.1.100:80805.2 ss与netstat端口监听与连接状态排查“端口被什么占用了”或者“端口是否在监听”是这个环节的核心需求。老命令是netstat -tlnp新命令是ss -tlnp。ss性能更好、输出更清晰现代发行版几乎都默认带。参数含义-t只看TCP-l只看监听状态-n以数字显示端口不解析域名-p显示占用进程的PID和名称。# 查看TCP端口监听情况 ss -tlnp # 查看所有TCP连接含已建立连接 ss -tnpss -tnp在排查“服务器大量连接处于TIME_WAIT”时很有用。TIME_WAIT连接过多是互联网服务常见问题通常与连接关闭后主动方需要等待一段时间有关。如果发现大量TIME_WAIT可以从系统内核参数net.ipv4.tcp_tw_reuse、net.ipv4.tcp_fin_timeout等角度去优化不过那已经属于进阶内核调优范畴。netstat在旧系统上依然常驻但新环境我建议直接练ss参数逻辑类似但命令名更短、输出更快。5.3 curl、wget命令行里的两个下载访问神器curl是我日常调试接口、验证HTTP服务最常用的工具没有之一。它的-i选项把返回头一起打印出来-v选项显示包括握手、请求头、响应头在内的完整过程-X POST指定请求方法-d带数据-H自定义请求头。一行命令就能像浏览器一样发出请求并看到服务端的完整回应这在排查API问题时的效率远高于打开浏览器F12看半天。# 查看HTTP响应头 curl -I https://example.com # POST JSON数据 curl -X POST https://api.example.com/users -H Content-Type: application/json -d {name:Tom} # 查看完整通信过程排查TLS/HTTP问题利器 curl -v https://example.comwget主要用于下载文件特别是递归下载整个站点目录的场景。日常我下载软件包倾向于用curl -O直接把远程文件保存为本地同名文件用-L跟随重定向很多下载链接会先302跳转到真实地址不加-L只能拿到跳转页面。wget的优势是断点续传。记住这一句话就能选型下载大文件想断点续传选 wget调试接口选 curl。5.4 ifconfig、ip、route网络接口与路由的现代替代ifconfig是老牌网卡配置查看工具但在现代Linux中逐渐被ip命令替代。ip addr看IP地址ip link看接口状态ip route看路由表一个ip命令全家桶全部搞定。我在服务器上排查“网卡没起来”就靠ip link show看状态是不是UP再看ip addr show eth0确认IP是否正常配置。route -n查看默认路由或者用ip route show能发现“为什么外网不通”这类问题是否源于缺少默认网关。对新手来说先别陷入“ifconfig被淘汰还是ip更好”的争论两个都会看就行。很多老系统的脚本里还是ifconfig但新环境建议优先会用ip因为它一个命令涵盖了ifconfig、route、arp等多个老命令的工作。需要修改IP或网关的实操我建议先备份原配置改完用ping验证确认没问题再固化到配置文件这是网络操作的基本素养。6. 文本处理三剑客grep、awk、sed6.1 grep不只是“过滤”grep是Linux文本处理里最基础的过滤器但它的实力远超“搜索关键词”。几个最实用的参数-E扩展正则表达式、-i忽略大小写、-r递归搜索目录、-c统计匹配行数、-v反向匹配排除。# 递归搜索目录下所有包含 error 的文件忽略大小写 grep -rie error /var/log/nginx/ # 统计日志中出现的403次数 grep -c 403 /var/log/nginx/access.log # 排除掉空行和注释行查看有效配置 grep -vE ^#|^$ /etc/nginx/nginx.conf最后这条是我压箱底的排查技巧配置文件里的内容多被注释和空行淹没直接过滤掉之后剩下的就是有效配置一眼看清全貌。这是个信息“瘦身”的思路类似的思路我还会用在别的场景。注意grep -vE里单引号内的正则不用转义但如果用双引号就得小心$、!之类的shell特殊字符被展开。grep还有一个值得一提的用法是显示匹配行的前后文grep -B 5 exception app.log显示匹配行前5行grep -A 5显示后5行-C 5前后各5行。排错时只看单独一行往往不够上下文里有大量线索这个参数用好了等于自带调试器。6.2 sed流编辑器做增删改sed有三个核心应用场景替换文本、删除行、打印指定范围。正常使用频率最高的还是文本替换尤其配合-i参数直接原地修改文件。这个参数又双叒是经典危险操作——sed -i直接改掉源文件改完没法撤销。我个人的习惯是先用不加-i的命令预览结果确认无误后再加-i正式执行。或者再配套一条-i.bak自动生成备份文件。# 把nginx.conf里所有80端口替换为8080先打印预览不加-i sed s/80/8080/g /etc/nginx/nginx.conf # 加上-i.bak直接改原文件并生成备份 sed -i.bak s/80/8080/g /etc/nginx/nginx.conf # 打印文件的第10到20行 sed -n 10,20p /var/log/syslogsed的替换语法s/旧/新/g里最后那个g表示全局替换不加g时只替换每行第一个匹配这两个结果差异非常大。我踩过这个坑想把配置文件里的IP地址全换掉结果漏了一大半原因就是忘了加g。还有一点sed的定界符不一定是/如果你要替换的内容本身包含/比如路径可以用#或|做定界符比如sed s#/old/path#/new/path#g省掉一堆转义符。6.3 awk格式化与提取字段的瑞士军刀awk对新手来说是三剑客里最劝退的但只要抓住核心用法“按列处理文本”就够了。默认按空白字符分列$1表示第一列$2第二列以此类推$0表示整行。配合print输出指定列就能完成大部分需求。# 取出监听端口列表中的本地地址列和进程列 ss -tlnp | awk {print $4, $NF} # 按条件筛选打印CPU使用率超过10%的进程 ps aux | awk $3 10 {print $1, $2, $3, $11}第二条已经体现了awk真正厉害的地方它不是简单的列提取而是自带编程能力的处理引擎。awk内部支持变量、条件判断、循环、内置函数甚至能做统计汇总。我看日志时还常用它来统计每秒请求量把访问日志中的时间戳列提取出来sort之后uniq -c统计频次再sort -nr排序一条管道下来就能看出流量波峰和异常情况。# 统计access.log中每个IP的访问次数取前10 awk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10这条命令组合拳非常值得背下来它用到了awk提取IP、sort排序、uniq -c统计去重计数、sort -nr数字逆序排、head取前10五个命令是Linux管道思想的经典实战。类似的组合还可以用来统计出现最多的URL、User-Agent等做访问日志分析完全够用。7. 用户与权限安全的第一道防线7.1 chmod、chown、umask权限矩阵简单记Linux文件有三组权限属主、属组、其他人每组都是rwx的组合。chmod修改权限chown修改属主和属组umask决定新建文件的默认权限。数值表示法大家可以靠口诀记r4w2x1相加得到最终值。常见的644是文件属主可读写、其他人只读755是属主全部权限、其他人读和执行600只有属主可读写适合密钥文件。# 设置脚本为可执行 chmod x deploy.sh # 把web目录属主改为www-data用户和组并递归 chown -R www-data:www-data /var/wwwchmod的x是给文件加执行权限最常用的快捷方式不用写数字。递归修改权限用-R参数但要注意递归chmod 777在服务器上是灾难操作会让所有用户都能改写文件这是几乎所有Web安全教程都会强调的禁忌。目录权限和文件权限是两回事目录的r是能不能列出内容w是能不能新建删除文件x是能不能进入目录。没有x权限的目录即使有r权限也无法cd进去这个细节我见过好几个人栽过。umask决定新文件默认权限公式是666 - umask得到文件权限777 - umask得到目录权限。多数系统默认umask是022所以新文件默认是644新目录是755。想更安全可以设027这样同一组用户对你的新文件没有写权限。修改umask可以临时执行umask 027或写入~/.bashrc永久生效。7.2 useradd、passwd、usermod用户管理的三驾马车创建用户用useradd但新手经常被“为什么用useradd没有创建家目录”搞懵。这是因为不同发行版默认行为不一样Debian/Ubuntu的useradd默认可能不建家目录而CentOS会建。所以我强烈建议创建用户时不要依赖默认行为显式把参数写全# 创建用户并指定家目录和shell useradd -m -d /home/dev -s /bin/bash dev # 设置或修改密码 passwd dev # 将用户加入sudo组 usermod -aG sudo dev-m创建家目录-d指定家目录路径-s指定shell-aG把用户附加到某个附加组同时保留原有组。尤其是usermod -aG里的-aappend绝不建议省略否则会把用户从现有组列表里替换掉造成权限变动。我见过因为usermod -G不加-a导致用户被移除关键组的案例影响相当严重。排查用户当前在哪些组用id dev加用户到web组用usermod -aG www-data dev这些操作在日常开发环境管理里非常普遍。还有一个容易被忽视的命令是su和sudo的区别su是切换用户身份通常需要目标用户的密码sudo是用当前用户身份以root权限执行单条命令验证的是自己的密码或无需密码取决于sudoers配置。生产环境给开发同学权限时给sudo按需提权比共享root密码安全得多。7.3 passwd文件与sudoers目录权限之外的配置细节/etc/passwd文件每行是一个用户字段用冒号分隔从左到右依次是用户名、密码占位符实际密码在/etc/shadow、UID、GID、用户说明、家目录、登录shell。/etc/group则记录组信息和组成员。查看一个用户的所属组和UIDid命令是最快的方式。sudo的权限配置集中在/etc/sudoers文件但我强烈不建议直接编辑而是用visudo命令来改它会做语法检查语法错误会拒绝保存并提示避免你把sudoers写坏导致所有sudo都不能用。给用户授权一行就够username ALL(ALL:ALL) ALL允许该用户在任意主机以任意用户身份执行任意命令。更精细的授权可以只允许特定命令username ALL(ALL) NOPASSWD: /usr/bin/systemctl restart nginx这样用户重启nginx服务不用输密码但不能干别的。这类最小权限原则的配置在生产环境里很有必要。8. 磁盘与存储从“满了”到“谁占的、怎么扩”8.1 磁盘空间排查四步法提到磁盘空间问题新手往往慌老手走四步。第一步df -hT看大分区谁满了第二步du -sh /dir/* | sort -hr | head -20定位大目录第三步find / -xdev -size 100M -exec ls -lh {} \; 2/dev/null找超大文件第四步lsof L1找出已被删除但还被进程占用的文件。这第四步是大招——有时候你删了文件磁盘空间没释放就是因为还有进程打开着这个文件句柄没有释放。lsof L1能列出这种“幽灵文件”。# 找出被进程占用但已删除的大文件 lsof L1 | grep deleted这个技巧挽救了我不止一次。最典型的是日志文件被rm了但服务进程还打开着磁盘空间并没有真正释放。得找到对应进程重启或让进程重新打开文件才能释放空间。你如果只做前两步永远找不到为什么“删了文件磁盘还是满的”。8.2 mount、umount、开机挂载Linux的挂载操作是把存储设备或分区挂到一个目录挂载点上之后访问该目录就相当于访问设备内容。日常你会接触的挂载形式有物理磁盘分区挂载、ISO镜像文件挂载、网络文件系统挂载。# 挂载一个设备到目录 sudo mount /dev/sdb1 /mnt/data # 卸载设备 sudo umount /mnt/data # 查看当前挂载情况 mount | grep /dev/sdb挂载不是永久行为重启后默认失效。要永久生效得写进/etc/fstab。/etc/fstab的每一行包含设备、挂载点、文件系统类型、挂载选项、dump标记、fsck顺序。我给新手的忠告是修改/etc/fstab之前必须先备份改完先执行mount -a测试确认没问题再重启。fstab写错是导致服务器重启起不来的经典原因之一。注意fstab里建议写UUID而不是设备名如/dev/sdb1因为设备名在不同引导顺序下可能变化UUID是稳定的唯一标识。用blkid可以查看分区UUID。8.3 dd磁盘操作的“手术刀”dd是底层数据复制工具既能备份、又能刻盘、还能做基准测试。但它的破坏性极强因为它是块级别的直接复制不检查文件系统结构。写错目标盘会瞬间毁掉整个分区。一个非常安全的用法是制作启动盘# 把ISO镜像写入U盘务必反复确认of指向U盘而非硬盘 sudo dd iflinux.iso of/dev/sdb bs4M statusprogressif是输入文件of是输出文件bs是块大小statusprogress显示进度。我绝对不推荐在不能确定盘符的情况下执行这行命令——先lsblk看所有块设备确认of的目标就是你心里想的那个U盘。写完启动盘后sync命令确保数据完全落盘再拔出U盘否则可能拷出来的系统不完整。但dd之类操作并不是我写这篇入门指南的核心重点新手知道它用来做镜像写入即可先别急着在重要机器上玩。9. Shell脚本基础把常用命令固化成自动化工具9.1 变量、条件判断、循环脚本的三大支柱当你发现自己反复手动敲那几条命令组合时就该写个脚本了。Shell脚本并不神秘就是用文本文件把命令按逻辑串起来加上变量、判断和循环。变量赋值注意等号两边不能有空格count5是对的count 5会解析成命令调用报错。引用变量用$变量名或${变量名}后者在拼接字符串时更安全。条件判断里if [ -f /etc/nginx/nginx.conf ]检查文件是否存在-d检查目录-z检查字符串是否为空。方括号前后必须有空格这是Shell语法上最容易被忽视的细节。for循环遍历一组文件或数字# 遍历当前目录所有.sh文件输出文件名 for f in *.sh; do echo $f; done脚本第一行#!/bin/bash是shebang指定解释器。写完保存后要chmod x才能执行否则bash script.sh才能跑。这两点我见过无数新手踩坑先记牢。9.2 管道与重定向Shell世界的组合魔法管道符|把上一个命令的标准输出接到下一个命令的标准输入这是Unix哲学“每个命令做好一件事组合起来解决复杂问题”的体现。重定向则把输入输出导向文件或设备覆盖写文件、追加写文件、2重定向错误输出、21把标准错误合并到标准输出。# 把命令的正确输出写到日志错误输出写到另一个文件 ./deploy.sh /tmp/deploy.log 2 /tmp/deploy_error.log # 把全部输出写到一个文件正确和错误合并 ./deploy.sh /tmp/deploy.log 21重定向的顺序有讲究 file 21是标准做法先重定向标准输出到文件再把标准错误指向标准输出当前指向的位置两者都进了同一文件。如果写成21 file标准错误先指向了终端再重定向标准输出到文件两个通道就分家了。这个顺序问题我在脚本里踩过输出日志一半在文件里一半在屏幕上的情况非常迷惑。管道和重定向结合用的场景数不胜数。比如定时备份时把打包结果追加到备份日志tar -czvf /backup/site.tar.gz /var/www /var/log/backup.log 21。这样不管成功失败都有日志可追溯。脚本里加上判断if [ $? -ne 0 ]; then检查上一条命令是否执行成功配上exit 1中断后续流程就是一个标准运维脚本的骨架。9.3 cron与定时任务让Linux自己干活写好的脚本要定时执行靠crontab。crontab -e编辑当前用户的定时任务语法是分钟、小时、日、月、星期 命令。每天凌晨3点执行备份脚本0 3 * * * /usr/local/bin/backup.sh。*表示任意值*/5表示每5个时间单位一次。我最常用的几个cron表达式可以背下来每分钟* * * * *每小时整点0 * * * *每天0点0 0 * * *每周日凌晨2点0 2 * * 0。日志处理、备份、健康检查都可以丢给cron托管但有一点要提醒cron的任务环境变量非常少不会自动加载你的~/.bashrc所以脚本里用到任何命令都尽量写绝对路径比如/usr/bin/tar或者脚本开头先source ~/.bashrc引入环境。否则你手动跑脚本一切正常cron一执行就报“command not found”这几乎是cron新手的第一大坑。10. 常见问题排查实录那些网上搜不到的实战细节10.1 磁盘空间满了但du找不到大文件这套路我前面提过但还是值得完整记录一次。现象df -h显示根分区100%占用但du -sh /统计的总占用远小于df显示的占用怎么找都找不到那几十GB到哪去了。原因就是有进程持有已删除文件的句柄。排查命令# 列出被删除但仍在被进程占用的文件 lsof L1 | grep deleted找到PID和文件名后对应重启服务或者 /path/to/file清空文件让进程继续写入。如果服务不能重启还可以用kill -HUP PID让进程重读配置重新打开日志文件。这个问题如果不了解lsof L1就算把整个磁盘翻个底朝天也找不到答案。顺便说一下lsof命令本身功能很强-i按端口查进程、-u按用户查打开文件都是排障利器。10.2 nohup和后台运行进程和终端“解绑”的艺术远程SSH跑一个长任务关掉终端进程就没了这是新手最常遇到的诡异现象。原因你的命令是SSH会话的子进程会话关闭时SIGHUP信号会发给子进程要求终止。解决办法有两个# 方法一使用nohup启动忽略挂断信号 nohup ./long_task.sh task.log 21 # 方法二使用setsid让进程成为新的会话领头人 setsid ./long_task.sh task.log 21 命令末尾的是把这个进程放入后台执行。nohup是“忽略挂断信号”的简写output.log存运行日志21把错误也算进日志。方法二setsid更彻底直接让进程成为独立会话。更现代的做法是用systemd-run --scope或者写systemd服务但对临时任务而言nohup足够用了。验证进程是否真的脱离了终端可以用ps -eo pid,ppid,sid,cmd | grep task看进程的会话ID是不是变了。顺便提醒只是后台运行并没有脱离终端控制。你关掉终端这个后台进程照样会被SIGHUP终结。想让进程“离开”终端必须配合nohup或setsid这是概念上很多新手混淆的关键点。10.3 命令找不到可能是PATH问题command not found是Linux新手经常撞见的现象但不一定是命令没安装。PATH环境变量定义了shell去哪些目录找可执行文件。如果你要跑的命令在/usr/local/bin而PATH里没这项就会报not found。用echo $PATH查看当前路径用which 命令名查找命令的真实路径用export PATH$PATH:/new/dir临时追加路径。另一个场景是你刚装完软件命令明明存在但就是找不到。这时候先跑hash -r清一下shell的命令缓存。因为bash会把之前查找过的命令路径缓存住装了新版本也不一定立即生效。如果实在找不到用find / -name 命令名 2/dev/null全局搜索或者dpkg -L 包名看包安装了哪些文件——不同发行版有不同包管理命令反正先弄明白路径就行。10.4 服务启动失败从日志和退出码找证据排查服务启动失败的标准流程我总结成四步第一步systemctl status 服务名看服务状态和最近的日志记录第二步journalctl -u 服务名 -n 50看最近50行服务日志第三步手动前台运行命令看直接错误输出第四步查配置文件的语法和权限。# Systemd服务状态 systemctl status nginx # 服务最近的日志 journalctl -u nginx -n 50手动前台运行是定位利器比如nginx起不来直接跑/usr/sbin/nginx -t它会做配置语法检查哪里写错了直接告诉你。这个操作方法比单纯看日志往往更直接。如果服务退出码是127通常是命令不存在或库缺失126是命令存在但不可执行检查权限。这些退出码的含义属于那种“看一次就记住、不看就永远踩”的知识点。排查多了你会发现大多数服务启动失败的原因不是配置写错就是端口被占真正查代码的工作并不多。10.5 系统启动异常这是“救命技能”级别最严重的情况是Linux系统无法正常启动。这类问题处理起来复杂度高但有一个所有新手都该先掌握的基础思路如果启动卡住或崩溃先进单用户模式或救援模式。不同发行版进入方式不同但核心思路是一样的——以最小化环境启动系统绕过有问题的服务做修复。进入救援模式后能做的事很多修改启动配置、修复fstab、重置密码、隔离坏驱动。我见过一个案例服务器重启后卡在A start job is running for /dev/sdb1这样一个挂载等待提示等了90秒然后进紧急模式。排查下来就是/etc/fstab里写了一个UUID不存在的分区系统在等它超时。删除该行后重启恢复正常。这类问题自己修过一次对后面排查同类问题帮助极大。还有个兜底技巧如果系统还能进grub菜单可以在启动项上按e编辑启动参数在linux那一行的末尾加上systemd.unitrescue.target或single直接进入单用户模式不用走完整启动流程。这个招对应急很有用建议收藏虽然希望你永远用不上。11. 写在最后几条持续提升的路径Linux命令的进阶没有捷径但可以有聪明的路径。我建议你把这篇文章里涉及的命令先逐条敲一遍不要复制粘贴手动敲一遍的记忆深度是粘贴的十倍。遇到不确定的参数就man一下把它当工具书用而不是当教材背。实际操作中我自己还有个习惯把新学到的命令组合按“场景”维度记而不是按“命令”维度记。比如“磁盘满了”这个场景下面记df -hT、du -sh、lsof L1、find -size四条命令和它们的组合用法而不是分开记“df是个查磁盘的命令”。场景驱动的记忆方式与遇到问题时的思考路径一致用到的时候直接整套提取效率高得多。最后分享一个我当年带自己学习时的小技巧——每天逼自己用命令行完成一件原本会用鼠标完成的事比如用grep找聊天记录、用find找下载目录里的旧文件、用tar归档这个月的照片。坚持一个月下来命令行就不再是“另外一套操作方式”而是你自然的操作习惯。到了这个阶段再去看那些“Linux命令大全”就不会觉得恐惧因为你已经知道那些命令不是用来背的是用来解决实际问题的每一条背后都藏着一个真实的场景当你遇到那个场景时自然会想起它。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进