干了这么多年Linux运维,每天绕着服务器转,说实话真正天天用的命令翻来覆去也就那几十条。但很多刚接触这块的朋友,一上来就捧着几百页的“命令大全”硬啃,今天记了明天忘,真到了服务器上照样抓瞎。我自己带新人的时候也一直在强调一件事:学Linux命令,重点不在“背了多少”,而在“理解它在解决什么问题”。
这篇东西就是想干一件事——把Linux里边最常用的基础命令,按照“实际干活”的角度重新捋一遍。不是把man手册搬过来抄一遍,而是站在一个每天要操作服务器、排查问题的人的立场,讲清楚哪些命令必须掌握、每个命令最核心的参数是什么、真正的使用场景长什么样。同时会穿插大量我在真实服务器上踩过的坑、总结的经验,以及调试问题时的完整思路。
这套东西适合谁看?刚入行的运维新手、准备转行做后端或嵌入式的开发者、还有那些用虚拟机装了Linux却不知道下一步该干什么的学生党。如果你已经有几年经验,也可以跳着看第5章以后的内容,那里有不少平时不太容易注意到的细节。总之,把这些命令理解透了,Linux的大门就算真正推开了。
1. 内容整体设计与思路拆解
很多培训机构把Linux课程设计成“命令词典”,一天讲50个命令,一周下来好像什么都见过,一上手却什么都干不了。我自己更倾向于“按需驱动”的方式来学习,也就是先把服务器使用中最高频的场景拆出来,针对每个场景去学对应的命令组合,这样学完马上能上手。
我们看看一个典型服务器管理员的日常工作流。早上到公司,先看服务器负载,用uptime、top;接着检查磁盘空间,用df -h;然后昨天的脚本跑失败了,要看日志,于是用tail、grep;再然后有人反馈网站打不开,就要查端口、查进程、查网络连接,大概率会用到ss、ps、netstat;如果发现服务挂了,需要用systemctl重启服务;如果不行就查journalctl看日志。到下午要部署新版本代码了,就要打包上传、解压、移动文件、改权限、改所有者,这时候tar、mv、cp、chmod、chown全用上了。
发现没有?真实工作流里用到的命令,远远没有“命令大全”里那么多,但这些命令的使用频率极高,而且往往是多个命令搭配在一起,形成一套解决问题的“组合拳”。所以这篇内容的编排方式不是按字母表列命令,而是按功能域划分:文件与目录操作、文本处理、用户与权限、进程与系统状态、网络排查、软件包管理,每个功能域配合典型的“工作场景”来讲。
在学习路径上,我也推荐大家别在IDE上装什么图形化插件,直接从命令行开始。Linux服务器的生产环境99%是没有图形界面的,你敲进去的是命令,出来的只有回显。习惯了纯命令行的环境之后,你对系统底层的理解会清晰很多。
再有就是命令的“知识颗粒度”问题。很多新手会陷入一个极端:把命令的每一个参数都背下来,比如ls的每个选项什么意思。这完全没必要。我的建议是每个命令只需要记住核心业务场景对应的“高频参数组合”,其他参数等遇到了再查man,一点都不丢人。实际上我身边干了十年的运维,也经常需要查命令参数,这本身也是一种工作习惯。
最终的设计思路就是一句话:把命令学成“解决问题的工具”,而不是“背名词的考试”。下面每个章节我都会按场景展开,并在关键时刻解释命令背后的机制,让你理解为什么这个命令要这样写。
2. Linux命令的底层逻辑与学习密码
聊具体命令之前,必须先花一点时间搞清楚Linux命令的底层逻辑。如果这个不搞清楚,你后面会遇到一个很常见的困惑:为什么别人的命令一长串,我却看不懂在干嘛。
2.1 Shell和命令的本质
你在终端里输入的所有命令,其实都不是Linux内核直接处理的,而是由一个叫Shell的中间层程序接收并解析的。默认用的是Bash,它的作用就是把你要执行的命令翻译成系统调用,再交给内核去操作硬件资源和文件系统。
你可以在Shell里做大量“编程”性质的操作,比如用管道把多个命令串联起来、用重定向把输出存到文件里、用通配符批量匹配文件。这才是Shell真正的威力所在。举例:
ps aux | grep java | grep -v grep这条命令就是先查看所有进程,再从结果中过滤出含“java”的进程,最后排除掉那条grep命令本身。管道符|在这里把前一个命令的输出当成后一个命令的输入。很多新手第一次看到这串代码会懵,但理解了Shell的这种数据流向之后,你会发现这是非常自然的设计。
2.2 命令、选项与参数的关系
标准的Linux命令格式是:
命令 [选项] [参数]命令是你要执行的程序名,选项用来调整行为,参数则指定要操作的对象。比如:
ls -lh /var/logls是命令,-l表示使用长格式显示,-h表示以人类可读的方式显示文件大小,/var/log就是要查看的目录。其中-lh等价于-l -h,可以合并。这就是为什么你看到很多老手敲命令很快,因为他们把高频选项合并成肌肉记忆了。
2.3 一切皆文件
这个理念是理解Linux系统的钥匙。在Linux世界里,普通文件、目录、硬件设备、甚至进程的状态信息,都通过文件系统来暴露。也就是说,你打开设备是去读一个文件,查看进程信息是去读/proc目录下的文件。由此衍生出的操作逻辑也很一致:只要能读文件,你就能拿到数据;只要能写文件,你就能下发配置。
做运维排查问题时,这种“文件化”的思路尤其有用。比如CPU信息:
cat /proc/cpuinfo内存信息:
cat /proc/meminfo系统运行时间与负载:
cat /proc/loadavg当你理解了系统的状态都以文件形式暴露在/proc和/sys下时,很多排查命令的原理你瞬间就懂了。free不过是在读取并格式化/proc/meminfo,ps不过是在解析/proc目录下的进程信息。这不神秘。理解到这层,就算系统里没有top、free这样的工具,你也能用最基本的cat命令手动获取想要的数据。
3. 高频核心命令解析与实操应用
现在进入正题,把Linux基础命令中最核心、最实用的部分逐个拆开揉碎。我按实战维度组织,从文件操作开始,再到文本处理、权限管理和系统运维,这一条线走下去,你会逐渐感受到命令之间的协同关系。
3.1 文件与目录操作:最日常的工作台
对服务器使用者来说,文件和目录相关的命令是每天的必修课,操作频率最高,出错的代价也往往最大。
先说pwd,作用是显示当前所在目录。这个命令虽然简单,但脚本里经常用到,因为你需要确认自己到底在哪个位置。cd用于切换目录,常用参数是-,可以快速回到上一次所在目录。~代表当前用户的家目录。我经常看到新手在路径不明确时乱敲cd,然后迷失在文件系统里,这时候请记住pwd和cd -这对救命的组合。
ls命令用得最多的是这几个参数:
ls -l # 长格式查看,包含权限、所有者、大小、修改时间 ls -a # 显示隐藏文件 ls -lh # 配合-l,让文件大小显示为K、M、G这种可读格式 ls -lt # 按时间排序,最新的排最上面,排查日志生成时很有用 ls */ # 只看目录我平时排查问题时最喜欢搭配ls -lh来看大小,如果某个日志文件已经几个G了,先不管权限设置得对不对,磁盘可能马上就满了,得抓紧处理。
目录创建用mkdir,注意mkdir -p可以递归创建多层目录:
mkdir -p /data/logs/nginx这条命令会把/data、/data/logs、/data/logs/nginx一次性建好,如果不存在的话。没有-p参数的话,每层父目录都必须存在,否则就会报错。这个-p参数同时也可以用来检测目录是否存在:如果已经存在,加上-p就不会报错。
删除文件和目录用的是rm,但这是所有Linux命令中最容易出事故的一个,没有之一。
rm file.txt # 删除文件 rm -r mydir # 递归删除目录 rm -f file.txt # 强制删除,不提示 rm -rf mydir # 递归强制删除rm -rf被称为“删库跑路”命令不是没有道理的。很多人根目录下敲成rm -rf /然后手一抖补了个空格参数,整台机器就没了。我的经验是:任何涉及到删除的高危操作,在回车前反复确认路径,尤其不要用变量拼接路径去执行rm -rf。比如脚本里写了
rm -rf $DIR/*如果$DIR因为某种原因是空的,这条命令就变成了rm -rf /*,后果极其严重。生产中这类事故不少见,所以我现在写脚本都建议先判断变量是否为空,或者用find配合-delete来精确删除。还有一个更安全的办法是给rm设置别名:
alias rm='rm -i'这样每次删除都会提示确认,虽然有时烦一点,但能救人一命。
复制和移动文件用的是cp和mv:
cp file.txt /backup/file.txt.bak # 复制文件 cp -r conf.d/ /backup/conf.d/ # 递归复制目录 mv oldname.txt newname.txt # 重命名文件 mv file.txt /data/ # 移动文件到其他目录cp常用参数有-r(递归复制目录)、-p(保留权限、所有者、时间戳)、-a(归档模式,等于-dpR,常用于备份)。一个容易忽略的点是:mv操作如果你跨文件系统(比如从/home移动到/data,而它们属于不同磁盘分区),实际上会执行“复制+删除”两步,耗时较长,所以大文件迁移时最好提前确认磁盘空间是否充足。
查找文件是新手最容易卡壳的地方。find虽然看起来复杂,但掌握了固定套路就很顺手:
find /data -name "*.log" # 按文件名查找 find /data -type f -size +100M # 查找大于100M的文件 find /data -mtime +7 -type f # 查找7天前修改过的文件 find / -name nginx.conf 2>/dev/null # 错误信息重定向,找配置文件必备很多新手不知道2>/dev/null是什么意思,这里的2是标准错误输出的文件描述符,/dev/null是Linux的黑洞设备,把错误信息扔进去,屏幕就不会刷出一堆“Permission denied”了。
还有个命令which也必须知道,它用来定位一个命令的可执行文件路径:
which python3 # /usr/bin/python3当你系统里装了多个版本的Python或Java时,用which确认到底用的是哪个路径下的版本,能省掉很多环境变量层面的排查时间。
3.2 文本内容查看与搜索:日志排查的命根子
服务器排障,绝大多数时间是在看文本内容,尤其是日志。所以文本相关命令的熟练程度,直接决定你排障的速度。
查看文件内容,最基础的是cat,它适合查看小文件。如果文件很长,cat会把全部内容刷到屏幕上,根本看不过来。这时候你需要的命令是less:
less /var/log/messagesless支持上下翻页、按/搜索关键字、按q退出。有个附带的好处是,它读取大文件时不会像cat那样一次性全部加载进内存,处理上百M的文件也很轻松。在排障场景里,我几乎不用cat看大文件,less是首选。
如果要看文件的头部或尾部,则用head和tail:
head -n 20 /var/log/messages # 查看前20行 tail -n 50 /var/log/messages # 查看后50行 tail -f /var/log/nginx/access.log # 实时跟踪日志输出,调试神器tail -f是我用得最多的命令之一,特别是调试接口或者观察应用日志的时候,开一个终端窗口盯日志,开另一个终端发请求,日志里的报错马上就能看到。
然后是搜索文件的绝对主力grep,它可以按正则表达式匹配文本内容:
grep "ERROR" /var/log/app.log grep -i "error" /var/log/app.log # 忽略大小写 grep -r "timeout" /etc/nginx/ # 递归搜索目录下所有文件 grep -n "exception" src/main.java # 显示匹配行号用grep过滤别的命令的输出是更进阶的用法。比如看Java进程中有没有出现内存相关的异常:
java -jar app.jar 2>&1 | grep -i "outofmemory"这条命令把Java程序的输出通过管道交给grep来过滤,只把匹配“OOM”的行显示出来。后面加的参数2>&1的含义是“把标准错误输出重定向到标准输出”,这样Java产生的错误日志也能被grep捕获到。这套组合是排查应用运行错误时的入门必备。
针对大日志文件,我一般还会配合grep的上下文参数:
grep -C 5 "Exception" /var/log/app.log # 显示匹配行之前和之后各5行这样能看到异常抛出前后的相关日志,排错效率翻倍。
3.3 用户与权限管理:Linux安全体系的基石
Linux是一个多用户系统,权限控制是它的核心安全机制。很多新手在这块栽跟头,主要原因是搞不明白用户、用户组、权限这三者之间的关系,以及对实际命令的误用。
先看用户相关命令。创建用户用useradd,设置或修改密码用passwd:
useradd zhangsan passwd zhangsan useradd -m -s /bin/bash lisi # 创建用户并同时创建家目录,指定Shell usermod -aG wheel zhangsan # 将用户加入wheel组,用于授权sudo userdel -r zhangsan # 删除用户并删除家目录这里面有个很容易踩的坑:在CentOS等系统上,执行完useradd zhangsan如果不加-m参数,默认可能不会自动创建/home/zhangsan这个家目录。不同的系统发行版默认配置不一样,所以我在创建用户时都会显式加上-m,保证行为一致。
id命令可以查看当前用户的UID、GID和所属组列表:
id zhangsan # uid=1001(zhangsan) gid=1001(zhangsan) groups=1001(zhangsan),10(wheel)Linux系统是靠数字ID来识别用户的,用户名只是给人看的映射。如果两个用户UID相同,系统会认为它们是同一个用户,所以做备份迁移时千万别随意改UID。
权限方面,先看一长串ls -l的输出:
-rw-r--r-- 1 root root 1234 Feb 15 10:30 app.conf第一个字符是文件类型,-代表普通文件,d代表目录,l代表符号链接。后面9个字符每3个一组,分别是文件所有者(owner)、所属组(group)、其他用户(others)的权限。每组里面,r表示读权限,值为4,w表示写权限,值为2,x表示执行权限,值为1。没有对应权限则为-。
于是修改权限的命令chmod你就可以理解得很透彻了:
chmod 644 file.txt # 含义:owner可读写(4+2=6),group可读(4),others可读(4) chmod 755 script.sh # 含义:owner可读写执行(4+2+1=7),group可读执行(4+1=5),others可读执行(5) chmod +x deploy.sh # 含义:给文件加上执行权限,相当于把x加给所有者、组、其他人 chmod -R 750 /data/app/ # 含义:递归修改目录下所有文件和子目录的权限为750为什么目录的权限和文件一样重要?目录的x(执行)权限实际上代表“能否进入这个目录”,r权限代表“能否列出目录内容”,w权限则代表“能否在目录中创建/删除文件”。所以如果在部署时给某个目录设了777权限(所有人都可读写执行),意味着任何系统用户都能往这个目录里放文件、删文件。这在生产环境是非常危险的。
修改文件的所有者和所属组用chown:
chown zhangsan:zhangsan app.conf chown -R nginx:nginx /usr/share/nginx/html/典型场景是:你用root用户发布完网站代码,但Nginx进程是以nginx用户运行的,就必须把站点目录所属者改成nginx,否则Nginx没有权限读文件,前端就会报403。这类问题在运维群里几乎每天都在出现。
还有两个命令需要区分清楚:su和sudo。
su - root # 切换到root用户,需要root密码 sudo -i # 以root身份执行,需要当前用户密码,且用户具备sudo权限 sudo systemctl restart nginx # 临时以root身份执行单条命令在生产环境中,我更推荐用sudo而不是直接su - root。原因一是安全审计——所有sudo操作都有日志记录,出问题能追溯;原因二是不用共享root密码,降低风险。
3.4 系统运行状态与资源监控:性能排查的基础课
当服务器出现卡顿或服务不可用时,你要能快速判断系统的瓶颈在哪里,这就离不开一系列系统状态查看命令。
先看平均负载:
uptime # 17:30:01 up 10 days, 4:32, 2 users, load average: 0.08, 0.03, 0.01最后三个数字依次是过去1分钟、5分钟、15分钟的平均负载。这里要注意一个理解误区:负载高不等于CPU使用率高。负载代表的是“正在运行和等待运行的进程平均数”,它包含CPU密集型任务,也包含不可中断的I/O操作。如果负载很高,但CPU使用率不高,那瓶颈可能是磁盘I/O或者进程在等待其他资源。
进程查看用ps:
ps -ef ps aux这两条命令输出的信息大同小异,ps aux的格式更便于阅读。重点关注%CPU、%MEM以及STAT这一列。STAT里常见的状态有:R(运行中)、S(睡眠,可中断)、D(不可中断睡眠,通常是在等待I/O)、Z(僵尸进程)。如果发现大量Z状态的进程,意味着父进程没正确回收子进程,需要排查代码。
动态监控用top,输入top后可以看到实时的进程排行和系统负载。在top界面里我还常用几个快捷键:
1:展开所有CPU核心的使用率M:按内存使用量排序P:按CPU使用率排序k:输入PID杀掉进程
比top命令更直观的是htop,颜色丰富、支持鼠标操作,实际体验确实好很多。如果系统装了就用htop,没装的话用top也完全够用。
内存监控用free:
free -h有人看到free输出中available不大就紧张,其实现代Linux系统会尽量利用空闲内存做文件缓存(Page Cache),这跟Windows的处理逻辑不一样。重点看available这一列,它估算的是“在不触发swap的前提下还可以分配多少内存”,比看free列更准确。真正危险的是可用内存持续降低并开始大量使用swap,这时候系统性能会急剧下降。
磁盘空间用df和du:
df -h # 查看每个挂载点的总容量、已用、可用空间 df -i # 查看inode使用情况,inode耗尽也无法写新文件 du -sh /var/log # 查看某个目录的总大小 du -h --max-depth=1 /data # 查看/data下一级目录的大小分布我在处理“磁盘满了”告警时,一般先df -h确认是哪个分区满,然后到对应目录下用du -sh *一级一级往下找,用不了两分钟就能锁定大文件位置。还要记得看df -i,因为ext4/xfs文件系统的inode数量是固定的,当小文件数量多到把inode耗尽后,df -h显示磁盘还有空间,但你就是创建不了新文件,这是特别容易踩坑的一类问题。
3.5 进程管理与系统服务:让程序乖乖听话
对于服务器上的服务进程,Systemd已经成为现在主流发行版的标准进程管理器。需要掌握的命令并不复杂,但背后逻辑值得了解。
查看服务状态:
systemctl status nginx如果服务处于running状态,后面会显示进程号、内存占用和最近日志。如果状态是failed或inactive (dead),那就需要进一步查看日志来确认原因。
启动、停止、重启和开机自启:
systemctl start nginx systemctl stop nginx systemctl restart nginx systemctl enable nginx systemctl disable nginx这里我想多说一句restart和reload的区别。restart是完整停止再启动,会断开所有现有连接;reload则是让进程重新加载配置文件,对于Nginx这类支持平滑重载的服务,只会用新配置启动新的worker进程,再把旧进程优雅退出,不断开现有请求。所以修改完配置后的首选操作应该是:
systemctl reload nginx只有在你改了很底层的配置(比如监听端口、用户权限等)后,才需要restart。
如果服务不是由systemd管理,而是直接跑起来的进程,需要杀进程时的命令是kill。最简单的用法是:
kill PID # 发送TERM信号,请求进程正常退出 kill -9 PID # 发送KILL信号,强制结束进程kill -9虽然简单粗暴,但我建议在大部分场景下先尝试普通的kill,给进程一个善后清理的机会。实在没反应了再上-9。还有pkill可以按名字匹配杀进程,生产环境慎用,因为它可能误杀多个同名进程。
查看端口占用是排查联调问题时的常用操作:
ss -lntp在新版Linux发行版中,ss已经取代了老旧的netstat,输出更快速清晰。-l表示只显示监听状态的端口,-n表示不解析域名,-t表示TCP协议,-p表示显示对应进程PID。如果看到某个端口被占用,可以用这个命令快速定位是谁占的:
ss -lntp | grep 80803.6 网络排查实用命令
网络问题排查是一个大话题,这里只挑基础命令讲,这些命令足以解决多数日常网络异常。
先看连通性,用ping:
ping -c 4 baidu.com-c指定发包数量。如果目标是通的,说明链路和DNS解析基本没问题。接下来检查DNS解析结果,用dig或nslookup:
dig example.com nslookup example.com如果域名解析到的IP和你预期的不一致,可以再看本机的DNS配置文件:
cat /etc/resolv.conf查看系统路由和默认网关:
ip addr ip routeip addr用于查看网卡IP地址,ip route查看路由表,默认路由一般是你流量的出口网关。当你的服务器外网不通时,先确认网关是否正常,再排查防火墙。
测试到某个端口的连通性,用telnet或者nc:
telnet 192.168.1.10 3306 nc -zv 192.168.1.10 3306如果telnet能连上,说明对方的3306端口是开放的,网络层和应用层都没问题。如果连不上,可能是防火墙拦截、端口未监听或服务没启动。这种测试方法在做MySQL、Redis这类服务的远程连接排查时非常管用。
如果服务器上有防火墙服务(比如firewalld或iptables),需要能查看和放通端口:
firewall-cmd --list-all firewall-cmd --add-port=8080/tcp --permanent firewall-cmd --reload用云服务器的朋友要注意,云安全组策略也要检查,它往往在系统防火墙之外又加了一层。常常遇到的情况是系统防火墙已经放开了,但云安全组没放行,从外部一样连不上。
3.7 软件安装与压缩打包:部署的基础
在CentOS等RHEL系发行版上,软件包管理用yum(新版本是dnf),在Ubuntu/Debian系上用apt。
# yum/dnf yum install -y nginx yum remove nginx yum update -y # apt apt update apt install -y nginx apt remove nginx注意:在使用yum或apt安装软件前,最好先搜索是否存在该软件包:
yum search nginx apt search nginx这样能确认包名是否准确,避免“No package xxx available”的报错。
如果软件不在系统源中,通常需要先安装EPEL(Extra Packages for Enterprise Linux)这类扩展源,或从官方仓库下载rpm/deb包直接安装:
yum install -y epel-release rpm -ivh package.rpm dpkg -i package.deb跟包管理器紧密相关的还有压缩打包命令tar。注意一个概念:tar原本只是“把一堆文件打包成一个文件”,本身不提供压缩能力,但通常会和压缩算法一起使用。
tar -czvf app.tar.gz /data/app/ tar -xzvf app.tar.gz tar -xzvf app.tar.gz -C /opt/拆解一下参数:-c表示创建归档,-x表示解压,-z表示通过gzip压缩/解压,-v表示显示过程,-f后面跟归档文件名。另外-j对应bzip2压缩,-J对应xz压缩。看到文件名后缀是.tar.bz2或.tar.xz时,把-z换成-j或-J即可。
我在打包时习惯加上--exclude参数排除无关内容:
tar -czvf backup.tar.gz --exclude='cache' /data/app/把不需要打包的缓存目录排除掉,既减小了压缩包的体积,也避免了把运行时产生的临时文件也备份走。
4. 从纯命令到工作流:综合场景实操演示
单独学完命令不代表会干活,真正的考验是把命令组合成一套操作流程。我挑两个最典型的运维场景,完整演示“接到任务后怎么一步步操作”。
4.1 场景一:新服务器环境初始化
假设你收到一台新申请的云服务器,要把它配置成一台能跑Nginx的Web服务器。完整流程如下。
先确认系统版本和基本信息:
cat /etc/os-release uname -a hostnamectl如果主机名不合理,改一下:
hostnamectl set-hostname web01官方源在国内可能不稳定,可以考虑换成国内镜像源。修改源配置前先备份原文件,这是我一直强调的习惯:
cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak然后更新缓存并安装常用工具:
yum makecache yum install -y vim wget curl net-tools tree lsof接着安装Nginx:
yum install -y nginx systemctl enable nginx systemctl start nginx启动后立即确认端口已经在监听:
ss -lntp | grep 80如果浏览器访问不了,就要按网络排查思路一步步验证:先在本机curl -I http://127.0.0.1,再查云安全组和防火墙。如果本机curl没问题,外部不通,基本可以断定是防火墙或安全组问题。
4.2 场景二:定位“CPU飙到100%”的故障
遇到告警说某台服务器CPU使用率持续100%,该怎么办?按下面的顺序做就好。
第一步,用uptime看当前负载是否正常:
uptime第二步,用top看是哪个进程吃CPU:
top在top里按P按CPU排序,记下占用最高的PID。如果那个进程是可疑的PHP进程或Java进程,接下来要确认是不是业务代码里的死循环或密集计算。
如果是Java应用,可以用jstack导出线程栈,看具体在跑什么代码:
jstack PID > thread_dump.txt top -H -p PID # 查看该进程下所有线程的CPU占用,找到具体线程PID将线程PID转换成十六进制:
printf '%x\n' 线程PID再到thread_dump.txt里搜索对应的十六进制线程号,就能定位到具体的Java代码行。整个过程看起来有点绕,但排查Java性能问题就是这么操作的。
如果是普通进程占CPU高,也可以用perf top查看它的调用栈,或者用strace -p PID跟踪系统调用,看它到底在干什么。
处理完问题后,别忘了检查是不是因为代码缺陷导致进程反复崩溃重启,systemctl status的状态和journalctl -u service-name日志会告诉你答案。
5. 常见问题与排查技巧实录
长期使用Linux命令过程中,我积累了一批高频问题和对应的排查思路,整理出来供大家参考,每一条都是实际工作中反复遇到的。
5.1 命令找不到或提示Permission denied
遇到command not found时,先别急着说系统没装这个命令。排查步骤是:确认拼写是否正确,然后用which看看包是否真的没装。如果命令确认存在但提示权限不够,再检查执行权限和当前用户的sudo权限。
如果某个命令存在于/sbin或/usr/sbin目录下,普通用户的PATH中未必包含这些目录,直接执行会提示找不到。解决办法是用全路径运行:
/sbin/iptables -L或者临时把目录加进PATH:
export PATH=$PATH:/sbin5.2 文件删不掉,提示“Text file busy”
这个报错通常发生在你想覆盖一个正在被进程执行的二进制或脚本时。Linux不会阻止你删除正在执行的二进制文件,但如果你尝试用mv覆盖它,就会收到这个提示。解决办法是先停掉相关进程再替换,或者用cat newfile > oldfile这种原地写入方式来绕过。
5.3 磁盘空间没满却写不了文件
早前讲过,第一反应看df -i,大概率是inode耗尽了。小文件太多会占满inode,常见于/tmp或/var/spool目录下面堆积了大量缓存或邮件。找到这些目录后,用find配合参数清理:
find /tmp -type f -atime +3 -delete find /var/spool/clientmqueue -type f -delete5.4 执行脚本提示/bin/bash^M: bad interpreter
这是因为脚本从Windows传过来,每行结尾带了一个回车符\r。用sed或dos2unix清理:
sed -i 's/\r$//' script.sh dos2unix script.sh这行命令在Windows与Linux之间来回传文件后特别实用,我自己处理这类问题没有一百次也有八十次了。
5.5 端口被占用,却找不到进程
用ss -lntp明明看到端口被监听,但在ps aux里却找不到对应进程,或者ss -lntp因为权限问题不显示进程名。这种情况先加sudo重试:
sudo ss -lntp | grep 8080有了完整权限后,-p参数就能显示PID和进程名了。如果还是看不到,用lsof -i:8080:
lsof -i:8080lsof输出会直接列出占用端口的PID和进程名,是排查端口占用误杀时的利器。
5.6 遗忘root密码
物理机或虚拟机里忘记了root密码,可以在进入GRUB引导菜单时选择内核,按e进入编辑模式,在linux16或linux行尾加上:
rd.break然后按Ctrl-x启动进入紧急模式。之后依次执行:
mount -o remount,rw /sysroot chroot /sysroot passwd root touch /.autorelabel exit reboot云服务器上一般有“重置密码”功能,比这个方式简单很多。但如果你管的是自己搭的虚拟机,这套步骤最好在测试环境先演练一遍,真到紧急时刻才不会慌。
6. 让命令操作事半功倍的几个习惯
这部分算是我个人长期实践下来觉得最有价值的内容,不是什么高深的技巧,但能实实在在地提升效率、降低出错率。
6.1 Tab键补全与历史命令
Linux终端里的Tab键是你最亲密的朋友。输入命令或路径前缀时,按一下Tab可以自动补全;如果有多个匹配项,连按两下Tab会列出所有可能。我见过太多新手还在一个字符一个字符地敲路径,其实Tab键生成的效率完全不在一个量级。
上下方向键可以浏览历史命令,history可以列出所有历史记录。想再次执行某条历史命令时,!100表示执行编号为100的命令,!!表示执行上一条命令。大部分时候我不太用这些高级历史操作,但有一个组合非常实用。比如先执行了
docker stop container_a想对另一个容器做同样操作,你只需要:
!!:s/container_a/container_b/这个写法等价于把上一条命令中的字符串替换后重新执行。不过说实话,这种操作偶尔用一下可以,真在写循环批量处理时,大家更常用的是在命令后面加Tab补全补出容器名再改。
6.2 用好软链接管理多版本环境
场景是这样的:服务器上可能同时存在多个Python版本,系统自带的Python 2.7,后来装了Python 3.6,再后来又编译安装了Python 3.9。如果每次都去找各自的完整路径太痛苦。
Linux的软链接可以解决这个问题。把当前要用的版本指向一个固定的路径:
ln -s /usr/local/python3.9/bin/python3 /usr/bin/python3这样系统里的python3命令就统一指向Python 3.9了。升级或者切换版本时,只需要改一下链接指向的目标,不需要改动任何调用方的代码。
但要注意,ln -s的第一个参数是目标文件(源),第二个参数是链接名(自己创建的快捷方式路径)。搞反了会生成一个指向错误方向的链接,也是个新手常见错误。
6.3 定期检查安全与优化建议
这里分享两个打开思路的命令。第一个是审计登录历史,排查服务器是否被人动过:
last这个命令会列出所有用户的登录记录和重启记录,配合cat /var/log/secure(CentOS)或grep "Failed password" /var/log/auth.log(Ubuntu)可以看到暴力破解的尝试次数。如果发现大量陌生IP尝试登录,那这台机器很可能已经被扫了,得赶紧改密码并考虑禁用密码登录、改用密钥认证。
第二个是查看当前所有登录用户:
who同时也可以使用w命令,它除了显示当前登录用户,还会显示每个用户在做什么。这两条命令对判断多用户环境下的系统使用情况很有帮助。
7. 经验沉淀与后续延伸
聊到这儿,基础命令的主干内容算是梳理完了,最后我想分享几个更偏“操作系统层面”的感悟和后续学习的延伸方向。
一个是我自己带新人时反复强调的观点:学习Linux命令,一定不要开一堆终端窗口在图形界面里点来点去,那样你永远记不住命令。把自己扔进纯黑框的终端里,逼自己用键盘完成任务,遇到不会的命令就查man、查--help,坚持两个星期,进步会非常明显。真正遇到故障时,图形界面根本没机会弹出来,你能依赖的只有键盘和大脑里积累的命令。
另一个是“会用命令”和“理解系统”之间的距离。命令只是外壳,想排查深层问题,最终需要理解内核的基本概念,比如进程调度、文件系统、虚拟内存、系统调用。free命令输出让你看到内存数据,但为什么Linux会吃掉大量内存做缓存,为什么这些缓存能被回收?理解Page Cache机制之后,你再看到free的输出就不会误判了。类似的,理解了文件描述符的限制,你才能明白为什么并发连接一高,服务会报“too many open files”。命令能帮你看到现象,原理才能帮你理解本质。所以建议在练习命令的同时,配合读一读《鸟哥的Linux私房菜》和《现代操作系统》这类书。
扩展方向值得关注的有Shell脚本编程。当你会用命令解决单个问题后,下一步就是把多个命令写成自动化脚本,用for循环批量处理文件、用if判断条件、用cron定时执行。到了这一步,你就不再是“只会敲命令的操作员”,而是具备自动化能力的初级运维或DevOps工程师了。一个典型的例子,把每天的磁盘检查、日志清理写成脚本并加入crontab,服务器维护就会轻松非常多。
再往后,可以尝试学习容器化。理解了Linux基础命令和权限体系之后,理解Docker容器就容易很多,容器本质就是使用了Linux内核的namespace和cgroup特性,配合镜像文件系统实现隔离与分发,底层并没有魔法,而是对Linux能力的工程化封装。回过头来看,我们会发现所有高级的技术栈,上层无论怎么包装,根基都离不开对这个操作系统最朴素的认知。
在真实环境中用命令解决问题、踩坑、总结,再回到命令本身加深理解,这个循环走几遍,Linux的水准自然就上来了。希望这篇内容能帮你少走一些弯路。