刚开始搞Linux实验的时候,我犯过一个特别蠢的错:跟着教程敲了半天的命令,最后发现自己连“当前在哪个目录”“这些文件到底属于谁”都没搞清楚,更别提理解每一条命令背后的含义了。后来我把这套系统环境搭建和基本命令实验完整做了一遍,把所有关键操作、参数选择和踩过的坑都记录了下来,才有了这份更像是“实验手记”的报告。它适合三类人:一是正在准备Linux期末实验的学生,二是刚转行运维想快速上手命令行的新人,三是平时习惯了图形界面、想彻底搞清楚终端里那些命令到底在做什么的开发者。整篇文章基于VirtualBox + CentOS Stream 9环境,但同样的操作放到Ubuntu、Rocky Linux上也都成立,我会在关键位置标注出发行版之间的差异。
1. 实验环境准备与系统安装
1.1 为什么我选择虚拟机方案
做Linux实验,第一件事就是决定环境跑在哪里。市面上常见的方案大致有三种:物理机直接安装、云服务器、虚拟机。我自己最后选了虚拟机,理由很实际:物理机安装意味着要放弃原有系统或者搞双引导,一旦分区错误或者引导程序出现问题,修复成本很高;云服务器每个月要花钱,而且很多实验涉及网络配置和系统级修改,操作失误可能导致远程连接彻底断开。虚拟机方案则完美规避了这两个问题,快照功能可以在出问题时一键还原,性能和真实物理机差距也微乎其微。
虚拟机软件的选择上,我用的是VirtualBox。虽然VMware Workstation在功能上更全面,但VirtualBox是开源免费的,对个人学习和教学场景来说没有任何授权风险。如果你的宿主机是Windows,直接去官网下载VirtualBox安装包即可;如果是macOS,注意选择对应芯片架构的版本。实在搞不定虚拟机,也可以用WSL2做基础的命令练习,但WSL毕竟不是一个完整的Linux内核环境,涉及systemd服务管理、网络抓包这类实验时会遇到不少限制。
1.2 虚拟机配置参数与镜像准备
创建虚拟机时,配置参数的设定直接关系到后续实验的流畅度。我的建议配置如下,这个参数组合跑完整的命令实验、装Nginx和Docker都没有压力。
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| 内存 | 4096 MB(4 GB) | 低于2 GB会导致编译类操作卡顿 |
| 处理器 | 2核 | 实验类负载足够 |
| 磁盘 | 40 GB(动态分配) | 给系统分区和软件安装留足空间 |
| 网络 | NAT + Host-Only | NAT用于上网,Host-Only用于宿主机通信 |
镜像选择方面,CentOS Stream 9、Rocky Linux 9、Ubuntu 22.04 LTS这三者任选其一即可。如果你是跟着我这篇文档做,建议直接用CentOS Stream 9,因为后面涉及的dnf包管理器、firewalld防火墙等命令都基于Red Hat系;如果身边朋友都用Ubuntu,那么用Ubuntu也完全没有问题,只是在安装软件包时把dnf换成apt就好。下载镜像时有一点要特别注意:看清楚CPU架构,x86_64还是aarch64,在Apple Silicon的Mac上跑虚拟机一定要下载ARM版本的镜像,否则安装过程中会直接报错。国内用户下载镜像可以走清华、阿里云的镜像站,速度快很多,这是我自己实测过的。
1.3 安装过程中的关键选项
系统安装过程中有几个选项,看起来不起眼,却会在后续使用中反复影响你。
分区方案建议选择“自定义分区”,而不是“自动分区”。自动分区虽然省事,但生成的方案往往把所有空间都给了根分区,等你想单独挂载一块数据盘的时候就会很被动。我这次实验用的分区方案如下:
| 挂载点 | 大小 | 文件系统 |
|---|---|---|
| /boot | 1 GB | xfs |
| swap | 4 GB | swap |
| / | 剩余全部 | xfs |
这里解释一下为什么这样分:/boot独立出来是为了方便内核升级和引导修复,1 GB完全够用;swap设为4 GB,是为了防止内存不足时程序直接OOM崩溃;/占剩余全部空间,是因为我们的实验环境不涉及多用户数据隔离,没必要单独分/home。软件选择上,带图形界面的GNOME桌面在普通场景下更友好,但我建议安装时选择“最小安装”,后面需要什么自己装什么。虽然命令行界面一开始会让人不习惯,但只有进入命令行,你才能真正开始理解Linux的核心操作逻辑。
最后一步设置root密码和创建普通用户时,记得勾选“允许该用户通过SSH登录”之类的选项,方便后面用终端工具远程连接。安装完成后重启,第一件事就是在终端里执行系统更新:
bash复制sudo dnf update -y
别跳过这一步。刚装完的系统带着一堆旧版本软件包,直接开始实验可能会遇到一些早已修复的Bug。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统环境核心认知
2.1 内核、Shell与命令的关系
很多人学Linux命令就是死记硬背,这导致换个环境就不会用了。想真正搞明白命令的作用,需要先搞清楚Linux系统运行的三层结构。把Linux比作一家餐厅:内核是后厨,真正干活的地方;Shell是前厅服务员,负责把你点的菜传达给后厨,再把做好的菜端给你;命令就是你对服务员说的话。当你敲下ls -l /home并按下回车,完整的过程是这样的:Shell(默认是bash)读取你的输入,解析出命令名ls和参数-l /home,然后去PATH环境变量指定的目录里找到ls这个程序并执行,ls通过系统调用请求内核读取/home目录的内容,内核把结果返回给ls,ls格式化后打印到终端上。
理解这层关系后,你就能解释很多以前困惑的现象:为什么系统自带命令可以直接执行,而你下载的软件却需要./前缀?因为系统自带的命令(比如ls、cat)都放在/usr/bin、/bin这些已经被PATH变量包含的目录里,而你自己下载的程序通常放在/opt或当前目录下,不在PATH范围内,所以需要明确指定路径。
Shell有很多种,bash、zsh、sh、fish等等。大多数Linux发行版默认的交互式Shell是bash。不同的Shell在语法上有些微差别,但日常使用层面基本互通。你可以通过echo $SHELL查看当前登录用户的Shell类型。
2.2 文件系统目录结构:目录到底用来做什么
Linux的目录结构和Windows有着完全不同的逻辑。Windows先有盘符C盘、D盘,然后才在盘符下面建立文件夹;Linux则是一棵倒挂的树,根是/,所有文件和设备都挂在这棵树下面,没有盘符的概念。U盘插入后,它会出现在/media或/run/media目录下,而不是变成E盘。
这里整理一份FHS标准目录速查表,建议初学者打印出来贴在工位上,比任何时候都管用:
| 目录 | 用途 | 必记级别 |
|---|---|---|
| / | 根目录,所有目录的起点 | 必记 |
| /root | root用户的家目录 | 必记 |
| /home | 普通用户家目录的父目录 | 必记 |
| /etc | 系统和服务器的配置文件所在目录 | 必记 |
| /var | 日志、缓存、邮件等经常变化的文件 | 必记 |
| /usr | 系统软件安装目录 | 了解 |
| /tmp | 临时文件目录,重启后自动清理 | 了解 |
| /bin、/sbin | 系统基本命令和系统管理命令 | 了解 |
| /dev | 设备文件,比如硬盘、终端 | 了解 |
| /proc | 虚拟文件系统,反映内核和进程的实时状态 | 了解 |
路径的概念同样重要。绝对路径永远从根/开始,比如/home/user/test.txt;相对路径则是相对于当前目录的位置。.代表当前目录,..代表上一级目录,~代表当前用户的家目录。我经常见到新人在实验报告里写“执行cd ..两次返回根目录”,但这里有个很容易忽略的点:刚登录时的当前目录是/home/用户名,执行一次cd ..进入/home,执行两次才到/。如果不清楚自己在哪,随时用pwd查看当前绝对路径,这个习惯建议从一开始就养成。
2.3 环境变量:让Shell记住你的偏好
环境变量是Shell里一处很容易被忽视但极其重要的区域。最核心的环境变量是PATH,它决定了当你敲一个命令时,系统去哪些目录找可执行文件。查看当前PATH:
bash复制echo $PATH
在我的CentOS系统上输出大概是这样的:
code复制/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/user/.local/bin:/home/user/bin
如果我想让某个目录下的可执行文件也能直接被命令名调用,可以把目录加到PATH里:
bash复制export PATH=$PATH:/opt/mybin
但注意,这样写只在当前终端会话内生效。想要永久生效,需要把这一行写入配置文件。写入/etc/profile会对所有用户生效,但需要root权限;写入~/.bashrc只对当前用户生效,不需要特殊权限,日常使用中推荐后者。修改完配置文件后,执行source ~/.bashrc让配置立即生效,不用重启系统。
3. 基本命令实操详解
3.1 文件与目录操作:从ls到rm的正确姿势
文件操作是Linux命令中使用频率最高的部分。先从最基础的ls讲起。ls的常用组合:
bash复制ls # 列出当前目录文件
ls -l # 以长格式显示详细信息
ls -a # 显示所有文件,包括以.开头的隐藏文件
ls -lh # 以人类可读的方式显示文件大小
ls -lt # 按修改时间降序排列
ls -l的输出值得花点时间彻底看懂,它就是理解Linux权限体系的钥匙。我拿一条真实输出来说明:
code复制-rw-r--r-- 1 user group 1024 Jun 8 10:30 test.txt
第一个字符-表示这是一个普通文件(d是目录,l是软链接,c是字符设备,b是块设备);后面9个字符分成三组,分别代表“属主权限”“属组权限”“其他人权限”,每组三位rwx分别是读、写、执行;1是硬链接数;user是属主;group是属组;1024是文件大小;Jun 8 10:30是最后修改时间;最后是文件名。
新建目录和文件、复制、移动、删除,这一组命令没什么难点,但要小心几个参数差异。mkdir -p可以递归创建多级目录,比如一次性建立mkdir -p /tmp/a/b/c,不加-p会报错。cp -r递归复制目录,cp -p保留文件属性,这两个参数在实际部署服务时很常用。mv既可以移动文件也可以重命名,这是因为它本质上是“把文件从一个路径挪到另一个路径”。
删除操作要特别说,因为这个坑我栽过,相信很多人都栽过。删除空目录用rmdir,删除非空目录用rm -r。如果想省事直接rm -rf,我建议在实验阶段强制自己养成一个习惯:先ls确认自己正在操作的是哪个目录,再执行删除。尤其是rm -rf /这种命令,一旦执行且你是root用户,系统会从头删到尾,没有任何确认提示。我见过有人写实验报告时把rm -rf /home/user/test.txt里的路径写错,结果把整个/home目录清空了。如果你想用安全一点的方式,可以考虑安装trash-cli工具,它删除文件时只是放进回收站,还能反悔。
文件查找也是一个高频需求。find命令功能极其强大,这里给出几个最核心的用法:
bash复制find /etc -name "*.conf" # 按文件名查找,支持通配符
find / -type f -size +100M # 查找大于100MB的文件
find /home -user user1 # 查找属主是user1的文件
find /tmp -mtime -3 # 查找3天内修改过的文件
find /tmp -name "*.log" -exec rm {} \; # 查找并删除
这里提一句,find结合-exec可以实现“查找后自动处理”,花点时间研究这个参数,比手动一个个删除高效得多。另外通配符*、?、[]在文件操作中同样非常有用,比如rm *.tmp删除所有.tmp文件,但使用时也要保持同样的警惕心,先确认匹配范围再执行。
3.2 用户与权限管理:新建用户不只是useradd一条命令
用户管理几乎是我见过面试题中出现频率最高的话题,它非常能反映一个人对Linux的理解深度。实验里面最基础的需求就是“新建用户”,我在热词里也看到了这个问题,这里把它写透。
新建用户的标准命令是useradd,但它有几个特别重要的参数:
bash复制sudo useradd -m -s /bin/bash -G wheel alice
-m:自动创建家目录/home/alice-s /bin/bash:指定默认Shell为bash-G wheel:把用户加入wheel组,wheel组在CentOS/RHEL系统中默认拥有sudo权限
创建完成后,必须给用户设置密码才能登录:
bash复制sudo passwd alice
修改用户属性和删除用户的命令也要记住:
bash复制sudo usermod -aG docker alice # 将alice加入docker组
sudo usermod -L alice # 锁定用户,禁止登录
sudo userdel -r alice # 删除用户并删除其家目录
权限部分,重点掌握chmod的两种模式:符号模式和数字模式。我在实验里更推荐数字模式,因为可读性强且不容易出错。数字权限的算法很简单:r=4,w=2,x=1,把三类权限的数值相加。比如chmod 755 file,拆开看就是:属主7(4+2+1,读写执行)、属组5(4+1,读和执行)、其他人5(4+1)。最常见的几个权限位组合如下:
| 数字 | 权限 | 典型用途 |
|---|---|---|
| 755 | rwxr-xr-x | 可执行文件、脚本 |
| 644 | rw-r--r-- | 普通文本文件 |
| 700 | rwx------ | 私密文件或目录 |
| 600 | rw------- | 密钥文件、密码文件 |
chown用于修改文件属主和属组,比如sudo chown alice:developers report.txt就是把report.txt的属主改成alice、属组改成developers。
关于权限还有一个容易忽略的umask概念。umask决定了新建文件默认的权限掩码。系统默认的umask通常是022,它表示新建文件的权限是666 - 022 = 644,新建目录是777 - 022 = 755。理解了这个逻辑,你就能解释为什么自己创建的文件别人默认只有读权限,而不是纠结“为什么我的文件默认不是777”。
3.3 进程、服务和系统状态查看
当我们完成了文件和用户相关实验后,接下来需要掌握观察系统状态的方法。我在实验报告里把它们单独列为一组,因为“查看”是“操作”的前提。
系统总体信息用uname -a查看内核版本和系统架构,用uptime看系统运行了多久和负载情况。内存和磁盘是日常排障的第一站:
bash复制free -h # 以人类可读格式查看内存使用
df -h # 查看文件系统磁盘占用
du -sh /var # 查看目录总大小
进程管理是系统管理的重头戏。ps -ef和ps aux都常用来查看进程列表,两者显示的信息差别不大,ps aux的CPU和内存占用率的展示更直观。动态监视进程用top,进入top界面后,按P按CPU排序,按M按内存排序,按q退出——这几个交互键是新手最容易卡住的地方。如果你想要更直观的交互界面,可以安装htop,但实验考试里一般还是靠top。
终止进程用kill。kill -9 PID是强制杀死进程,kill -15 PID是温和地请求进程退出。这里必须强调一下:kill -9是最终手段,不是首选。很多程序(比如数据库)被kill -9后可能留下损坏的临时文件,正常操作应优先使用kill -15,等几秒再升级到-9。
实验做到这一步,我强烈建议你在系统里亲手装一个Nginx,作为“服务管理”的实操案例。CentOS上直接:
bash复制sudo dnf install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
systemctl是现在所有主流Linux发行版统一的服务管理工具。start启动服务,enable设置开机自启,status查看状态。理解这几个命令,比背十个冷门命令都更有价值。如果你想在实验里加练,还可以再装一个Docker:
bash复制sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
装完之后跑一个docker run hello-world验证环境,整个实验的“系统环境”部分就闭环了。
3.4 网络命令与远程文件传输
网络命令在实验报告里属于进阶部分,但也是最能体现“环境可用性”的部分。查看IP地址,新版系统推荐用ip addr而不是老旧的ifconfig;ifconfig在最小安装下默认不存在,需要额外安装net-tools。两者功能差别不大,但ip命令更强大,比如查看路由表要用ip route。
连通性测试用ping,它基于ICMP协议。注意,有些云环境或防火墙配置会屏蔽ICMP,ping不通不代表网络不通,还要结合后续的端口测试综合判断。端口监听状态用ss命令查看,这是替代netstat的现代工具,ss -tlnp可以列出所有TCP监听端口及其对应的进程PID。有同学问过“linux的9090端口什么再用”这类问题,解决办法很简单:
bash复制ss -tlnp | grep 9090
输出会告诉你哪个进程在监听9090端口,以及它的进程号,直接kill对应PID或者修改该服务配置里的端口即可。
远程文件传输是运维工作中使用频率最高的技能之一,scp命令基于SSH协议,安全且简单。它的基本格式是:
bash复制# 把本地文件推送到远程服务器
scp /home/user/test.txt root@192.168.1.100:/root/
# 把远程文件拉取到本地
scp root@192.168.1.100:/root/test.txt /home/user/
# 递归复制整个目录
scp -r /home/user/data root@192.168.1.100:/root/
# 指定端口(SSH不是默认22端口时)
scp -P 2222 /home/user/test.txt root@192.168.1.100:/root/
这里有个特别容易踩的坑:scp的-P是大写,而ssh命令指定端口时用的是小写-p,两个命令参数刚好相反。做实验时我至少见过三个同学在这里卡住。另外提醒一句,scp复制的是文件内容,如果两个系统之间文件属主、权限不一致,复制过去后可能需要执行chown和chmod重新设置。
4. 常见问题与排查技巧实录
4.1 安装与启动阶段的典型故障
虚拟机安装Linux过程中,最常见的故障是安装界面卡住、花屏或者直接蓝屏(Windows宿主机的VirtualBox环境)。排查顺序建议:优先怀疑CPU虚拟化功能没有开启,重启电脑进入BIOS/UEFI设置,找到Intel VT-x或AMD-V选项并开启;其次检查虚拟机版本和镜像架构是否匹配,比如在一台AMD处理器的电脑上装ARM镜像就会出问题;最后考虑磁盘空间不足,VirtualBox动态分配磁盘时,如果宿主机的剩余空间小于设定的上限,安装过程后期必然报错。
启动阶段如果系统卡在GRUB引导界面,或者在文本界面滚了一堆日志就停住,多半是显卡驱动或内核参数问题。可以在GRUB启动项上按e进入编辑模式,在linux开头的行尾追加nomodeset参数,然后按Ctrl+x启动,这个方法能绕过大部分显卡驱动问题。
还有一个非常常见的现象:安装时明明设置了root密码,但登录时怎么输都不对。有相当大概率是键盘布局问题,安装过程中选择了默认的英文键盘,但你的密码里包含中文输入法状态下的符号,比如全角冒号、中文双引号,登录时输进去的字符和设置时根本不是一个字符。解决方法就是设置密码时只用英文键盘上的字母和数字,避免一切特殊符号。
4.2 权限问题和误操作的恢复经验
权限问题在实验中大概能占到报错数量的一半。最常见的是Permission denied,看到这个错误第一反应不应该是“加sudo”,而是先弄清楚当前用户是谁、目标文件属主是谁、目标文件的权限位是什么。执行id查看当前用户,执行ls -l查看文件属主和权限,有时候问题仅仅是当前用户不在目标文件的属组里,加入对应组即可解决,而不是一路sudo到底。
更危险的一类问题来自误操作。我见过有人在执行chown -R的时候,把整个/etc目录的属主全部改成了普通用户,导致系统几乎瘫痪。这种问题的恢复思路是:使用现场救援模式或Live CD启动系统,然后重新把所有系统目录的属主改回root。但实际操作非常痛苦,所以这里再次强调:涉及-R参数的chown、chmod命令,执行前一定要用ls -ld确认目标和作用范围,这比事后抢救靠谱一万倍。
误删文件也是高频事故。rm -rf /home/user/backup 和rm -rf /home/user/backup/看起来只差一个斜杠,但含义完全不同——后者如果路径写错,配合通配符可能会波及到意想不到的范围。日常操作可以给自己加一道保险:在~/.bashrc里给rm设置别名:
bash复制alias rm='rm -i'
顺手把mv也设置成alias mv='mv -i'。这样每次删除或移动前系统都会询问确认,虽然多一步操作,却能在关键时刻拦住手滑和脑抽。
4.3 发行版之间的命令差异速查
很多同学做完实验写报告时,喜欢把网上搜到的Ubuntu命令直接粘贴进CentOS环境,结果各种报错。这里整理了一份高频命令差异对照表,建议存一下:
| 操作场景 | CentOS/RHEL/Rocky | Ubuntu/Debian |
|---|---|---|
| 安装软件 | dnf install / yum install | apt install |
| 更新软件源 | dnf update | apt update && apt upgrade |
| 防火墙 | firewalld(firewall-cmd) | ufw |
| 网络配置 | nmcli / /etc/sysconfig/network-scripts | netplan / /etc/network/interfaces |
| 默认文本编辑器 | vi(vim需要安装) | nano(好用但面试不常用) |
| 用户组管理 | wheel组有sudo权限 | sudo组有sudo权限 |
最主要的区别集中在包管理器和防火墙上。比如打开80端口,CentOS上执行sudo firewall-cmd --add-port=80/tcp --permanent && sudo firewall-cmd --reload,而Ubuntu上执行sudo ufw allow 80/tcp。两条命令功能相同,形式却完全不同。如果你在校验Nginx能否访问时发现网站在本机能打开但外部访问不了,先别急着怀疑Nginx配置,检查防火墙放行规则才是第一优先级。
4.4 网络排查与端口占用处理流程
实验过程中最让人头疼的就是网络问题。这里分享一套我自己固定使用的排查流程,基本能覆盖80%的场景。假设你发现某个服务连不上,按这个顺序走:
- 先确认服务是否在跑:
systemctl status 服务名,没跑就启动它。 - 确认端口是否在监听:
ss -tlnp | grep 端口号,如果看不到输出,说明服务可能配置了错误的IP或端口。 - 本机测试连通性:
curl http://127.0.0.1:端口号,本机都访问不了就一定是服务本身的问题。 - 跨主机测试:从另一台机器
ping目标IP,通了再telnet 目标IP 端口号,测试端口是否可达。 - 检查防火墙:CentOS上
firewall-cmd --list-all,Ubuntu上ufw status。 - 检查SELinux:CentOS上执行
getenforce,如果返回Enforcing,可以临时用setenforce 0关闭再测试,如果关闭后服务恢复正常,就需要为服务配置正确的SELinux策略或端口标签。
端口占用的问题,我做一个实验的时候就遇到过:装了Nginx之后默认端口80被占用,怎么都启动不起来。排查方法就是用ss -tlnp | grep :80找到占用进程的PID,再用ps -p PID -o comm=查看进程名。如果是Apache占用了,直接停掉Apache即可。需要说明的是,ss -tlnp中最后那个-p参数需要root权限才能显示进程名,普通用户执行会看不到PID,这是一个容易困惑的点。
4.5 让实验记录更有价值的几个习惯
这部分是我做完整套实验之后最想分享的内容,算是给后来者的一点建议。
首先是“留痕”的习惯。每执行一条命令,就把命令、输出结果、执行时间记录下来。我自己的做法是用一个experiment.md文件,按日期记录每次操作的命令和现象。这套习惯在写实验报告时帮了大忙——由于平时记录了完整的执行过程和输出,最后整理成文几乎不需要回忆,直接对照记录稍加润色即可,而且所有关键输出都有据可查。
其次是“先想后动”的习惯。在执行有破坏性的命令(rm、chown -R、格式化、清空日志)之前,强迫自己先在纸上或者文档里写下这条命令的作用范围。写不出来的情况下不要执行,先去man或--help查清楚。看起来多花了时间,实际是在给自己买保险。
最后是“制造问题再解决问题”的训练方式。学Linux命令不能只按照教程按部就班地敲一遍,那样印象不深。我建议在实验后期主动制造几个故障场景:比如手动把/etc/passwd改坏再修复、把某个服务的端口改成和别的服务冲突、给Nginx配置文件写一个语法错误再观察报错。自己在可控范围内折腾一次,比被动看十篇排查文章都管用。
Linux命令的学习本质上是一个“肌肉记忆”的过程,敲得多了自然就熟了。但肌肉记忆的前提是理解原理,否则你只是在重复按键,而不是在操作系统。希望这份实验手记能帮你把系统环境、文件权限、用户管理和网络通信这些基础模块串成一条线,从而真正迈过Linux命令行这道门槛。
