第一次登录公司分给我的 Linux 服务器时,我对着黑乎乎的命令行窗口基本是发呆状态。旁边同事丢过来一句“先 ls 看看目录结构”,我敲完ls看到一堆目录名还是不知道下一步该干嘛。后来带新人和实习生,我发现大家都会经历同一个阶段:不是记不住命令,而是不知道在什么场景下该用哪条命令。这篇文章我就把自己平时在服务器上真正高频使用的 Linux 工作常用基础指令,按干活的实际顺序重新捋一遍,不讲考试题,不讲冷门技巧,只讲日常干活真正会碰到的那些操作。适合刚接触服务器的新人、做后端或运维的同事、需要自己部署服务的同学,也适合那些“命令背了不少但上手就卡壳”的朋友。
1. 工作流的拆解:为什么“基础指令”就够用
1.1 从工作场景倒推出指令清单
很多教程喜欢按照“文件管理、用户管理、网络管理、磁盘管理”这种科目分类来罗列命令,学完一整套觉得挺全,但真到工位上打开终端却不知道该调哪条。我的习惯是反过来,从工作场景倒推。
一天里最常干的事无非这么几件:进某台服务器看目录结构,找到某个配置文件或日志文件,改一下配置里的参数,检查系统资源是不是被打满了,把本地代码或产物传到服务器,然后把服务起起来并确认它在正常跑。
对应到指令上,每件事背后其实只有几个核心命令。看目录用ls和cd,找文件用find,看日志状态用tail配合grep,检查资源和进程用top、free、df、ps,传文件用scp或rsync,打扫战场用tar打包解压。你会发现这些命令翻来覆去就那三四十个,单个拆开都不复杂,工作的核心难点反而在于怎么把它们串起来用。
所以别被“Linux 命令大全”那种内容吓到。真正在 Linux 工作里撑起日常需求的,永远是“少而精”的那部分基础指令,剩下的属于遇到专用场景再去翻手册的范畴。先掌握最常用的,再按需扩展,这是我认为最不容易跑偏的学习路线。
1.2 先记一份“最小指令集”
如果让我只留一张表给新手,我会给下面这张最小指令集,按“拿到一台服务器后最可能先做的动作”排序:
| 工作场景 | 核心指令 | 用途 |
|---|---|---|
| 确认自己在哪 | pwd | 防止在错误目录里执行危险操作 |
| 看目录内容 | ls -lh | 带权限、大小、时间地列出文件 |
| 切换目录 | cd、cd -、cd ~ | 快速在不同路径间切换 |
| 找文件/目录 | find | 按名称、时间、大小定位目标 |
| 看日志 | tail -n 100、tail -f | 查看尾部内容和实时追踪 |
| 过滤关键内容 | grep | 在海量输出里捞有效信息 |
| 看进程和资源 | ps、top、free、df | 判断系统是否健康 |
| 打包与解压 | tar -zcvf、tar -zxvf | 部署和备份最常见的操作 |
| 修改权限 | chmod、chown | 解决“权限不足”类报错 |
| 后台挂服务 | nohup 命令 & | 让任务在退出终端后继续跑 |
这张表是骨架,后面几节我会把每个场景的细节和容易踩的坑展开讲。记住一个原则:命令本身只是工具,工作流才是主线。先用这张表把日常流程跑通,比背一百条命令但拼不出完整操作链路要有效得多。
2. 文件与目录操作里的门道:别只背参数,要理解路径与权限
2.1 路径与 ls:每天第一眼的习惯
大部分人一进服务器就敲ls -l,这没错,但我建议习惯用ls -lh。-h会把文件大小显示成“4.0K”“100M”这种人类友好的格式,不然你看到的是一长串字节数,数完位数都不知道那个日志文件是 1MB 还是 1GB。
目录切换也有讲究。cd回到当前用户主目录,cd ..回上一级,cd -返回上一次所在目录,这个我特别推荐记下来。排查问题时经常要在两个深度不同的目录之间来回看,比如一边是/var/log/nginx/access.log,另一边是/home/user/app/config/application.yml,来回敲绝对路径很烦,cd -一下就能在两个位置之间跳,省下的时间很可观。
关于绝对路径和相对路径,我见过不少新人在这上面吃过亏。绝对路径是从根目录/算起,相对路径是从当前目录开始,两种都可以指向同一个文件。但脚本里我强烈建议用绝对路径,因为脚本的执行位置不受你手动控制,一旦中间切了目录,相对路径就会指错地方。这个原则在排查问题时同样适用:拿到一个报错路径,先想清楚它是相对当前目录还是绝对路径,再做下一步操作。
ls还有一个容易忽略的参数是-t,按修改时间排序。排查“今天改了哪个文件导致出问题”的时候,ls -lht一眼就能把最近被改动过的文件挑出来,比一个个翻时间戳高效得多。
2.2 cp、mv、rm 背后那点容易忽略的细节
cp复制文件,mv移动或重命名文件,这两个操作看起来简单,但有几个细节值得单独说。
第一,cp复制目录必须加-r,否则会报“省略了目录”之类的错误。如果希望保留文件的权限和时间戳,用cp -a,这个参数相当于把整个目录原样复制一份,在做备份时非常有用。
第二,mv在同一文件系统内其实只是“改个名字”,速度极快;但如果跨分区移动大目录,系统会先复制再删除,速度会慢很多。理解了这一点,你就不会在移动一个几十 GB 的数据目录时以为机器卡死了。
第三,rm -rf是删除目录的常用姿势,但也是最危险的一条指令。我不反对用,但强烈建议在执行前先echo或ls确认要删除的范围。比如你想删掉/opt/app/log/*下的日志文件,先执行ls /opt/app/log/*看看会展开出哪些文件,确认没有把重要的东西括进来再动手。通配符在 shell 里会先展开成具体路径,如果手滑写成rm -rf /opt/app/*,你删掉的可能就不是日志目录了。
还有一个实战常见的坑:目录里的文件特别多时,rm *.log可能直接报“argument list too long”。这是因为 shell 把通配符展开成了海量参数,一次执行的长度有限。解决办法是用find配合删除,我一般用find /path -name "*.log" -delete,或者find /path -name "*.log" -exec rm {} \;,这样一条条处理,不依赖 shell 展开。
2.3 用 find 一次性定位目标文件
find是“找文件”的终极大杀器,核心用法是按名字找、按时间找、按大小找。
按名字找最常见:find / -name "application.yml"。在公司服务器上,配置文件散落在各个目录是常态,这条命令比一个个猜路径靠谱得多。
按时间找适合“系统今天出了异常,我想知道哪些文件今天被改过”这种场景:find /var/log -mtime -1 -type f,-mtime的单位是天,-mtime -1表示最近一天内,-type f表示只查普通文件,避免一堆目录混进来。
按大小找适合磁盘告警时定位大文件:find / -size +500M,一下子就能把超过 500MB 的家伙揪出来,通常是某个日志文件或备份文件在作祟。
find还能配合-exec做批量操作,比如find /tmp -name "*.tmp" -exec rm {} \;。这个写法里面的{}是“找到的每一个文件”,\;是命令结束符。不过我更推荐配合xargs使用,写成find /tmp -name "*.tmp" | xargs rm -f,处理效率更高。但要注意文件名含空格时xargs会按空格切分,稳妥的方法是find /tmp -name "*.tmp" -print0 | xargs -0 rm -f,用空字符作为分隔符。这条我不要求新手马上背下来,但遇到了解原理,排查问题时能少走很多弯路。
3. 文本处理三件套:日志排查和配置改动的看家本领
3.1 tail、less、cat:看日志的三层用法
cat适合看小文件,直接把整个文件内容打到屏幕上。但日志文件动辄几百 MB 甚至几 GB,cat一下就把终端刷到没法看,所以工作中更常用的是tail和less。
tail -n 100 app.log看日志的最后 100 行,这是定位报错最快的入口。因为程序报错通常发生在最近时间点,而日志文件的末尾就是最新记录。排查问题时我几乎不会从头开始读一个日志文件,都是从尾部往前翻。
实时追踪用tail -f,程序运行时想看它是否有新输出,一条tail -f app.log可以让新日志自动滚动出来。这里有个经验:很多日志系统会做日志轮转,也就是日志文件被改名或者重新创建,普通的tail -f会跟随旧文件的句柄而停止输出,这时候用tail -F(大写 F),它会自动重新打开新生成的日志文件,继续跟踪。生产环境我基本默认用大写F。
当日志文件比较大又需要上下翻看时,less比cat合适。less支持按方向键翻页,按/输入关键字搜索,按n跳到下一个匹配位置。让我印象很深的一个操作是:先用less打开日志,然后按大写F,它也能进入类似tail -f的实时跟踪模式,看完再按Ctrl + C回到普通浏览状态。等于是把“查看历史日志”和“追踪实时输出”合并成了一次操作。
3.2 grep 不只是搜索:上下文与正则
grep是日志排查最常用的指令,但很多人只会grep "error" app.log,拿到匹配行就看到孤零零一行,根本不知道报错发生的上下文。
我常用的参数组合是grep -n -A 5 -B 5 "error" app.log。-n显示行号,-A 5显示匹配行之后的 5 行,-B 5显示之前的 5 行。日志里的异常通常包含多条堆栈信息,只看一个关键字周围的一段才能还原现场,这个组合能直接省掉你反复翻日志的时间。
grep -v用于反向过滤,比如日志里全是“INFO”级别的正常输出,你想看除了 INFO 还有什么,grep -v INFO app.log就把 INFO 行滤掉,异常和 WARN 就浮出来了。
正则表达式是grep的高级形态,日常至少记住这条:用grep -E启用扩展正则,可以一次匹配多个模式。比如grep -E "error|exception|timeout" app.log,一次把三类关键词都捞出来,排查阶段不会漏掉线索。
如果目标文件是二进制或者包含特殊字符,grep 可能输出“Binary file matches”这类提示,这时加-a把它当文本来处理就行。这个坑看似小,但第一次遇到时真的会愣住。
3.3 sed 与 awk:改配置和数日志的两把刀
sed最有用的场景是“批量替换文件内容”。比如把配置文件里的旧地址改成新地址:sed -i 's/192.168.1.10/192.168.1.11/g' application.yml。-i表示直接修改原文件,s是替换命令,g表示全局替换。这个操作在生产环境很常用,但有个前提必须先做的事:备份原文件。我习惯先cp application.yml application.yml.bak,万一替换结果不对,还能快速回滚。
sed还能用来提取文件的一部分内容,比如只看前 20 行配置:sed -n '1,20p' application.yml。-n是安静模式,不输出所有行,p表示打印指定范围。看配置片段时比cat高效很多。
awk则是按列处理文本的神器。默认以空白字符(空格/Tab)作为分隔,awk '{print $1}' app.log就能打印每一行的第一列。最常见的实战用法是统计日志里的访问来源:awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10。这条命令拆开看:awk取出第一列 IP,sort排序,uniq -c统计每个 IP 出现次数,再按次数降序,取前 10 名。我经常用它快速判断是哪个来源在刷接口。
awk -F可以指定分隔符,比如想从一行 CSV 数据里取第二个字段:awk -F ',' '{print $2}'。理解awk的“按列取数”思路后,你会发现很多“数数据”的任务都不需要写脚本,一条命令就搞定了。
3.4 管道与重定向:把命令串成一条流水线
管道符|是 Linux 命令行最精彩的设计,它的含义是把前一个命令的输出作为后一个命令的输入。上面那个统计 IP 的命令就是用四个管道连起来的,每一步的输出都交给下一步处理,像流水线一样。
重定向的三件套也需要彻底理解:>把输出写到文件(覆盖),>>追加到文件末尾,2>&1把错误输出也合并到标准输出里。最经典的写法是nohup ./start.sh > app.log 2>&1 &,我把这条拆解一下:nohup让进程不随终端退出而终止,>把标准输出写到日志文件,2>&1让错误信息也进同一个日志,最后的&让命令在后台执行。这套组合几乎是每个部署脚本里都会出现的。
排查脚本问题时,2>&1的作用尤其明显。如果错误信息没有重定向到文件,你又是在终端里手动跑的,错误还能直接看到;但一旦放进后台或者定时任务里,不重定向的错误信息就会丢,只看日志永远找不到问题在哪。
4. 系统状态与进程排查:出故障时,先看谁占了 CPU 和内存
4.1 先看负载再看进程:uptime、top、ps
服务器卡顿是工作里最常见的“事故”。我拿到一台疑似有问题的服务器时,第一反应是uptime,它会输出当前时间、运行时长和 1、5、15 分钟平均负载。负载数字如果是单核机器,超过 1 就意味着任务排队;如果是多核机器,一般认为负载低于 CPU 核心数还算健康。
然后再用top看现场。top默认按 CPU 占用排序,按P键按 CPU 排序,按M键按内存排序,按1可以展开每个 CPU 核心的使用情况,按q退出。我见过很多同事用top只盯着第一眼的数据,其实top是个交互工具,按不同的键可以切换不同的排序视角,排查 CPU 飙高和内存不足时,排序方式直接决定你能不能第一时间看到肇事进程。
ps用于抓拍进程快照,最常用的写法是ps aux。比如ps aux | grep java可以快速找出所有 Java 进程,看它们的 CPU、内存和启动时间。ps aux的输出里,USER列看运行用户,PID列是进程号,%CPU和%MEM是资源占用,TIME是累计 CPU 时间,COMMAND是启动它的命令。如果看到某个进程 CPU 占用长期维持在几百百分比,基本可以判断它有异常循环或死锁风险了。
4.2 内存、磁盘和“谁占了大头”
内存用free -h看,-h依旧是人类友好的显示模式。输出里注意available列,它比free列更能代表“实际可用内存”,因为现代系统会利用多余内存做缓存,free显示得很低但系统并不一定紧张,available会把可回收的缓存也算进去,更有参考价值。
磁盘用df -h看整体的分区使用率,比如某个挂载点写到 100% 时,服务很可能因为无法写日志而崩溃。这时候再用du -sh /var/log/*逐项看目录占用,用du -h --max-depth=1 /从根目录逐层排查,很快能找到哪个目录堆了几十 GB 日志。
有个非常隐蔽的坑:df -h显示分区 100%,但你把日志文件删了,使用率还是 100%。原因是有一个已经打开的文件占着空间,进程没退出,文件虽然被删了但句柄还在。排查方法是用lsof +L1 | grep deleted,就能列出那些“已被删除但仍被进程占用”的文件,找到对应进程并重启或让它释放文件句柄,磁盘空间才会真正回来。这个问题我遇到过不止一次,没有经验的新人通常会陷入“删了又满了”的循环。
4.3 端口被占用与进程清理
部署新服务时报“端口已被占用”是高频问题。现在的服务器上我建议直接用ss -tlnp,它列出所有监听端口和对应的进程信息,比传统的netstat结果更准确且速度更快。如果想单独查某个端口,比如 8080 被谁占了,ss -tlnp | grep 8080或者lsof -i :8080,lsof 的输出里PID就是占用进程的编号,顺着 PID 用ps aux | grep <PID>看是谁起的,再决定是保留还是清理。
清理进程时,kill有方式区别。默认kill <PID>发送的是 SIGTERM 信号,相当于“请你有礼貌地退出”,进程可以自己清理临时文件和连接;如果它迟迟不退,再用kill -9 <PID>发送 SIGKILL,让内核直接强制结束。我通常先给进程一个体面的退出机会,等几秒不行再上-9,因为直接-9有可能留下临时文件或让配置没有正常落盘。
在top或ps输出里如果看到Z状态,代表僵尸进程。这种进程已经运行结束,但它的父进程没有正确回收子进程状态,所以一直占着进程表条目。僵尸进程本身不占 CPU 和内存,但数量过多会影响系统,解决思路是杀掉或重启它的父进程,由父进程清理。
5. 用户权限与打包部署:上线前最后一步
5.1 权限位的计算:从 rwx 到 chmod 数字
每次用ls -l看到的-rw-r--r--这类一堆字符,实际上是不同对象的权限标记。第一个字符表示类型(-文件、d目录、l软链接),后面每三个字符一组,依次是文件属主、属主所在组、其他人的读/写/执行权限,读为r,写为w,执行为x。
所以-rw-r--r--表示:文件属主可读写,组内用户和其他用户只能读。权限用数字表示时,读r=4,写w=2,执行x=1,加起来就是一组权限。例如7是 4+2+1,6是 4+2,5是 4+1,3是 2+1。
chmod最常见的组合是:目录给 755,普通文件给 644。chmod 755 mydir表示属主有完整权限,组和其他人有读和执行权。配置文件经常因为“其他用户没有读权限”导致服务启动失败,看到“Permission denied”时先ls -l检查文件权限再用chmod修正。注意可执行文件必须有x,比如脚本deploy.sh无法直接./deploy.sh执行,多半是缺少执行权限,chmod +x deploy.sh就能解决。
chown用于修改文件属主和属组,比如部署目录需要由服务账号管理时执行chown -R appuser:appgroup /opt/app,-R递归作用到目录下所有文件。权限报错排查顺序:先看属主是否正确,再看权限位是否足够,最后确认执行用户是否在正确的组里,三步能解决大部分问题。
5.2 打包、解压与跨机传输
日常部署和备份,tar是绕不开的。打包加压缩一条龙用tar -zcvf app.tar.gz /path/to/app,其中z表示 gzip 压缩,c创建归档,v显示过程,f指定归档文件名。解压用tar -zxvf app.tar.gz -C /opt,-C指定解压目标目录,我建议所有解压都先明确目标路径,而不是解压到当前目录把文件散一地。
解压之前先看一眼内容:tar -ztf app.tar.gz,只列出包里的文件列表,不解压。我经常用这条命令确认包结构,避免把路径带回错。
跨机器传文件,scp是大部分人第一个接触的,用法是scp local_file user@host:/remote/path。但日常同步代码和备份大目录时,我更推荐rsync:rsync -avz /local/dir/ user@host:/remote/dir/。-a归档模式保留权限和时间戳,-v显示详情,-z压缩传输。rsync的核心优势是断点续传和增量同步,第一次全量,第二次只传变化的部分,传一半断了,下一次从断的地方继续,比scp强太多。
如果服务器之间需要经常免密传文件,可以配置 SSH 密钥:ssh-keygen -t ed25519生成密钥对,然后用ssh-copy-id user@host把公钥拷到目标机器,之后scp和rsync就不再需要输密码了。这是工作中很常规的配置,能省掉大量反复输密码的琐碎时间。
5.3 让服务稳稳在后台跑:nohup 与相关习惯
在终端里直接执行服务程序,最大的问题是:一旦关闭终端或者 SSH 断线,进程就被挂断。解决办法是nohup。比如启动一个 Java 服务:nohup java -jar app.jar > app.log 2>&1 &。用nohup让进程忽略终端挂断信号,&让它进入后台,日志重定向到文件。
启动之后确认它真的起来了,我用ps aux | grep app.jar或者tail -f app.log看启动日志。有些服务启动到日志出现“Started”才算成功,所以要盯住日志文件。
后台任务管理还有一套习惯:jobs查看当前终端会话里的后台任务,fg把某个后台任务拉回前台。但需要注意,这些只对当前终端会话有效,如果用nohup启动的进程在另一个终端里,jobs是看不到的,这时候用ps和kill配合管理。
关于&&和;的区别也顺便说一句:cd /opt/app && ./deploy.sh表示前一条命令成功后才会执行后一条;cd /opt/app ; ./deploy.sh则不管前一条是否成功都会继续执行。写部署流程时用&&能避免“目录不存在却继续执行脚本”的混乱。
6. 我踩过的 5 个高频坑和排查习惯
6.1 高频报错的速查表
以下是我在平时带人和自己排查时经常遇到的几个基础问题,整理成表格方便对照:
| 现象 | 常见原因 | 排查指令 | 解决办法 |
|---|---|---|---|
| 命令未找到 | PATH 路径里没有对应程序 | which 命令、echo $PATH | 用绝对路径执行,或把目录加入 PATH |
| 权限不足 | 文件属主或权限位不正确 | ls -l | chmod或chown |
| 端口被占用 | 其他进程已经在监听 | ss -tlnp、lsof -i :端口 | 确认后kill对应 PID |
| 磁盘满但删文件无效 | 删除后进程仍占用句柄 | `lsof +L1 | grep deleted` |
| 脚本执行报错 | 换行符是 Windows 风格 | file script.sh | 用dos2unix或 sed 转换 |
| 后台任务关终端就死 | 没有用 nohup 或 tmux | 确认启动方式 | 重新用nohup ... &启动 |
6.2 三个我踩过又最容易被忽略的坑
第一个坑是命令找不到,也就是“明明装了软件,一执行就 command not found”。多半原因是软件安装到了某个目录,但该目录没有加进 PATH 环境变量。排查用which 命令,如果没有任何输出,说明 PATH 里没有它。临时执行可以用绝对路径,想长期生效就把路径追加到.bashrc里,然后source ~/.bashrc。
第二个坑是写了脚本却执行不了,明明看起来权限没问题。用file script.sh检查格式,如果是“with CRLF line terminators”,说明是 Windows 换行符导致的。先sed -i 's/\r$//' script.sh转换一下,或者直接dos2unix script.sh,之后再执行就正常了。这个坑在团队协作跨平台提交脚本时非常常见。
第三个坑是rm误删和通配符展开出错。我之前犯过一次“本来想删临时目录,结果变量没赋值,命令变成了rm -rf /”的错误。现在我的习惯是:删除前先用echo打印表达式确认展开结果,再在目录内小心执行;重要文件和目录永远先备份到/tmp或另一个分区,而不是直接删。Linux 没有“回收站”的概念,rm 出去的文件是真的找不回来了,所以凡是带递归删除的操作,我都要求自己先想三秒钟。
6.3 让日常操作更顺手的几个习惯
基础指令学会了,但如果能配合一些“软习惯”,日常效率还能再上一个台阶。
第一是善用 Tab 自动补全。路径太长时不要一个个字符敲,输入前几个字符按 Tab 键,终端会自动补全剩余部分;有歧义时连按两次 Tab 会列出所有候选。这个习惯能防拼错,也能防因为输错路径而碰到的各种诡异问题。
第二是把常用别名写进.bashrc。比如alias ll='ls -lh'、alias g='grep',直接用ll代替ls -lh,几分钟就能让操作节奏快起来。.bashrc修改完记得source ~/.bashrc让它生效。
第三是历史命令的妙用。按方向键上可以翻历史命令,history显示批记录,!加编号可以重复执行某条历史命令。写长命令出错时,直接在历史里往上翻再修改,比重新敲一遍稳得多。
第四是善用Ctrl + C中断误操作,Ctrl + Z挂起当前任务。想退出less用q,想退出tail -f用Ctrl + C,这些快捷键顺手之后,终端就不会再出现“进去了却退不出来”的尴尬。
最后分享一个我自己的习惯:每次登录服务器后,不急着马上敲业务命令,而是先用pwd确认自己在哪个目录,再用df -h瞄一眼磁盘,最后uptime看下负载。别小看这十几秒的固定动作,它帮我在问题发生前就发现了不少磁盘打满和负载异常的情况。把这些基础指令练成肌肉记忆之后,你会慢慢发现,所谓“Linux 基础”能覆盖掉九成以上的日常工作,剩下的那些疑难杂症,靠排查思路和查手册也基本都能搞定。