写在前面
在前面的 Linux 系统编程系列中,我们已经从 UNIX 与 Linux 的发展背景,逐步进入 Linux 命令行的实际使用。
上一篇《Linux系统编程(三):从文件移动到文本查看|mv、cat、less、head、tail 与时间命令》中,我们学习了文件移动、文本内容查看、输入输出重定向、管道以及时间相关命令。
到目前为止,已经可以完成基本的文件与目录操作,但如果真正使用 Linux 管理项目、调试程序或者维护服务器,还需要继续解决几个问题:
项目文件越来越多,怎样快速找到需要的文件?
日志中出现错误,如何定位包含特定信息的内容?
怎样观察 Linux 正在运行的进程?
如何打包、压缩和传输项目文件?
Shell、操作系统内核和可执行程序究竟是什么关系?
为什么同一个文件,有些用户可以修改,有些用户却只能查看?
为什么某个文件本身不能写,却仍然可能被其他用户删除?
本篇继续学习 Linux 基础指令后半部分的内容,并将相关命令组织成几个相互联系的知识模块。
与之前一样,文章不只是记录命令格式,还会解释命令的作用、常用参数和适用场景。
本文所有演示均以Luminous学习环境为背景。示例终端提示符统一写作:
[Luminous@linux-lab ~]$这是为了统一博客中的演示风格。实际登录时,Linux 用户名以系统配置为准,不要求和示例保持相同大小写。
一、文件检索:find、which、whereis 与 grep
1.1 从文件名查找开始:find
在目录较少时,我们可以不断通过cd和ls查找文件。
但是随着项目增多,如果已经忘记某个源文件存放在哪个目录,手动逐层查找就不再方便。
find的作用,就是从指定目录开始,根据条件遍历目录树并查找文件。
基本语法:
find 起始路径 查找条件首先创建一组测试目录:
mkdir -p ~/linux_lab_04/{src,docs,logs} touch ~/linux_lab_04/src/main.c touch ~/linux_lab_04/src/test.c touch ~/linux_lab_04/docs/README.md cd ~/linux_lab_04现在目录结构为:
linux_lab_04/ ├── src/ │ ├── main.c │ └── test.c ├── docs/ │ └── README.md └── logs/如果希望查找所有.c文件,可以执行:
find . -name "*.c"输出:
./src/main.c ./src/test.c其中:
.:从当前目录开始查找;-name:按文件名进行匹配;"*.c":匹配以.c结尾的文件或目录名。
这里需要注意,通配符应该使用引号包裹,防止 Shell 提前展开。
如果希望只查找普通文件,可以进一步添加-type f:
find . -type f -name "*.c"而:
find . -type d则表示查找目录。
如果文件名称存在大小写差异,还可以使用:
find . -iname "*.md"-iname不区分大小写,能够匹配.md、.MD等形式。
实现思想:find并不是凭空知道文件的位置,而是从指定起点遍历目录项,根据条件判断哪些对象符合要求。
这也与前面数据结构中学习过的树结构遍历形成了联系。
不过需要注意,find在遍历大型文件系统时可能需要访问大量目录和文件元数据,因此搜索范围越大,执行成本通常也越高。
1.2 which:查找外部命令的位置
上一篇已经介绍过PATH环境变量,Shell 可以利用它搜索外部可执行程序。
例如:
which gcc可能输出:
/usr/bin/gcc如果我们想进一步了解 Shell 如何解释某个命令,推荐使用:
type gcc type cd type -a ls这里需要区分:
which:主要用于定位外部命令;type:可以判断命令是别名、Shell 内建命令,还是外部程序。
特别是cd、alias等命令,不能简单地将它们理解为磁盘上某个普通的独立可执行文件。
1.3 whereis:查找程序及其相关文件
whereis主要用于定位程序的二进制文件、源码文件和手册文件。
例如:
whereis gcc可能返回:
gcc: /usr/bin/gcc /usr/share/man/man1/gcc.1.gz具体结果取决于系统实际安装的软件和文档。
因此,可以将几种查找方式进行区分:
| 命令 | 主要查找对象 |
|---|---|
find | 目录树中的文件和目录 |
which | 可通过命令搜索环境找到的外部程序 |
whereis | 程序、源码及手册相关文件 |
type | Shell 对命令名称的解释方式 |
这些工具各有用途,不需要相互替代。
1.4 grep:在文件内容中查找字符串
前面介绍的find解决的是文件在哪里的问题。
如果文件已经找到,但我们不知道需要的内容位于哪一行,就可以使用grep。
先创建一份简单的日志:
cat > logs/app.log <<'EOF' INFO: Luminous started the application INFO: Database connection established WARNING: Response time is increasing ERROR: Failed to load configuration INFO: Application stopped EOF这段命令使用了 Shell 的 Here Document,将多行文本写入app.log,作为后续搜索实验的数据。
现在查找包含ERROR的行:
grep "ERROR" logs/app.log输出:
ERROR: Failed to load configuration如果需要显示行号:
grep -n "ERROR" logs/app.log输出:
4:ERROR: Failed to load configuration其中4是行号。
如果不知道文本采用了大写还是小写,可以添加-i:
grep -in "error" logs/app.log如果希望查找不包含INFO的行,可以使用:
grep -v "INFO" logs/app.log常用参数可以总结如下:
| 参数 | 作用 |
|---|---|
-i | 忽略大小写 |
-n | 显示行号 |
-v | 反向筛选不匹配的行 |
-r | 递归搜索目录中的文件 |
实际开发时,我们经常需要在一个项目中查找某个函数名或变量名。
例如:
grep -rn "main" ./src表示递归搜索src目录中包含main的文本行,并显示匹配位置。
如果希望限制为 C 语言源文件,可以使用 GNU grep 的--include选项:
grep -rn --include="*.c" "main" .这比手动打开每个文件进行搜索方便得多。
1.5 find 与 grep 的组合
当文件数量进一步增加时,可以将两个命令结合起来。
例如:
find . -type f -name "*.c" -exec grep -nH "main" {} +可以分为两个阶段理解:
第一阶段,find找到符合条件的.c文件。
第二阶段,-exec将找到的文件交给grep搜索内容。
其中:
{}表示匹配到的文件路径;+表示尽可能将多个文件路径组合为命令参数;grep -nH会显示匹配行号和文件名。
这种思路体现了 Linux 命令行的特点:一个命令负责筛选文件,另一个命令负责处理文件内容。
二、top:观察 Linux 系统运行状态
2.1 为什么需要查看进程?
前面的命令主要围绕文件展开。
但是 Linux 不仅要管理文件,还需要运行程序。
一个程序运行起来以后,通常会对应一个或多个进程。多个进程同时运行时,系统需要分配 CPU 时间、内存等资源。
当程序出现卡顿、CPU 占用异常或者内存使用过高时,就需要观察系统状态。
top是 Linux 中常用的实时进程监控命令。
直接执行:
top即可进入监控界面。
通常可以观察到:
系统运行时间;
平均负载;
CPU 使用情况;
内存与交换空间使用情况;
进程数量及状态;
各个进程的 CPU 和内存占用。
2.2 常用参数
例如:
top -d 2 -n 3其中:
-d 2:设置刷新间隔为约 2 秒;-n 3:刷新 3 次后退出。
如果不设置退出次数,可以通过q离开监控界面。
需要注意,top显示的是运行过程中的系统状态,并非固定结果。不同设备、不同时间的 CPU 与内存占用可能差别很大。
在这一阶段,我们先掌握它的基础用途即可。
以后学习进程、线程和操作系统调度时,再进一步研究 PID、进程状态、CPU 时间与系统负载等概念。
三、文件压缩与打包:zip、unzip 和 tar
3.1 为什么需要压缩和打包?
当一个项目包含大量文件时,逐个传输并不方便。
例如,一个 C 语言项目可能包含:
MyProject/ ├── main.c ├── Stack.c ├── Stack.h ├── Queue.c ├── Queue.h └── README.md如果需要进行备份、发送给其他人或者上传服务器,将整个项目打包为一个文件通常更方便。
但是,这里需要先区分两个概念:
打包(Archive):把多个文件和目录组织成一个归档文件。
压缩(Compression):利用压缩算法减少数据占用的存储空间。
二者并不是完全相同的操作。
例如,.tar通常表示归档文件,本身不一定经过压缩;而.tar.gz通常表示经过 gzip 压缩的 tar 归档文件。
3.2 zip:创建 ZIP 压缩包
zip可以将文件压缩为.zip格式。
先在实验目录中创建一份新的测试项目:
mkdir -p ~/linux_lab_04/MyProject/include touch ~/linux_lab_04/MyProject/main.c touch ~/linux_lab_04/MyProject/include/project.h cd ~/linux_lab_04将整个项目压缩:
zip -r MyProject.zip MyProject/这里的-r表示递归处理目录。
执行完成后,会生成:
MyProject.zip如果没有-r,仅指定目录进行压缩时,通常不会自动将目录中的全部文件递归加入。
3.3 unzip:解压 ZIP 文件
如果需要解压:
unzip MyProject.zip默认会将归档内的文件解压到当前目录,可能与原有文件发生名称冲突。
因此,实际使用时可以指定一个独立的目录:
unzip MyProject.zip -d restored/这样归档中的内容会解压到restored目录下。
为了查看 ZIP 包内的文件列表而不实际解压,也可以使用:
unzip -l MyProject.zip3.4 tar:Linux 中重要的打包工具
相比zip,tar在 Linux 软件源码发布、系统备份和项目打包中也非常常见。
常用参数如下:
| 参数 | 作用 |
|---|---|
-c | 创建归档文件 |
-x | 从归档中提取文件 |
-t | 查看归档内容 |
-v | 显示处理过程 |
-f | 指定归档文件名 |
-z | 使用 gzip 压缩或解压 |
-j | 使用 bzip2 压缩或解压 |
-C | 切换到指定目录后操作 |
-p | 解压时尝试保留归档内记录的权限 |
最常见的组合之一是:
tar -czvf MyProject.tar.gz MyProject/对应含义:
-c 创建归档 -z 使用 gzip -v 显示过程 -f 指定文件名这样就会生成一个.tar.gz文件。
3.5 不压缩,仅打包
如果只希望把文件组织到一个归档中,而不使用 gzip 压缩:
tar -cvf MyProject.tar MyProject/这会生成:
MyProject.tar可以理解为将多个文件放进一个容器,但没有额外使用 gzip 压缩算法。
3.6 查看归档内容
如果只想知道归档里有哪些文件,不必先解压:
tar -tzvf MyProject.tar.gz其中-t表示列出归档内容。
这是一个比较实用的习惯:解压未知来源的归档前,可以先查看里面包含哪些路径。
3.7 解压到指定目录
首先创建目标目录:
mkdir -p restored_tar然后执行:
tar -xzvf MyProject.tar.gz -C restored_tar/解压后的文件会位于:
restored_tar/ └── MyProject/ ├── main.c └── include/ └── project.h需要注意,-C后面指定的目标目录应当已经存在。
3.8 只解压归档中的某个文件
如果只需要归档中的main.c,不需要解压整个项目,可以执行:
tar -xzvf MyProject.tar.gz MyProject/main.c -C restored_tar/这里的文件路径必须与归档中记录的成员路径对应。
因此,可以先使用tar -tf查看归档内部路径,再决定提取哪个文件。
3.9 tar 的进一步使用
tar还支持一些比较实用的选项,例如:
tar --exclude="MyProject/build" \ -czvf MyProject_source.tar.gz MyProject/这表示创建项目归档时,排除MyProject/build路径。
对于 C/C++ 工程,这种方法可以避免把编译生成的中间文件和可执行文件全部打包进去。
另外,tar也可以通过-N等选项按时间条件筛选文件,但涉及备份时需要进一步考虑文件时间、文件系统与实际备份策略,不能直接把它当作完整的增量备份方案。
课件中还涉及权限保留和管道方式打包。这里先记住:
创建归档使用
-c;解压归档使用
-x;查看归档使用
-t;某些恢复场景中可以通过
-p保留归档权限,但应确认用户权限及安全需求。
3.10 关于压缩包安全
归档文件中保存的不只是普通数据,还包括路径、目录结构以及可能存在的符号链接等信息。
因此:
不要随意以 root 身份解压不可信的压缩包。
优先在独立目录中解压。
解压前先查看归档内容。
避免不必要地保留外部归档中的特殊权限或文件所有权。
这些习惯在后续管理服务器和部署项目时非常重要。
四、Linux 文件传输:rz、sz 与实际使用场景
除了本地打包,Linux 开发中还经常需要在 Windows 和 Linux 之间传输文件。
如果使用支持 ZMODEM 协议的远程终端,例如配置正确的 Xshell,可以考虑使用rz和sz。
这两个命令通常由lrzsz软件包提供。
在 Ubuntu 系统中,可以尝试:
sudo apt install lrzsz在 CentOS Stream 等系统中,则需要检查当前软件仓库是否提供:
sudo dnf install lrzsz安装成功后:
rz通常用于接收客户端发送的文件。
而:
sz MyProject.tar.gz则用于向支持对应协议的客户端发送指定文件。
需要注意,rz和sz不是所有 SSH 客户端都支持的通用文件传输方式,实际使用取决于终端客户端的协议支持。
以后如果使用不同终端或需要更加通用的方式,还可以进一步学习基于 SSH 的scp、sftp等文件传输工具。
五、系统信息与终端交互
5.1 bc:命令行计算器
Linux 中可以使用bc进行数学计算。
例如:
echo "10+20" | bc输出:
30需要计算带小数的结果时,可以设置精度:
echo "scale=4; 10/3" | bc输出:
3.3333其中:
scale=4:设置除法结果的小数位数;10/3:执行除法计算;| bc:把前一个命令的输出交给bc处理。
这里正好复用了上一篇学习的管道知识。
5.2 uname:查看内核和系统信息
查看内核版本:
uname -r查看更完整的系统信息:
uname -auname可以显示内核名称、主机名、内核版本、硬件架构等信息。
但是需要注意,uname -r显示的是内核版本信息,并不能直接完整说明 Ubuntu 或 CentOS 发行版的版本。
如果希望查看发行版信息,可以执行:
cat /etc/os-release部分系统还可以使用:
lsb_release -a但lsb_release不一定默认安装。
因此,以后排查环境问题时,建议同时区分操作系统内核版本和 Linux 发行版版本。
5.3 三个重要快捷键
Linux 终端有几个非常常见的快捷操作。
| 快捷键 | 作用 |
|---|---|
Tab | 命令或路径补全 |
Ctrl+C | 通常向前台进程组发送 SIGINT 信号 |
Ctrl+D | 在终端输入中发送 EOF 条件 |
例如,输入:
cd ~/linux_如果存在唯一匹配目录,可以按Tab自动补全。
当执行了一个长时间运行的命令,例如:
tail -f logs/app.log通常可以使用Ctrl+C请求中断。
需要注意,Ctrl+C并不意味着直接强制关闭所有进程;程序可以自行处理或者忽略 SIGINT 信号。
而Ctrl+D与输入结束有关。当交互式 Shell 在空命令行收到 EOF 时,通常会退出当前会话。
5.4 shutdown:关闭或重启系统
Linux 可以通过shutdown安排关机或重启。
例如:
sudo shutdown -h now表示立即执行关机流程。
sudo shutdown -r now表示立即重新启动。
也可以安排稍后重启:
sudo shutdown -r +10表示计划在约 10 分钟后重启。
如果系统支持取消已安排的关机任务,可以使用:
sudo shutdown -c这里仅介绍命令用法。学习时不要随意在正在使用的远程服务器上执行关机或重启命令。
六、Shell 与 Linux 内核到底是什么关系?
前面已经使用了很多 Linux 命令,但我们还需要进一步理解一个问题:
当用户在终端中输入一个命令时,计算机究竟怎样执行它?
6.1 Shell 是什么?
Linux 内核(Kernel)是操作系统中负责管理进程、内存、设备、文件系统等核心资源的部分。
用户通常不会直接操作内核内部结构,而是通过命令行工具、图形程序以及系统提供的接口完成操作。
Shell 就是常见的命令解释器之一。
例如 Bash,能够完成:
读取用户输入;
分析命令和参数;
处理变量与路径展开;
执行 Shell 内建命令;
启动外部可执行程序;
处理输入输出重定向与管道;
管理前台和后台任务。
6.2 一条命令的执行过程
例如:
ls -l可以把它的执行过程简化为:
用户输入 ls -l ↓ Shell 读取命令 ↓ 解析命令名称与参数 ↓ 搜索对应的可执行程序 ↓ 启动外部程序 ↓ 程序通过系统接口访问目录信息 ↓ 操作系统内核完成相应工作 ↓ 结果输出到终端这只是对常见外部命令执行过程的概括。
如果执行的是cd这样的 Shell 内建命令,Shell 就不需要像运行ls一样再启动一个独立的外部程序。
这也再次解释了为什么前面学习PATH、alias和 Shell 内建命令时,需要区分不同类型的命令。
6.3 Shell 与图形界面的关系
在 Windows 或 Linux 桌面环境中,用户通常通过图形界面完成文件管理等工作。
而在命令行环境中,用户通过 Shell 输入命令,由程序调用系统接口完成相应操作。
两者并非完全不同的操作系统机制,只是面向用户提供的交互方式不同。
例如:
图形界面可以通过鼠标复制文件;
命令行可以通过
cp复制文件。
这些操作最终都需要依赖操作系统提供的文件管理能力。
理解这一点后,我们就不会把 Shell 和 Linux 内核混为一谈。
七、Linux 用户与文件权限
7.1 root 与普通用户
Linux 是多用户操作系统,通常需要区分普通用户和超级用户。
例如:
whoami如果当前用户是 Luminous,输出可能为:
Luminous普通用户通常只拥有自己被授权的操作权限。
超级用户root则具有非常广泛的系统管理权限,但仍可能受到安全机制、命名空间或其他系统限制。
在传统 Shell 提示符中:
[Luminous@linux-lab ~]$通常表示普通用户。
而:
[root@linux-lab ~]#通常表示 root 用户。
但提示符本身可以自定义,因此不能只依靠$或#判断真实权限。
7.2 su:切换用户身份
su可以用于切换用户。
例如:
su -通常表示尝试切换到 root,并加载目标用户的登录环境。
如果目标用户有可用的登录环境,也可以使用:
su - Luminous这里的用户名称仅作为示例,实际系统必须存在对应用户。
su是否成功,取决于当前用户身份、认证方式及系统配置。
需要特别注意:切换身份后,原有命令可能获得不同权限,因此在进行文件修改、删除和系统配置操作前,应该确认当前用户身份。
7.3 Linux 文件访问者的三类身份
Linux 文件权限通常按照三种访问者身份划分:
u(User):文件所有者;g(Group):文件所属组对应的用户;o(Others):其他用户。
例如:
ls -l main.c可能输出:
-rw-r--r-- 1 Luminous Luminous 128 Oct 29 09:00 main.c其中:
第一个
Luminous:文件所有者;第二个
Luminous:文件所属组;-rw-r--r--:文件类型与权限信息。
这里只是示例输出,真实文件大小、时间、用户名和所属组以系统实际情况为准。
7.4 r、w、x 三种权限
Linux 中最常见的三种权限如下:
| 权限 | 数值 | 普通文件 | 目录 |
|---|---|---|---|
r | 4 | 允许读取文件内容 | 允许列出目录中的名称 |
w | 2 | 允许修改文件内容 | 与执行权限配合管理目录项 |
x | 1 | 允许将文件作为程序执行(仍需满足格式等条件) | 允许进入或搜索目录中的路径 |
这里有一个非常值得注意的地方:
目录的权限与普通文件的权限并不完全相同。
例如,目录有r权限,不代表用户一定能够进入目录。
目录的x权限主要控制路径搜索与访问。
对于创建、删除和重命名目录中的文件,通常同时需要目录的w和x权限。
7.5 权限如何表示?
例如:
-rwxr-xr--可以拆分为:
- | rwx | r-x | r-- u g o第一位表示文件类型,后面每三位为一组:
rwx:所有者拥有读、写、执行权限;r-x:同组用户拥有读、执行权限;r--:其他用户拥有读权限。
也可以使用八进制数表示权限。
例如:
rwx = 4 + 2 + 1 = 7 r-x = 4 + 0 + 1 = 5 r-- = 4 + 0 + 0 = 4所以:
rwxr-xr-- = 754这种表示方式后面使用chmod时非常方便。
八、chmod、chown、chgrp 与 umask
8.1 chmod:修改文件权限
chmod用于修改文件或目录的权限。
例如:
chmod u+x script.sh表示为文件所有者增加执行权限。
如果希望取消其他用户的写权限:
chmod o-w script.sh如果想通过数字直接设置权限:
chmod 644 main.c其中:
6 = rw- 4 = r-- 4 = r--所以最终权限为:
-rw-r--r--对于普通脚本,可以根据需要使用:
chmod 755 script.sh对应权限:
-rwxr-xr-x需要强调:不是所有文件都应该设置执行权限,更不能为了省事给所有文件使用777。
权限应该根据实际需求分配。
8.2 chown:修改文件所有者
chown用于修改文件所有者,也可以同时修改所属组。
例如:
sudo chown Luminous:Luminous main.c表示将main.c的所有者和所属组设置为示例中的Luminous。
实际执行时,用户名和组名必须存在于系统中。普通用户通常不能随意把文件所有权转交给其他用户,因此这类操作经常需要适当的管理权限。
8.3 chgrp:修改文件所属组
chgrp用于修改文件或目录所属组。
例如:
chgrp developers main.c表示尝试把main.c的所属组改为developers。
命令能否成功,取决于当前用户权限、目标用户组是否存在等条件。
对于普通用户,通常只能在系统允许的范围内修改文件所属组。
8.4 umask:为什么新建文件不一定是最大权限?
在 Linux 中,新建普通文件和目录通常有不同的权限基准。
常见情况是:
普通文件:666 目录:777但这不意味着新建文件最终一定具有这些权限。
创建文件时还会受到umask的影响。
查看当前掩码:
umask假设输出:
0022对于新建普通文件:
666 & ~022 = 644对于新建目录:
777 & ~022 = 755所以在这种情况下:
touch demo.txt mkdir demo_dir通常会得到:
demo.txt → 644 demo_dir → 755这里需要注意,权限计算本质上是按位屏蔽,而不是普通的十进制减法。
另外,实际结果也可能受到 ACL、文件系统及程序自身创建参数等因素影响。
学习阶段建议先掌握:
umask 决定创建文件时哪些权限位会被屏蔽。
不建议为了实验随意修改系统全局的umask配置。
九、目录权限与粘滞位:为什么能删除别人的文件?
9.1 一个容易忽略的问题
假设某个目录允许多个用户写入。
目录中有一个由 Luminous 创建的文件:
shared/ └── luminous.txt如果其他用户拥有这个目录的写入和搜索权限,那么即使这些用户没有文件本身的写权限,也可能删除该文件对应的目录项。
为什么?
因为删除文件本质上涉及对父目录中目录项的修改,并不仅仅取决于文件自身是否可以写入。
这说明:
文件内容修改权限与目录项删除权限,是两个不同层面的问题。
9.2 粘滞位 Sticky Bit
为了解决公共可写目录中用户相互删除文件的问题,Linux 提供了粘滞位机制。
例如:
chmod 1777 shared其中最高位的1表示设置粘滞位。
如果查看目录权限,可能看到:
drwxrwxrwt最后的t就是粘滞位的常见显示形式。
在设置了粘滞位的目录中,通常只有以下身份可以删除或重命名其中的文件:
文件所有者;
目录所有者;
具有相应特权的用户。
这也是/tmp等公共临时目录常用的权限设计方式。
需要注意,粘滞位不能代替完整的访问控制策略。实际是否允许操作,还受到目录权限、系统安全机制和其他限制的影响。
9.3 file:识别文件类型
除了通过文件后缀判断类型,还可以使用:
file main.c或者:
file MyProject.tar.gzfile会根据文件内容、元数据或特征识别文件类型。
这和单纯通过.c、.txt、.zip后缀判断不同,因为 Linux 文件名的后缀并不是确定文件类型的必要条件。
例如,一个没有.sh后缀的文件,也可能是 Shell 脚本。
9.4 sudo:以授权身份执行命令
Linux 中不应当为了完成某个管理操作,就长期保持 root 登录。
如果系统已经为当前用户配置了适当的 sudo 权限,可以通过:
sudo 命令在授权条件下执行需要更高权限的操作。
例如:
sudo -u root whoami如果授权通过,命令通常会输出:
root实际操作中,建议遵循最小权限原则,只在确实需要时使用 sudo。
如果需要配置 sudo 授权,通常应由管理员通过适当工具,例如visudo,安全地编辑 sudoers 配置,而不应直接随意修改/etc/sudoers的权限或内容。
十、完整实践:把本篇知识串起来
这一篇涉及的内容比较多,最后通过一组实验将其中的重要命令连接起来。
首先进入实验目录:
mkdir -p ~/linux_lab_04/{project,backup,logs} cd ~/linux_lab_04创建项目文件:
cat > project/main.c <<'EOF' #include <stdio.h> int main(void) { printf("Hello from Luminous!\n"); return 0; } EOF创建日志:
cat > logs/build.log <<'EOF' INFO: Starting compilation INFO: Checking source files WARNING: Unused variable detected ERROR: Missing header file INFO: Build finished EOF现在可以依次完成以下操作。
第一步:查找 C 源文件
find . -type f -name "*.c"第二步:搜索错误信息
grep -n "ERROR" logs/build.log第三步:打包项目
tar -czvf backup/project.tar.gz project/第四步:查看归档内容
tar -tzvf backup/project.tar.gz第五步:查看系统内核信息
uname -r第六步:查看文件权限
ls -l project/main.c第七步:调整源文件权限
chmod 644 project/main.c第八步:查看当前用户与权限掩码
whoami umask整个练习可以理解为:
创建项目文件 ↓ 查找文件 ↓ 搜索日志 ↓ 打包备份 ↓ 查看归档 ↓ 检查系统信息 ↓ 理解文件权限这比把每个命令孤立地背下来更容易形成完整印象。
需要说明的是,本次实验并不要求执行关机、切换 root、修改系统目录权限等高风险操作。这些命令的语法可以先理解,实际测试应当在可恢复的虚拟机或专用实验环境中进行。
十一、本篇知识点与命令总结
| 模块 | 主要命令 | 核心作用 |
|---|---|---|
| 文件查找 | find | 按条件遍历目录树 |
| 命令定位 | which、whereis、type | 定位程序及了解命令类型 |
| 文本检索 | grep | 搜索匹配的文本行 |
| 系统监控 | top | 观察进程与资源使用 |
| ZIP 压缩 | zip、unzip | 创建与解压 ZIP 文件 |
| 归档管理 | tar | 打包、查看与解包 |
| 远程传输 | rz、sz | 在受支持的终端中传输文件 |
| 命令行计算 | bc | 数学计算 |
| 系统信息 | uname | 查看内核与硬件相关信息 |
| 终端操作 | Tab、Ctrl+C、Ctrl+D | 补全、中断、输入结束 |
| 系统控制 | shutdown | 关机或重启 |
| 身份切换 | su、sudo | 切换用户或执行授权命令 |
| 权限修改 | chmod | 修改访问权限 |
| 所有权管理 | chown、chgrp | 修改所有者和所属组 |
| 权限掩码 | umask | 控制新建对象的默认权限 |
| 文件识别 | file | 判断文件实际类型 |
写在最后
回顾前面几篇 Linux 基础学习内容,可以发现我们正在逐步从“记住一个命令”过渡到“理解一个系统”。
第一篇主要认识 Linux 的历史和开源生态;第二篇建立目录树与命令执行的基础;第三篇学会文本查看、管道和重定向;这一篇则进一步扩展到了文件检索、压缩归档、系统信息和用户权限。
其中,文件权限这一部分尤其值得继续深入。
因为 Linux 的文件不只是保存数据的载体,还涉及:
文件属于谁;
哪些用户能够访问;
能否读取、修改或执行;
目录权限如何影响内部文件;
程序运行时具有什么权限。
这些知识与前面学习的 C 语言、文件指针、进程以及后续 Linux 系统编程存在直接联系。
例如,在 C 语言中执行文件操作时,除了程序自身逻辑正确,还必须满足操作系统的权限要求。
因此,理解 Linux 权限并不是单纯学习chmod的参数,而是在为后续文件 IO、进程、线程和系统调用打基础。
接下来,Linux 系列将逐步从基础命令转向实际开发环境的使用,继续学习 GCC、GDB、Makefile 等工具,并在后续深入文件 IO、进程和线程等系统编程内容。
学习的目标也不只是能够操作 Linux,而是逐渐理解程序如何在 Linux 环境中被编译、运行、管理和控制。
从能够使用命令,到理解命令背后的运行机制,是这套学习记录持续推进的方向。