Linux系统编程:(三)Shell命令及其运行原理+Linux权限机制
目录
一、Shell命令及其运行原理
1.1 理解Shell
在探讨 Shell 的具体工作机制之前,我们需要先厘清 Linux 系统的层级结构。严格意义上讲,Linux 指的是我们常说的操作系统“内核(Kernel)”。然而,普通用户是无法直接与这个内核进行交互的,因为内核运行在底层,它只负责最基础的硬件调度和资源管理。为了能够与内核沟通,我们需要借助一个中间层——也就是所谓的“外壳”程序,即 Shell。
那么,为什么用户不能直接操作 Kernel 呢?从本质上说,Kernel 是一段极其复杂且底层的代码,它直接面对的是 CPU、内存和磁盘等硬件。如果让用户直接发号施令,不仅需要极高的专业知识,而且极易导致系统崩溃。因此,Shell 应运而生,它在用户和内核之间搭建了一座桥梁。从技术角度来定义,Shell 最核心的身份就是一个“命令行解释器(Command Interpreter)”。它的工作流程非常精妙:它接收用户输入的指令,将这些人类可读的指令翻译成内核能够理解的机器语言并传递给内核去执行;待内核处理完毕并返回结果后,Shell 又会将这些冰冷的底层反馈,翻译回人类可读的格式呈现给用户。
为了让这个概念更易于理解,我们不妨将其与我们熟悉的 Windows 系统进行类比。在 Windows 环境中,我们通常也不是直接去操作底层的 Windows 内核,而是通过图形用户界面(GUI)来间接完成操作。比如,我们想要进入 D 盘,通常是双击桌面上的 D 盘图标,或者运行某个应用程序。在这个过程中,图形界面就充当了用户与系统内核之间的“翻译官”。Shell 对于 Linux 而言,正是扮演着完全相同的角色。它作为 Linux 的“人机交互界面”,主要负责对我们输入的指令进行解析,将其传递给 Linux 内核去执行;随后,它再将内核运行出的结果接收过来,经过解析后展示给用户,从而完成一次完整的互动。
1.2 Shell命令
1.2.1 命令补全与历史记录
为了提高交互效率,Shell 内置了一套高效的智能联想与历史复用机制,这能大幅减少重复敲击,降低拼写错误。
1. Tab 键补全(命令与路径联想)
Tab 键是 Shell 中最强大的快捷键,它能基于当前上下文进行实时匹配:
-
命令补全:输入命令前缀(如
l)后按 Tab,Shell 会自动补全为唯一匹配的完整命令(如ls),或在存在多个匹配项时列出候选列表(如less,ln等)。 -
路径补全:在输入文件路径时(如
ls dir/),Tab 键会自动扫描目标目录,并将文件名直接补全,省去手动敲入冗长路径的麻烦。
2. 历史命令与会话复用
Shell 会维护一份用户的操作日志(History),通过特定的语法可以实现闪电般的命令召回:
-
查看历史:使用
history命令可以列出当前会话执行过的所有指令及其序号。 -
序号召回:使用
!<序号>可以直接调取历史记录中的特定命令。例如执行!2,Shell 会立即再次执行第 2 条历史命令(即pwd)。 -
前缀模糊匹配:使用
!<前缀>可以执行最近一条以该字符串开头的命令。例如执行!tou,Shell 会自动匹配并执行最近的一条touch newfile.txt。
[whb@bite-alicloud ~]$ history
1 ls -l
2 pwd
3 cd test/
4 touch newfile.txt
[whb@bite-alicloud ~]$ !2 # 执行第2条历史命令
pwd
/home/whb/test
[whb@bite-alicloud ~]$ !tou # 执行以tou开头的历史命令
touch newfile.txt
这种基于历史记录的调用机制,避免了重复造轮子,是提升终端操作效率的核心技巧。
1.2.2 管道与重定向机制
在 Shell 中,默认情况下每个命令都是独立运行的,标准输出(stdout)直接打印在终端。然而,现实场景往往需要将多个命令串联起来协作,或者将输出结果保存到文件中。管道(Pipe)与重定向(Redirection)正是为了解决这一需求而生,它们赋予了 Shell 强大的数据流转能力。
1. 管道(|)
管道符 |的作用是将前一个命令的标准输出(stdout)直接作为后一个命令的标准输入(stdin)。它打破了命令之间的孤立,实现了多个进程间的数据流式处理。
示例:查找 /home目录下属于用户 whb的文件。这里先用 ls -l列出详细信息,再通过管道传递给 grep进行文本过滤。
[whb@bite-alicloud ~]$ ls -l /home | grep "whb"
drwx------ 22 whb whb 4096 Jan 11 14:21 whb
2. 输出重定向
通常情况下,命令的输出默认流向终端屏幕。通过输出重定向,我们可以将这些数据精准地写入到指定的文件中,分为覆盖和追加两种模式:
-
覆盖写入(
>):将命令的输出结果写入文件。如果该文件已存在,则会清空原文件内容;若不存在,则创建新文件。 -
追加写入(
>>):将输出结果添加到文件的末尾,保留原有内容。
示例:
将 ls 的结果覆盖写入 file_list.txt
[whb@bite-alicloud ~]$ ls -l > file_list.txt
使用 echo 向同一文件追加一行新内容
[whb@bite-alicloud ~]$ echo "新增内容" >> file_list.txt
验证文件内容:既包含了文件列表,也包含了追加的文本
[whb@bite-alicloud ~]$ cat file_list.txt
total 8
drwxrwxr-x 2 whb whb 4096 Jan 11 14:22 dir
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
新增内容
3. 输入重定向
与输出重定向相反,输入重定向允许我们将文件的内容直接作为命令的输入源,而不是从键盘读取。
示例:使用 <符号,将 file.txt的内容直接喂给 cat命令读取。这在功能上等价于直接执行 cat file.txt,但展示了数据流向的反向操作。
[whb@bite-alicloud ~]$ cat < file.txt
你好
1.2.3 Shell别名与脚本机制
在熟练掌握了单条命令的使用后,我们自然会面临两个核心需求:如何简化繁琐的长命令? 以及 如何让电脑自动批量处理重复性工作? Shell 提供的“别名(Alias)”与“脚本(Script)”机制,正是解决这两个问题的利器。
1. 别名机制(alias)
别名就像是给常用的长命令串起一个“外号”。通过 alias命令,我们可以将复杂的参数组合封装成一个简短、易记的新命令,大幅提升输入效率。
- 临时设置:直接在终端中定义,仅在当前会话中生效。
给 ls -l 起个简单的别名 ll
[whb@bite-alicloud ~]$ alias ll='ls -l'
定义一个带多个参数的复杂别名
[whb@bite-alicloud ~]$ alias hello='ls -a -l -n'
使用别名,效果等同于执行 ls -l
[whb@bite-alicloud ~]$ ll
total 8
drwxrwxr-x 2 whb whb 4096 Jan 11 14:22 dir
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
- 永久生效:如果需要让别名长期可用,必须将其写入 Shell 的配置文件(如用户主目录下的
~/.bashrc)中。修改后,执行source ~/.bashrc即可让配置立即生效,无需重启终端。
2. 脚本机制
当我们需要执行的任务不再是一两条命令,而是一系列复杂的、有逻辑关联的操作时(例如:批量创建文件、定时清理日志),就需要用到 Shell 脚本(.sh文件)。它是将零散命令组合成“程序”的载体。
-
编写脚本:使用文本编辑器(如
vim)创建一个脚本文件,并在首行指定解释器(#!/bin/bash)。 -
赋予权限:新创建的文件默认没有执行权限,必须通过
chmod +x命令为其添加可执行权限。 -
运行脚本:通过相对路径(
./script.sh)或绝对路径执行。
实战示例:批量创建文件
假设我们需要一次性创建 5 个测试文件,手动敲 touch未免太慢。我们可以编写一个简单的 for循环脚本:
1. 创建脚本文件
[whb@bite-alicloud ~]$ touch create_files.sh
2. 编辑脚本内容
[whb@bite-alicloud ~]$ vim create_files.sh
写入以下内容:
#!/bin/bash 指定解释器
for i in 1 2 3 4 5
do
touch "test_$i.txt"
done
echo "5个文件创建完成!"
3. 赋予执行权限(关键步骤)
[whb@bite-alicloud ~]$ chmod +x create_files.sh
4. 执行脚本
[whb@bite-alicloud ~]$ ./create_files.sh
5个文件创建完成!
5. 验证结果
[whb@bite-alicloud ~]$ ls
create_files.sh test_1.txt test_2.txt test_3.txt test_4.txt test_5.txt
通过脚本,我们将原本需要 5 步的手动操作,简化为 1 步自动化执行,这就是 Shell 脚本在运维和开发中不可替代的价值。
1.3 Shell的运行原理
作为连接用户与 Linux 内核的桥梁,Shell 的本质是一个强大的命令行解释器。当我们敲击回车键的那一刻,Shell 会按照一套严密且高效的流水线作业来执行我们的指令。这个过程环环相扣,主要可以拆解为四个核心步骤:读取命令 →解析命令 →执行命令 →返回结果。
1.3.1 读取命令
用户通过终端输入的字符序列(如 ls -l)被送入标准输入(stdin)。Shell 作为前台进程,会从该文件描述符中同步读取字符流,并存入内部缓冲区,等待解析。
1.3.2 解析命令
Shell 对缓冲区内容进行词法分析与切分,识别出命令名(ls)、选项(-l)及参数。随后,Shell 会判断该命令属于内置命令(如 cd,由 Shell 自身直接处理)还是外部命令。
对于外部命令,Shell 将依照 $PATH环境变量定义的目录顺序,查找对应的可执行文件。可使用 type或 which命令验证查找结果,例如:
$ type ls
ls is aliased to `ls --color=auto'
$ which ls
/usr/bin/ls
可见 ls属于外部命令,实为 /usr/bin/ls的一个带颜色输出的别名。
1.3.3 执行命令
解析阶段确定了命令的“身份”和“位置”后,Shell 进入核心的执行阶段。为了兼顾环境隔离与并发执行,Linux 采用了经典的 fork-exec进程模型来处理外部命令。对于内置命令,直接在当前 Shell 进程中执行,无需创建新进程,如cd命令,若创建子进程执行,切换目录的效果仅在子进程中有效,无法影响当前终端环境;
我们可以用 ps命令来观察 Shell 启动时的初始进程树:
[whb@bite-alicloud ~]$ ps -ef | grep bash
whb 1234 1230 0 10:00 pts/0 00:00:00 -bash
whb 1256 1234 0 10:05 pts/0 00:00:00 grep --color=auto bash
上述输出显示,PID 为 1234的 bash进程是父进程(PPID 1230),此时系统中还没有执行其他任务。
当我们执行一个外部命令(如 ls -l)时,Shell 会执行以下精密的操作:
-
Fork(裂变):Shell 进程调用
fork()系统调用,创建一个几乎完全相同的子进程(Child Process)。 -
Exec(变身):子进程调用
exec()系列函数,释放自身的 Shell 程序代码段,将内存空间完全替换为/usr/bin/ls程序的代码和数据,并开始执行该程序的指令。 -
Wait(同步):父进程(Shell)通常会阻塞并调用
wait(),等待子进程执行完毕,以获取其退出状态。
我们可以通过对比执行前后的进程快照来验证这一过程:
执行命令前,只有 Shell 主进程:
[whb@bite-alicloud ~]$ ps -ef | grep bash
whb 1234 1230 0 10:00 pts/0 00:00:00 -bash
whb 1256 1234 0 10:05 pts/0 00:00:00 grep --color=auto bash
执行 ls -l 命令期间:
[whb@webite-alicloud ~]$ ls -l
total 4
drwxrwxr-x 2 whb whb 4096 Jan 11 14:22 dir
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
执行命令瞬间,出现了一个 ls 子进程 (PID 1260):
[whb@webite-alicloud ~]$ ps -ef | grep ls
whb 1260 1234 0 10:06 pts/0 00:00:00 ls --color=auto
在上面显示的实际的ps输出中,由于 grep本身也是一个外部命令,所以上面显示的 grep --color=auto ls实际上是 grep进程。但在真实的执行逻辑中,当 ls命令执行完毕退出后,其对应的子进程也会随之销毁,终端控制权交还给 Shell。也就是说用 ps | grep这种方式很难捕捉到像 ls这样执行速度极快的瞬时进程。它并不是说 fork-exec模型不对,而是指出了这种观察方法的局限性。在真实的系统里,ls进程确实被创建、执行然后销毁了,只是它的存在时间太短,普通方法“看”不到。
1.3.4 返回结果
当命令执行完毕后,并非简单的“打印”与“结束”。Shell 与命令之间遵循一套严格的 I/O 重定向与状态反馈协议,主要通过标准流(Standard Streams)与退出状态码(Exit Status)来完成闭环。
1. 标准输出(stdout)与标准错误(stderr)
Linux 进程默认会打开三个文件描述符进行通信:
-
0 (STDIN):标准输入,默认指向键盘,用于读取用户输入。
-
1 (STDOUT):标准输出,默认指向终端屏幕,用于输出正常结果。
-
2 (STDERR):标准错误,默认也指向终端屏幕,专门用于处理错误提示。
2. 退出状态码(Exit Code)
除了文本信息,命令执行的最终结果(成功或失败)通过一个整数值——退出状态码来告知 Shell。
-
约定规范:在 Unix/Linux 哲学中,约定
0 代表命令成功执行;非0 的整数代表不同类型的异常或错误。 -
状态捕获:Shell 在命令结束后会将此状态码存入特殊变量
$? 中,供后续脚本逻辑进行条件判断。
我们可以通过具体的命令执行实例来验证这一机制:
场景一:命令执行成功
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
捕获退出码:$? 的值为 0,表示执行无误
[whb@bite-alicloud ~]echo $? # 查看上一条命令的退出状态码
0
场景二:命令执行失败(文件不存在)
[whb@bite-alicloud ~]$ ls -l nofile.txt
ls: cannot access 'nofile.txt': No such file or directory
捕获退出码:$? 为非 0 值(此处为 2),表示发生错误
[whb@bite-alicloud ~]echo $?
2
通过这种标准化的信号交互,Shell 能够准确感知下游命令的执行状态,从而决定脚本是继续向下运行,还是触发错误处理分支。
二、Linux权限
2.1 权限的意义
Linux 作为典型的多用户、多任务操作系统,其设计初衷就是允许多个用户在同一台机器上协同工作,共享硬件与文件系统资源。为了在这种开放的环境中保障数据的安全性与系统的稳定性,权限机制(Permission)应运而生,成为守护资源的“无形之门”。
其核心目的可以归纳为以下三点:
-
访问控制:精确控制不同身份的用户(Who)对特定资源(What)拥有何种操作权限(How)。基本权限包括读(Read)、写(Write)、执行(Execute)。
-
数据保护:防止未授权的用户非法篡改、删除或窃取系统中的重要文件与配置,确保数据的机密性和完整性。
-
系统安全:限制普通用户的操作范围,避免误操作或恶意破坏导致的内核崩溃、服务宕机或全系统瘫痪。
2.2 Linux 用户与用户组
要理解权限如何运作,首先需要明确 Linux 中的“访问主体”——用户(User)与用户组(Group)。所有的权限检查,本质上都是对这些身份的校验。
2.2.1 三类核心用户
Linux 系统将所有使用者划分为三类,每类对应不同的系统角色和权限级别:
超级用户 (root):
特征:系统的“终极管理员”,命令提示符为
#。权限:拥有至高无上的系统控制权,可以跨越任何权限限制,执行任何操作(如修改核心配置、安装卸载软件、管理所有文件)。
普通用户:
特征:日常登录和工作的主体,命令提示符通常为
$。权限:权限受到严格限制,默认只能查看和修改属于自己的文件,或那些被明确授权给所有人的公共资源。
虚拟用户 (系统用户/服务用户):
特征:通常不对应真实的人类操作者,没有登录密码和 Shell 环境。
用途:专用于运行特定的后台服务(如 Web 服务器、数据库),以确保服务进程的独立性和安全性,防止被外部直接登录操控。
用户切换实战 :su命令
在实际运维中,我们经常需要在不同身份间切换。使用 su(Switch User) 命令可以实现身份的临时转换:
场景一:从普通用户(whb)切换到超级管理员(root)
注意:需要输入 root 用户的密码才能通过验证
[whb@bite-alicloud ~]$ su root
Password:
[root@bite-alicloud whb]# whoami # 验证当前身份
root
场景二:从超级管理员(root)切回普通用户(whb)
特权:root 切换到任何普通用户均无需密码验证,这是 root 的特权之一
[root@bite-alicloud whb]# su whb
[whb@bite-alicloud ~]$ whoami
whb
2.2.2 用户组的作用与管理
当系统用户增多时,如果为每个用户单独设置文件权限,管理成本将呈指数级上升。用户组(Group)机制正是为了解决这个问题而设计的——它是多个用户的逻辑集合,用于简化批量权限管理。
核心逻辑:
将具有相同职能或协作需求的人员归入同一个“部门”(用户组),只需为该组分配一次权限,组内所有成员即刻生效,无需逐个配置。
常用组管理命令示例:
-
创建新组:
groupadd test_group
-
创建用户并直接加入指定组:
useradd -g test_group test_user
-
修改已有用户的所属组:
usermod -g test_group test_user
-
查看用户隶属于哪些组:
groups test_user
2.3 文件/目录的权限表示方法
在 Linux 中,每个文件或目录的权限都可以通过 ls -l命令查看,其权限信息由 10 个字符 组成,格式如下:
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
这 10 个字符可分为 4 个部分,拆解后含义如下:
|
位置 |
含义 |
示例(-rw-rw-r--) |
|---|---|---|
|
第 1 位 |
文件类型 |
|
|
第 2-4 位 |
所有者(u)权限 |
|
|
第 5-7 位 |
所属组(g)权限 |
|
|
第 8-10 位 |
其他用户(o)权限 |
|
2.3.1 文件类型标识
第 1 位的字符代表文件类型,常见类型如下:
|
标识字符 |
文件类型名称 |
详细说明与示例 |
|---|---|---|
|
- |
普通文件 |
最常见的文件类型,包含文本文件、可执行程序、数据文件等。 |
|
d |
目录 |
即文件夹,用于组织和存放其他文件与子目录。 |
|
l |
软链接 |
类似于 Windows 系统中的“快捷方式”,指向另一个文件或目录的路径。 |
|
b |
块设备文件 |
提供随机存取能力的设备,如硬盘、光驱、U盘等。 |
|
c |
字符设备文件 |
提供流式存取的设备,如键盘、鼠标、屏幕等终端设备。 |
|
p |
管道文件 |
用于进程间通信(IPC),实现数据的单向传输。 |
|
s |
套接口文件 |
主要用于网络通信,常见于数据库服务等后台进程的网络连接。 |
示例:
[whb@bite-alicloud ~]$ ls -l
total 12
drwxrwxr-x 2 whb whb 4096 Jan 11 14:22 dir # d表示目录
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt # -表示普通文件
lrwxrwxrwx 1 whb whb 8 Jan 11 19:00 link.txt -> file.txt # l表示软链接
2.3.2 基本权限含义
第 2-10 位的权限由 r(读)、w(写)、x(执行)三个字符组合而成,-表示“无该权限”。
不同权限对 文件 和 目录 的作用完全不同,具体如下:
|
权限 |
对文件的作用 |
对目录的作用 |
|---|---|---|
|
|
可读取文件内容(如 |
可查看目录下的文件列表(如 |
|
|
可修改文件内容(如 |
可在目录中创建、删除、移动文件(如 |
|
|
可执行文件(如 |
可进入目录(如 |
关键注意点:
-
目录的
x权限是“进入目录”的基础 —— 即使有r权限,没有x也无法cd进入目录。 -
目录的
w权限允许删除其中的文件(无论文件所有者是谁)。后续学习“粘滞位(sticky bit)”后会明白如何避免这种情况。
2.3.3 权限的数值表示法
除了字符表示法,Linux 还提供了更高效的八进制数值表示法。这种方法是基于二进制计算得出的,非常适合批量设置权限。它的核心逻辑是将 r(读)、w(写)、x(执行)三种权限赋予不同的权重,通过简单的加法运算来组合出最终的权限状态。
1. 权限的权重映射
每种权限对应一个固定的数值权重:
-
读 (r) = 4
-
写 (w) = 2
-
执行 (x) = 1
-
无权限 (-) = 0
2. 计算规则
一个完整的三位数权限(如 755),每一位数字都是由 所有者(u)、所属组(g)、其他用户(o) 的权限权重相加而来:
-
第一位数字:代表所有者的权限值总和。
-
第二位数字:代表所属组的权限值总和。
-
第三位数字:代表其他用户的权限值总和。
3. 常见权限数值对照表
|
数值 |
字符表示 |
权限分配拆解 |
典型应用场景 |
|---|---|---|---|
|
777 |
|
所有者(4+2+1) + 组(4+2+1) + 其他人(4+2+1) |
所有用户拥有完全控制权限(常用于测试环境,生产环境慎用)。 |
|
755 |
|
所有者(4+2+1) + 组(4+0+1) + 其他人(4+0+1) |
目录标准权限。所有者可读写执行,同组及其他用户可读和执行(进入)。 |
|
644 |
|
所有者(4+2+0) + 组(4+0+0) + 其他人(4+0+0) |
文件标准权限。所有者可读写,同组及其他用户仅可读。 |
|
600 |
|
所有者(4+2+0) + 组(0+0+0) + 其他人(0+0+0) |
私密文件权限。仅所有者拥有读写权限,其他任何人无法访问(如 SSH 私钥)。 |
4. 实例解析
通过数值快速还原权限的实际含义:
示例 1:664
拆解:所有者(6=4+2) + 所属组(6=4+2) + 其他用户(4)
含义:所有者和组成员可读写,其他人只读。
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
示例 2:755
拆解:所有者(7=4+2+1) + 所属组(5=4+1) + 其他用户(5=4+1)
含义:所有者完全控制,组和其他人可读+进入目录。
[whb@bite-alicloud ~]$ ls -ld dir
drwxr-xr-x 2 whb whb 4096 Jan 11 14:22 dir
2.4 修改权限的命令
Linux 提供了三个核心命令来管理权限:chmod(改权限)、chown(改所有者)和 chgrp(改所属组)。它们共同构成了文件安全策略的执行工具。
2.4.1 chmod:修改权限
chmod(Change Mode) 是控制文件访问权的核心命令。它支持两种修改模式:字符模式(直观易懂)和 数值模式(高效快捷)。
1. 字符修改
通过指定“用户范围”和“操作符”来动态调整权限。
chmod [选项] [用户标识][+/-/=][权限字符] 文件名/目录名
-
用户标识:
u(所有者)、g(所属组)、o(其他用户)、a(所有用户)。 -
操作符:
+(添加)、-(移除)、=(覆盖设置为)。 -
选项:
-R(递归修改目录及其子内容)。
示例:精细化调整
查看初始状态:所有者读写,组和其他人只读
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-rw-r-- 1 whb whb 0 Jan 11 14:22 file.txt
1. 给“其他用户”添加写权限
[whb@bite-alicloud ~]$ chmod o+w file.txt
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-rw-rw- 1 whb whb 0 Jan 11 14:22 file.txt
2. 撤销“所属组”的写权限
[whb@bite-alicloud ~]$ chmod g-w file.txt
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-r--rw- 1 whb whb 0 Jan 11 14:22 file.txt
2. 数值修改
使用三位八进制数字直接设定权限状态,是最常用的方式。
chmod [选项] 权限数值 文件名/目录名
示例:快速设置标准权限
设置文件为 644 (rw-r--r--):所有者读写,其他人只读
[whb@bite-alicloud ~]$ chmod 644 file.txt
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-r--r-- 1 whb whb 0 Jan 11 14:22 file.txt
设置目录为 755 (rwxr-xr-x),并递归应用到子目录
注意:ls -ld 用于查看目录本身的权限
[whb@bite-alicloud ~]$ chmod -R 755 dir
[whb@bite-alicloud ~]$ ls -ld dir
drwxr-xr-x 2 whb whb 4096 Jan 11 14:22 dir
2.4.2 chown:修改所有者
chown用于变更文件或目录的归属权。
⚠️ 注意:只有 root用户或文件的原所有者才有权限执行此操作。
语法规则:
chown [选项] 新所有者[:新所属组] 文件名/目录名
-
:的作用:用于同时修改所有者和所属组。 -
选项:
-R(递归修改)。
示例:变更归属权
1. 创建测试用户
[root@bite-alicloud ~]# useradd test_user
2. 查看文件当前所有者为 whb
[whb@bite-alicloud ~]$ ls -l file.txt
-rw-r--r-- 1 whb whb 0 Jan 11 14:22 file.txt
3. 将所有者变更为 test_user
[root@bite-alicloud ~]# chown test_user file.txt
[root@bite-alicloud ~]# ls -l file.txt
-rw-r--r-- 1 test_user whb 0 Jan 11 14:22 file.txt
2.4.3 chgrp:修改所属组
chgrp是专门用于修改文件或目录“所属组”的命令,用法比 chown更单一。
语法规则:
chgrp [选项] 新所属组 文件名/目录名
-
选项:
-R(递归修改)。
示例:修改目录所属组
1. 查看目录当前所属组为 test_user
[root@bite-alicloud ~]# ls -ld dir/
drwxr-xr-x 2 test_user test_user 4096 Jan 11 14:22 dir/
2. 将所属组修改为 whb
[root@bite-alicloud ~]# chgrp whb dir/
[root@bite-alicloud ~]# ls -ld dir/
drwxr-xr-x 2 test_user whb 4096 Jan 11 14:22 dir/
2.5 文件掩码 umask
在 Linux 中,当我们创建一个新文件或目录时,系统并不是简单地给予它们默认的满权限(如 666 或 777),而是通过一种叫做 umask(文件掩码) 的机制来控制初始权限。
简单来说,umask 定义了在创建资源时默认需要“屏蔽”或“拿走”哪些权限,以防止所有新建文件都具有过高的开放度,从而保障系统基础安全。
2.5.1 umask 的作用与计算逻辑
Linux 系统中存在两个预设的“基准权限”:
-
文件基准权限:
0666(即 rw-rw-rw-) -
目录基准权限:
0777(即 rwxrwxrwx)
umask 的工作就是从这个基准权限中减去自身设定的值,得出最终的默认权限。计算公式为:
-
新文件默认权限 =
0666 - umask(注:出于安全考虑,系统会自动抹去文件的可执行权限) -
新目录默认权限 =
0777 - umask(注:目录必须具备执行权限才能被进入)
不同用户的默认 umask 值:
系统为不同身份的用户设定了不同的默认掩码,以降低风险:
-
root 用户:默认
0022。这意味着会拿走“组用户”和“其他用户”的写权限(---w--w-)。 -
普通用户:默认
0002。这意味着只会拿走“其他用户”的写权限(-------w-)。
2.5.2 umask 的查看与修改实操
我们可以通过简单的命令来查看当前的 umask 值,并通过一个实际的文件创建案例来验证上述的计算逻辑。
示例:验证文件的默认权限的计算过程
1. 普通用户查看当前 umask 值
输出 0002,表示将默认去除其他用户的“写”权限
[whb@bite-alicloud ~]$ umask
0002
2. 理论计算:
新文件权限 = 0666(基准) - 0002(掩码) = 0664
转换为字符即为 rw-rw-r--
3. 实际创建测试文件
[whb@bite-alicloud ~]$ touch test_umask.txt
4. 验证实际权限
结果确实是 -rw-rw-r-- (664),与计算结果完全一致
[whb@bite-alicloud ~]$ ls -l test_umask.txt
-rw-rw-r-- 1 whb whb 0 Jan 11 19:30 test_umask.txt
目录的权限计算也同理:
# 创建新目录,默认权限=0777-0002=0775(rwxrwxr-x)
[whb@bite-alicloud ~]$ mkdir dir_umask
[whb@bite-alicloud ~]$ ls -ld dir_umask/
drwxrwxr-x 2 whb whb 4096 Jan 11 19:31 dir_umask/
如果想要修改umask的值,直接在命令行输入 umask加上你想要的新掩码数值即可。关闭终端后,设置将失效。
将 umask 修改为 0022
这意味着以后新建的文件默认权限将变为 0644 (rw-r--r--)
[whb@bite-alicloud ~]$ umask 0022
再次创建测试文件验证
[whb@bite-alicloud ~]$ touch test_umask2.txt
[whb@bite-alicloud ~]$ ls -l test_umask2.txt
-rw-r--r-- 1 whb whb 0 Jan 11 19:35 test_umask2.txt
如果你希望每次登录系统或在当前用户下工作时,都保持自定义的 umask 值,需要将其写入特定的配置文件中:
-
针对当前用户生效:编辑用户主目录下的
~/.bashrc或~/.bash_profile文件,在末尾添加一行umask 0022,然后保存退出。 -
针对所有用户生效(系统级):编辑
/etc/profile文件,找到umask相关的设置行进行修改,或者使用umask 0022命令重新加载配置使其立即生效。
2.6 粘滞位(Sticky Bit)
在 Linux 系统的日常管理中,权限控制是保障数据安全的核心机制。通常情况下,如果我们对一个目录赋予了 777(即 rwxrwxrwx)的权限,意味着该目录下的所有用户都可以自由地读取、写入和执行其中的文件。
然而,这种极高的开放度会带来一个严重的安全隐患:任何用户都拥有了删除该目录下文件的权限。这就意味着,即使某个文件不是用户自己创建的(例如张三创建的文件),只要李四对该目录有写权限,他就能轻易地将张三的文件误删。为了防止这种“误伤”行为,Linux 引入了粘滞位(Sticky Bit)这一特殊权限。
2.6.1 粘滞位的作用与标识
粘滞位的核心作用是限制目录内文件的删除操作。当一个目录被设置了粘滞位后,该目录下的文件将受到严格保护,只有以下三类主体才有权限删除这些文件:
超级用户 (root):拥有至高无上的系统控制权。
目录的所有者:即创建了该文件夹的用户。
文件的所有者:即创建了该特定文件的用户。
粘滞位的视觉标识:
在查看目录权限时,如果最后一位权限字符变为了小写字母 t,就代表该目录开启了粘滞位。
正常满权限目录:
drwxrwxrwx开启粘滞位的目录:
drwxrwxrwt
2.6.2 粘滞位的设置与验证实操
为了直观地理解粘滞位如何防止文件被误删,我们可以通过以下一组实操命令来进行验证。
第一步:模拟无保护的共享目录环境
首先,我们创建一个测试目录,并故意将其权限设置为所有人都可读写执行(777),模拟一个公共共享文件夹。
1. 创建测试目录 sticky_dir
[root@bite-alicloud ~]# mkdir sticky_dir
2. 将目录权限设置为 777 (drwxrwxrwx)
[root@bite-alicloud ~]# chmod 777 sticky_dir/
3. 查看目录权限,确认最后一位是 x
[root@bite-alicloud ~]# ls -ld sticky_dir/
drwxrwxrwx 2 root root 4096 Jan 11 19:40 sticky_dir/
第二步:普通用户创建文件并尝试互删
接下来,我们切换到普通用户 whb,在刚才创建的共享目录中生成一个文件。
切换到普通用户 whb
[whb@bite-alicloud ~]$ cd sticky_dir/
创建测试文件
[whb@bite-alicloud sticky_dir]$ touch whb_file.txt
查看文件权限,所有者是 whb
[whb@bite-alicloud sticky_dir]$ ls -l
total 0
-rw-rw-r-- 1 whb whb 0 Jan 11 19:41 whb_file.txt
此时,假设系统中还有另一个普通用户 test_user。在没有粘滞位的情况下,test_user虽然不能修改 whb_file.txt的内容,但他完全可以删除这个文件,因为他拥有 sticky_dir目录的写权限。
切换到另一个普通用户 test_user (注:此处需具备进入该目录的权限)
[test_user@bite-alicloud ~]$ cd /home/whb/sticky_dir
尝试删除 whb 创建的文件
[test_user@bite-alicloud sticky_dir]$ rm whb_file.txt
rm: remove regular empty file 'whb_file.txt'? y
删除成功!查看目录,文件已消失
[test_user@bite-alicloud sticky_dir]$ ls -l
total 0
第三步:开启粘滞位并再次验证
现在,我们回到 root 用户,给 sticky_dir目录加上粘滞位(使用 +t参数)。
回到 root 用户并添加粘滞位 (chmod +t)
[root@bite-alicloud ~]# chmod +t sticky_dir/
[root@bite-alicloud ~]# ls -ld sticky_dir/
drwxrwxrwt 2 root root 4096 Jan 11 19:43 sticky_dir/
再次切换到普通用户 whb,重新创建文件
[whb@bite-alicloud ~]$ touch sticky_dir/whb_file2.txt
此时,当 test_user再次尝试删除 whb的文件时,系统会触发保护机制:
test_user 再次尝试删除 whb 的文件
[test_user@bite-alicloud ~]$ rm sticky_dir/whb_file2.txt
rm: remove regular empty file 'sticky_dir/whb_file2.txt'? y
rm: cannot remove 'sticky_dir/whb_file2.txt': Operation not permitted
删除失败!系统明确提示“操作不被允许”
[test_user@bite-alicloud ~]$ ls -l sticky_dir/
total 0
-rw-rw-r-- 1 whb whb 0 Jan 11 19:44 whb_file2.txt
现实应用案例:
Linux 系统中的 /tmp 目录就是最典型的粘滞位应用场景。它是一个所有用户都可以读写的全局临时文件存放区。正是因为 /tmp默认开启了粘滞位(drwxrwxrwt),才确保了用户 A 在 /tmp里生成的临时文件,不会被用户 B 意外或恶意删除,保障了多用户环境下的系统稳定与安全。
为了让 sudo权限提升这一节的内容更加系统化和易于理解,我将配置逻辑梳理为“语法拆解”和“最小权限原则”,并补充了关于密码缓存和日志记录的重要细节。以下是润色后的完整内容:
2.7 sudo:普通用户的权限提升
在日常运维中,普通用户(如 whb)的权限是受限的。若需要执行 root用户的特权命令(例如安装软件、修改核心系统配置),无需频繁切换账号,可以通过 sudo(Superuser Do) 命令实现临时提权。
2.7.1 sudo 的配置机制
sudo 的权限规则并不在命令行直接指定,而是集中配置在 /etc/sudoers文件中。由于该文件语法严格,强烈建议使用 visudo命令进行编辑。它会在保存时自动检查语法,有效避免因配置错误导致所有用户都无法使用 sudo 的严重后果。
使用 visudo 安全地编辑配置文件
[root@bite-alicloud ~]# visudo
1. 配置语法与参数拆解
在 /etc/sudoers文件中,标准的授权配置行由三部分组成:
用户名 主机=(目标身份) 可执行命令列表
我们可以通过以下两个示例来深入理解每个 ALL的含义:
场景 A:赋予完全管理员权限
whb ALL=(ALL) ALL
效果:用户 whb可以在本机上以任何人的身份运行任何命令,相当于拥有了临时的 root 权限。
-
第一个
ALL:允许在所有主机上使用该配置(针对多服务器集群环境)。 -
第二个
(ALL):允许以所有用户身份执行命令(即可以切换到任意用户,包括 root)。 -
第三个
ALL:允许执行所有命令。
场景 B:遵循“最小权限原则”(推荐)
为了系统安全,通常不建议直接赋予 ALL权限,而是限制其只能运行特定的必要命令。
whb ALL=(ALL) /usr/sbin/useradd
效果:用户 whb依然可以在本机和以任意身份运行命令,但仅限于执行 /usr/sbin/useradd(创建用户)。如果尝试运行其他未授权的命令(如 rm -rf /),系统会拒绝。
2.7.2 sudo 的使用示例与特性
配置生效后,普通用户即可体验提权操作。这里有几个关键的实操细节:
示例:创建新用户
1. 尝试直接创建用户(权限不足,被拒绝)
[whb@bite-alicloud ~]$ useradd new_user
useradd: Permission denied
2. 使用 sudo 前缀重新执行
[whb@bite-alicloud ~]$ sudo useradd new_user
3. 系统提示输入密码(注意:输入的是 whb 自己的密码,而非 root 密码)
[sudo] password for whb:
4. 验证用户创建成功
[whb@bite-alicloud ~]$ id new_user
uid=1005(new_user) gid=1005(new_user) groups=1005(new_user)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)