很多朋友装了Ubuntu之后,最先接触的是干干净净的桌面和看起来很好用的软件中心,直到某一天需要在终端里敲命令装依赖、改配置、看日志,才发现网上教程里那一大串"在终端执行xxx"根本绕不过去。这篇文章我打算把Linux常用命令按"使用频率"和"实际场景"重新过一遍,不是说教式地列参数,而是讲清楚每个命令族的底层逻辑、最常踩的坑,以及我从服务器运维和日常开发里总结下来的使用习惯。适合刚从Windows过来、刚开始在虚拟机或双系统里碰Ubuntu的朋友,也适合那些零零散散学过一点命令但一直没串成体系的人。
1. 先想明白一件事:为什么Ubuntu最终绕不开命令行
1.1 服务器上没有图形界面,Linux的主战场本来就不在桌面
你可以在Ubuntu桌面版里用鼠标完成绝大多数日常操作,但等你需要部署一个网站、跑一个Python脚本、把一台云主机配置成服务时,面对的往往是一个只有黑屏终端的环境。哪怕你用虚拟机装了带桌面的Ubuntu,很多教程里给出的操作步骤依然是终端命令,原因很简单:命令是唯一的、可被复述的、和环境无关的描述方式。同一个操作,在Ubuntu 20.04和22.04的桌面菜单里可能位置不一样,但apt install这条命令在两个版本上的结果是一样的。
我见过太多人从Windows带过来的思维是"找设置按钮"、"翻菜单选项",这种思路在Linux上会碰壁。因为Linux的理念是"每个程序都是一个命令,每个命令都有明确的输入输出",所有的图形界面工具本质上是把命令包装成了按钮。你学会命令,等于直接在使用系统底层的语言,图形工具反而成了可选的辅助。
1.2 命令行真正的优势不是"酷",而是可重复、可脚本化
图形界面操作最大的问题是不可记录:你怎么点的、点了多少次、间隔多久,没人知道。但命令不一样,你输入了什么、输出是什么,都能复现、能检查、能放进脚本里自动执行。比如说你要在10台机器上批量创建用户,手点图形界面能让人崩溃,而写一个for循环调用useradd,几分钟搞定。
我从实际使用的角度给Linux命令做了个分层:文件操作、权限管理、软件安装、服务管理、文本处理、进程网络。这六块基本覆盖了日常工作90%的命令使用场景。下面每一章对应一个命令族,你在Ubuntu里遇到的大部分问题,最终都会归结到这几个方向之一。
2. 文件与目录操作:Ubuntu日常最硬核的肌肉记忆
2.1 定位与浏览:pwd、ls、cd,三个命令定生死
不管是在终端里手动操作还是写脚本,你首先得知道自己"站在哪里"。pwd(print working directory)就是干这个的,它打印当前工作目录的绝对路径。我刚用Linux时经常犯一个错:以为自己在某个目录,结果执行命令时报"no such file or directory",赶紧pwd一看,果然人在根目录。这不是小事,后面执行rm或覆盖操作时,搞错当前目录可能造成不可逆的损失。
ls的常用组合是ls -lah。拆开看:-l是长格式列表,显示权限、属主、大小、修改时间;-a是显示隐藏文件(Linux里以点开头的文件);-h是以人类可读的大小单位显示(KB、MB),不然你看到一串纯字节数还得心算。ls -l输出里的第一个字符表示文件类型,-是普通文件,d是目录,l是符号链接。这个细节在你排查"怎么这个文件删不掉"或"这到底是个软链还是真文件"时特别有用。
cd没什么好说的,但有几个技巧值得记住:cd -回到上一次所在目录,这个在日志目录和工作目录之间来回切换时非常高效;cd ~直接回当前用户的家目录;cd ..回到上一级。写命令时尽量不要用绝对路径走完全程,多在相对路径之间切换,这样一旦项目目录整体移动,你的命令习惯也不用大改。
2.2 复制、移动、删除:cp、mv、rm的安全边界
cp的常用形态是cp -r源目录 目标目录,-r表示递归复制,复制目录时必须加。日常我还习惯加一个参数组合cp -av:-a保留文件属性(权限、时间戳),-v是verbose,把复制的每个文件都列出来。如果你在复制一个很有可能是配置文件的目录,保留属性很重要,否则复制出来的文件权限变了,服务可能报错。
mv有两个功能:移动文件和重命名。这有点反直觉,但你要接受Linux的设计思路——重命名就是在同一目录下"移动"到新的名字。mv跨文件系统时,本质上是复制后删除,所以如果目标盘空间不够,mv哪怕只是挪个位置也可能失败。这一点在移动大文件(比如虚拟机镜像)时尤其要留意。
rm是新人最容易闯祸的命令。rm -rf的杀伤力我不用多形容,关键是理解为什么它会那么危险:-r递归删除目录及内容,-f强制,不询问确认。它不会像Windows那样先放进回收站,而是直接从文件系统层面抹掉。所以我个人的习惯是:在交互式终端里,能用rm -i就用,-i会在删除每个文件前询问;在脚本里,先用find或ls确认要删除的路径确实是自己想删的那个,再执行rm。还有一个实用技巧:写rm命令时不建议先敲完整命令再补路径,而是先确认路径,最后关头再补上rm,避免历史命令里失误。
2.3 通配符、路径约定与"隐藏文件"背后的逻辑
Linux里一切皆文件,这句话你可能听过,但实际操作中影响最深的是路径和通配符。*代表任意多个字符,?代表单个字符,[abc]表示字符集中的一个。比如rm *.log只会删除当前目录下.log结尾的文件,不会动.log.bak。这些通配符看着简单,但加上管道和循环后威力很大。
关于隐藏文件:Linux下文件名以.开头就是隐藏文件,系统配置大多放在家目录的隐藏目录里,比如~/.ssh、~/.config。很多新人在vi或nano里改了配置文件后找不到,多半是没开ls -a。这里有个经验:配置类的隐藏文件一般权限都很精细,不要看到个.bashrc就忍不住chmod 777,后面我会讲为什么。
3. 权限与用户管理:sudo、chmod、chown背后那一套
3.1 sudo到底在干什么,为什么不直接登录root
sudo的全称是superuser do,意思是"以超级用户的身份执行这条命令"。Ubuntu默认禁用了root账号直接登录,而是建议普通用户通过sudo临时提权。很多人觉得这很麻烦,其实这个设计是为了安全和审计:每一条sudo执行都会被记录在/var/log/auth.log里,出问题时能回溯是哪位用户、什么时间、执行了什么命令。
使用sudo时要理解它的粒度:sudo后面的命令以root身份运行,但它不会改变你的环境变量,也不会让整个shell变成root。你执行sudo cat /etc/shadow能读文件,但同一条shell里如果没有sudo你会被拒绝访问,这两者的区别经常让新人困惑。顺手提一句,长期用sudo当真和长期用root还是有区别的——sudo的超时时间默认是15分钟,过了要重新输密码,这本身就是一层约束。
3.2 chmod的数字法则:rwx为什么等于421
chmod是用来修改文件权限的命令,最重要的模型是"三组三格":属主(u)、属组(g)、其他人(o),每组都有读(r=4)、写(w=2)、执行(x=1)三种权限。数字模式下,把每组权限对应的数字相加,三位数字分别代表u、g、o。比如chmod 755表示属主有rwx(7=4+2+1),属组和他人有r-x(5=4+1)。
我的建议是记住一组默认安全组合:普通文件644,目录755。755的x是给目录的执行权限,这对目录来说其实是"进入目录"的权限,没有x你无法cd进去,这是新人最容易忽略的。你可能会遇到某个目录明明有r权限,却进不去,就是缺了x。需要重点提醒的是:不要随手chmod 777。我见过有人为了图省事把整个项目目录设成777,结果网站被植入恶意文件。正确的做法是给目录755,给需要写的特定文件或目录再单独放开写权限。
chown用来修改属主和属组,最常见的场景是把某个文件从root改成当前用户操作。例如我用sudo创建了一个文件在项目目录里,之后编辑它总被提示权限不足,这时sudo chown $(whoami) 文件名就能把属主改成当前用户。这里$(whoami)是命令替换,会把whoami的执行结果填到命令里,这个技巧在日常操作中经常用到。
3.3 用户和用户组:useradd、passwd、su的基本用法
Ubuntu里新增用户用sudo useradd -m 用户名,-m会自动创建家目录。很多教程喜欢用adduser(带交互向导),但脚本化操作时useradd更可控。创建后必须用sudo passwd 用户名设置密码,否则这个用户无法登录。
su用于切换身份,比如su - 用户名,注意这里的-表示同时加载目标用户的环境变量。很多人只在sudo和su之间纠结,其实日常场景里根本不常切换用户,更推荐用sudo执行单条命令,而不是整个会话切过去。我踩过的坑是:用su - root切过去后,误以为自己在原目录,实际整个环境都换了,依赖当前目录假设的命令全部失灵。
4. 软件安装与系统维护:apt、systemctl、日志三件套
4.1 apt系列:为什么先update再install是一个铁律
Ubuntu使用apt作为包管理器,底层基于dpkg。最核心的命令组合是:sudo apt update先刷新软件源索引,sudo apt install接包名安装。很多人上来apt install报错"unable to locate package",十有八九是因为没先update。原理是:本地有一个软件包索引列表,update会去软件源服务器同步最新可用版本和依赖信息,install根据这个索引去下载安装包,索引都没有自然找不到。
apt upgrade是升级所有可升级的包,注意它不会自动删除不需要的依赖,也不会处理需要"变更已安装包依赖关系"的情况。那些改动较大的升级,要用apt dist-upgrade或apt full-upgrade。Ubuntu 22.04之后apt还加了apt autoremove用来清理自动安装但不再需要的依赖。
这里分享一个我的习惯:apt install之前先apt search看准包名,别凭印象装。比如你要装的是nginx,但apt search nginx会列出十几个包里有个nginx-core之类的,装错包后配置文件路径完全不同,最后折腾半天还得purge重来。彻底卸载用sudo apt purge 包名,purge会连配置文件一起清掉,普通remove会保留配置文件。对新手来说,卸载不干净往往比装不上更让人困惑。
4.2 systemctl:让服务开机自启和查看状态的正规姿势
现代Ubuntu用systemd管理服务,systemctl就是操作它的工具。最常用的几个是:sudo systemctl start 服务名、stop、restart、status,以及enable(开机自启)和disable(取消自启)。注意restart和reload的区别:restart是干脆利落地重启整个进程,reload是让进程重新读取配置而不中断服务,生产环境里能用reload就别restart。
systemctl status输出里有一段非常有价值的启动日志,服务起不来时,这里通常会告诉你失败原因。另一个高频救命命令是journalctl -xe,-x把它和错误信息一起展开解释,-e直接跳到日志尾部。排查服务起不来时我习惯先journalctl -u 服务名 --no-pager -n 50,只看这个服务最近50行日志,快速定位是配置语法错误还是端口被占。
4.3 PATH环境变量:命令找不到时先检查这里
每个终端会话都有一个PATH变量,里面是一串用冒号分隔的目录,系统在PATH里依次查找可执行文件。当你输入命令提示command not found,不是命令不存在,而是它所在的目录不在PATH里。查看当前PATH用echo $PATH,临时往PATH里加目录用export PATH=$PATH:/新目录,把这个export写进~/.bashrc就能永久生效。
关于PATH最经典的坑是环境变量配置错误导致系统基础命令找不到。我调整PATH时一直遵循一个原则:修改前先备份~/.bashrc,然后在新终端会话里验证,不能用当前会话直接去测试生产环境。万一搞坏了,可以用绝对路径/bin/或/usr/bin/调用命令临时恢复,比如/bin/cp把备份文件复制回去。
5. 文本处理与日志实战:grep、awk、sed和管道组合拳
5.1 管道:把命令变成一条流水线
管道符|是Linux命令组合的精髓,它把左边命令的标准输出接到右边命令的标准输入。我常打一个比方:命令就工厂的单台机器,管道是传送带,把半成品从一台机器送到下一台。一个经典组合是history | grep apt,你可以快速翻出以前敲过的apt命令,这对找回长参数命令特别管用。
管道之所以强大,在于它把一个个只做单一职责的命令组合成复杂逻辑。比如你要找日志里出现error的100行,再统计出IP地址,用一系列管道命令就能完成,而无需写一个Python脚本。理解了管道,你对Linux命令的理解就上了一个台阶。
5.2 grep:过滤和定位,日志排查的起点
grep是最常用的文本过滤器,基础用法是grep "关键字" 文件名。但它真正的威力在参数组合上:-i忽略大小写,-n显示行号,-v反向匹配,-r递归搜索目录,-E使用扩展正则。排查日志时我离不开的命令是grep -n "error" app.log | head -20,只取前20行,避免输出太多刷屏。
还经常配合-C参数显示匹配行的上下文:grep -C 5 "Exception" app.log,把错误前后5行都拉出来,很多异常原因就在前面几行的调用链里。另外,grep默认是搜索文件内容,如果用grep找文件名的话要用-l参数:grep -rn "keyword" /etc/,递归列出匹配文件路径,这在改配置时快速定位"这个配置项在哪个文件里"非常高效。
5.3 awk和sed:从"看日志"到"统计日志"
awk默认按空格把每行拆成字段,$1是第一个字段,$NF是最后一个字段。最经典的使用场景是统计日志里状态码分布:cat access.log | awk '{print $9}' | sort | uniq -c | sort -rn。这条命令先把第九列(HTTP状态码)提取出来,排序后统计数量,再按数量倒序排列。我排查网站访问异常时,第一步几乎都是跑这条,几秒钟就能看出500是不是突然多了。
sed是行编辑器,最常配合管道做文本替换,sed 's/旧文本/新文本/g'会把每行里所有匹配的旧文本替换成新文本。我在批量修改配置文件时经常用:sed -i 's/localhost/192.168.1.10/g' config.yml。-i是直接修改文件,操作前必须确认替换规则正确,或者先不带-i跑一遍看输出。另一个实用参数是-n和p组合:sed -n '20,30p' 文件名,专门看文件的第20到30行,这在查看大配置文件里的某个区间时比vim翻页更快。
5.4 一个完整的日志排查小案例
我把上面这些串起来演示一遍。假设Nginx日志里频繁出现5xx,我要知道哪些接口最严重:grep '" 5[0-9][0-9]' access.log在双引号后匹配状态码,管道给awk '{print $7}'取第七列请求路径,再sort、uniq -c、sort -rn,前10行就是最需要关注的接口。
还有tail -f配合管道也很有用:tail -f access.log | grep "error"可以实时过滤出新出现的错误日志。我在联调时经常开两个终端,一个tail -f看服务日志,一个执行操作,两边对照,问题在哪一目了然。别小看这些"基础命令",生产环境下真正能救命的往往就是它们。
6. 网络与进程排查:Ubuntu"卡住/连不上"时的自救指南
6.1 进程管理:top、ps、kill的正确打开方式
系统卡了第一反应是看谁在耗资源。top可以实时显示CPU和内存占用,按P按CPU排序,按M按内存排序。不过top是交互式界面,脚本和远程排查时我更常用ps aux | head或者ps aux --sort=-%cpu | head -10,直接取前十名。
找到可疑进程后,kill 进程PID是发送SIGTERM,让进程自己处理退出前的清理工作;kill -9是SIGKILL,直接强制终止,进程没有机会保存数据或释放资源。我明确说一句:优先用普通kill,杀不掉再上kill -9。很多人一上来就-9,数据库、服务进程在写入半途被杀,可能导致数据损坏。配合pgrep按名字找进程:pkill -f python会杀掉命令行里包含python的进程,这个要谨慎使用,它会匹配很多你想不到的东西。
6.2 网络排查:ping、curl、ss三件套
ping是测基础连通性的,ping -c 4 IP表示发4个包后结束。ping通只能说明主机可达,不代表服务正常,这是很多人排查时的误区。接下来要测端口:ss -tlnp是查看本机监听端口和对应进程,-t显示TCP,-l显示监听,-n不解析服务名,-p显示进程信息。老命令netstat在新版Ubuntu里默认没有了,需要单独安装,而ss是系统自带,我没有在这个问题上纠结过。
curl用来测HTTP服务,curl -I http://localhost可以只拿响应头,看HTTP状态码;curl -v可以看到完整请求和响应交互过程。我在本地起服务后习惯先curl -I http://127.0.0.1:8080,通了再让别的机器访问,这一下就能区分是服务本身问题还是网络策略问题。
6.3 端口被占用:一个高频实战排查
我遇到过很多次启动服务时提示"port already in use",这个问题的排查思路值得完整过一遍。第一步ss -tlnp | grep 端口号,找出占用端口的PID。第二步看看这个PID对应的进程是不是还活着、该不该让它继续占着:ps -p PID -o comm=显示进程名。第三步按情况处理:如果是残留的旧进程,kill掉再启动;如果是有意占用,就换个启动参数端口。
这里有一个比较隐蔽的坑:某些进程(比如node开发服务)被kill后,子进程还活着,依然占着端口,表面上看"进程没了但端口还被占用"。这时用fuser -k 端口号/tcp可以发送信号给占用该端口的进程组,强制释放,再用ss确认。这套流程我重复了不下几十次,从最初的手忙脚乱到后面的条件反射,现在只要看到端口报错,三秒钟就能定位到责任人。
关于网络排查还有一句话想补:内网排查讲命令,外网排查讲防火墙和安全组。在云服务器上,命令查不到原因的时候,考虑一下云平台的安全组规则是不是屏蔽了端口,这个在本地虚拟机里测不出来,属于经验盲区,踩过一次就有印象了。
最后再分享一个我个人的使用习惯:不要试图一次性记住所有命令和参数。命令这个东西用进废退,我至今查参数也是靠man和--help。真正重要的是把每个命令族的使用场景打通——看到"文件"想到ls、cp、mv;看到"权限"想到chmod、chown;看到"装软件"想到apt;看到"服务起不来"想到systemctl和journalctl;看到"日志分析"想到grep、awk、管道。场景和命令建立关联之后,具体参数随时可以查,但解决问题的思路是必须内化成肌肉记忆的。