引言:
💡 阅读策略建议
本文设计为「工具字典」,无需死记硬背,遇到问题时直接按场景查阅即可。
你只需要:
🔸 了解每个指令能解决什么问题
🔸 收藏本文作为实战弹药库
🔸 需要时用 Ctrl+F 精准提取
文章目录
1.什么是Namespace?
namespace
是 Linux 内核用来隔离内核资源的方式。通过 namespace,不同进程能看到各自独立的资源,彼此之间完全感知不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。
Linux namespaces 是对 全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前namespace 里的进程,对其他 namespace 中的进程没有影响。
Linux 提供了多个API 用来操作 namespace,它们是 clone()
、 setns()
和 unshare()
函数,为了明确隔离的具体是哪类 namespace,在使用这些 API 时,通常需要指定一些调用参数: CLONE_NEWIPC、 CLONE_NEWNET、 CLONE_NEWNS、CLONE_NEWPID、 CLONE_NEWUSER、 CLONE_NEWUTS
和CLONE_NEWCGROUP
。如果要同时隔离多个 namespace,可以使用 | (按位或)组合这些参数。
举个例子
三年一班的小明和三年二班的小明,虽说他们名字是一样的,但是所在班级不一样,那么,在全年级排行榜上面,即使出现两个名字一样的小明,也会通过各自的学号来区分。对于学校来说,每个班级就相当于是一个命名空间,这个空间的名称是班级号。班级号用于描述逻辑上的学生分组信息,至于什么学生分配到 1 班,什么学生分配到 2 班,那就由学校层面来统一调度。
2.dd命令
- 功能:用于读取、转换并输出数据。dd可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准数据。
语法:
shell
dd OPITION
参数:
if=文件名
:输入文件名(即指的源文件),默认为标准输入of=文件名
:输出文件名(即指定目的文件),默认为标准输出ibs=bytes
:一次读入bytes个字节,即指定一个块大小为bytes个字节obs=bytes
:一次输出bytes个字节bs=bytes
:同时读入/输出的块大小为bytes字节cbs=bytes
:一次转换bytes个字节,即指定转换缓冲区大小skip=blocks
:从输入文件开头跳过blocks个块后再开始拷贝seek=blocks
:从输出文件开头跳过blocks个块后开始拷贝count=blocks
:仅拷贝blocks个块,块大小等于ibs指定的字节数conv=<关键字>
,关键字有以下11中:conversion
:用指定的参数转换文件ascii
:转换 ebcdic 为 asciiebcdic
:转换 ascii 为 ebcdicibm
:转换 ascii 为 alternate ebcdicblock
:把每一行转换为长度为 cbs,不足部分用空格填充unblock
:使每一行的长度都为 cbs,不足部分用空格填充lcase
:把大写字符转换为小写字符ucase
:把小写字符转换为大写字符swap
:交换输入的每对字节noerror
:出错时不停止sync
: 将每个输入块填充到 ibs 个字节,不足部分用空(NULL)字符补齐。
--help
: 显示帮助信息--version
: 显示版本信息
示例:创建指定大小空白文件
- 输入文件:特殊文件设备,产生连续不断的空白字符流。
- 输出文件:空白镜像文件。
shell
dd if=/dev/zero of=test.img bs=8k count=1024
效果如下:
示例2:
大小写转换
shell
vim in.txt #创建文件,在里面写入 hello world
dd if=in.txt of=out.txt conv=ucase
效果:
3.mkfs命令
功能:
- 用于在设备上创建 Linux 文件系统(俗称格式化),例如格式化 U 盘等存储设备。
语法:
shell
mkfs [-V] [-t fstype] [fs-options] filesys [blocks]
参数说明
-V
:启用详细显示模式。-t fstype
:指定要创建的文件系统类型(如 ext3、ext4)。filesys
:指定目标设备的文件名(如 /dev/sdb1)。blocks
:指定文件系统的磁盘块数。fs-options
:传递给具体文件系统的额外参数。
示例:
把镜像文件格式化为磁盘文件。
shell
mkfs -t ext4 ./test.img
效果:
4.df命令
- 功能:用于显示 Linux 系统上文件系统的磁盘使用情况统计。
语法:
shell
df [OPTION]... [FILE]...
常见参数
-a, --all
:显示所有文件系统(包括占用 0 Blocks 的文件系统)。-h, --human-readable
:以人类可读的格式显示(如 KB、MB、GB)。-H, --si
:类似 -h,但以 1000 为单位换算(而非 1024)。-t, --type=TYPE
:仅显示指定类型的文件系统(如 ext4)。-T, --print-type
:显示文件系统类型。
示例:
shell
df

shell
df -a

shell
df -h

shell
df -t ext4

5.mount命令
- 功能:用于将文件系统加载到指定的挂载点。该命令常用于挂载光盘等存储设备,因为在 Linux 系统中插入光盘后不会自动挂载,需手动使用 mount 命令完成挂载操作。
语法:
shell
mount -t [文件系统类型] [选项] [设备源] [挂载点]
什么是挂载?例子:插入U盘,然后弹出磁盘E:
Linux 挂载特点
- 灵活组合:
- Linux 系统下不同目录可以挂载到不同的分区或磁盘设备。
- 目录与磁盘分区是分离的,可通过挂载自由组合。
- 数据分布:
- 不同目录的数据可以跨越多个磁盘分区或不同的磁盘设备。
- 挂载实质:
- 挂载的本质是为磁盘设备添加访问入口(挂载点)。
示例:
用上文格式化好的test.img文件,挂载到目录,如目录mkdir testmount
(先创建好该目录)
挂载:
shell
mount ./test.img /testmount
查看:
shell
df -h

现在我们就把一个空白镜像文件挂载成磁盘。
6.unshare 命令
- 功能:用于在不共享父进程命名空间的情况下运行指定程序。
语法:
shell
unshare [options] program [arguments]
短参数 长参数 功能描述
-i,--ipc
:不共享 IPC 命名空间(进程间通信隔离)-m,--mount
:不共享 Mount 命名空间(文件系统挂载点隔离)-n,--net
:不共享 Net 命名空间(网络栈隔离)-p,--pid
:不共享 PID 命名空间(进程ID隔离)-u,--uts
:不共享 UTS 命名空间(主机名和域名隔离)-U,--user
:不共享 User 命名空间(用户和用户组隔离)-V,--version
:显示 unshare 命令版本信息--fork
:先 fork 子进程,再在子进程中执行 unshare(用于避免影响父进程环境)--mount-proc
:在启动子进程前,优先挂载 /proc 文件系统(通常与 --pid 配合使用)
示例
隔离主机名,创建新的bash子进程并与父进程隔离:
shell
unshare -u /bin/bash
验证:
shell
hostname test #设置主机名,为test
hostname #查看主机名,并新窗口查看主机名是否一样。
exit #退出子进程
hostname #查看主机名
效果:
7.PID隔离
示例:
shell
unshare -p /bin/bash #错误演示

PID 命名空间的特性
PID 命名空间的目的是隔离进程树,使新命名空间中的进程从 PID 1 开始重新编号。但 Linux 要求:
- 每个 PID 命名空间必须有一个初始进程(init 进程,PID=1)。
- 这个 init 进程需要管理命名空间内的孤儿进程(防止僵尸进程)。
如果直接运行 unshare -p /bin/bash
:
-
/bin/bash 会继承当前进程的 PID(仍在原命名空间),无法成为新 PID 命名空间的 init 进程。
-
新命名空间没有有效的 init 进程,导致功能异常(如
ps、top
等命令失效)。
--fork
的作用
--fork
(或 -f
)会让 unshare
在创建新命名空间后,先调用 fork() 创建一个子进程,再在该子进程中运行 /bin/bash。这样:
unshare
调用fork()
,生成一个子进程。- 子进程进入新的 PID 命名空间,并成为该命名空间的
init
进程(PID=1)。 - 子进程再执行
/bin/bash
,此时 Bash 的 PID 在新命名空间中为 1。
如果没有 --fork:
/bin/bash
的 PID 仍然是原命名空间的 PID(非 1),导致新 PID 命名空间无 init 进程,破坏隔离性。
添加 --fork:
shell
unshare -p --fork /bin/bash #错误演示
注意:如果执行失败,使用exit指令退出子进程,再进行执行。
仅加上 --fork选项仍然有问题,当运行ps、top、htop
等命令时,它们实际上是从 历史/proc 读取数据。
效果:
/proc 文件系统的作用
/proc 是一个 虚拟文件系统(procfs),它动态反映系统内核的运行时信息,包括:
- 进程信息(/proc/[PID]/)
- 系统资源(CPU、内存、设备等)
- 内核参数(可通过 sysctl 调整)
当运行ps、top、htop
等命令时,它们实际上是从/proc
读取数据。
默认 /proc 的问题
默认情况下,/proc 挂载的是 宿主机的 PID 命名空间 的信息。如果只运行:
- bash
unshare -p --fork /bin/bash
虽然进入了新的 PID 命名空间(echo $$ 显示 1),
但 /proc 仍然显示原命名空间的进程信息,导致:ps aux
会显示所有宿主机进程(而非当前命名空间的进程)。top、htop
等工具也无法正确运行。
--mount-proc 的作用
--mount-proc
选项会自动:
- 卸载当前
/proc
(如果已挂载)。 - 重新挂载一个
新的 /proc
,使其仅显示 当前PID
命名空间 的进程信息。
示例(正确用法):
shell
unshare -p --fork --mount-proc /bin/bash
效果:
运行后:
echo $$
返回 1(当前 Bash 是新命名空间的 init 进程)。ls /proc
仅显示当前命名空间的进程(如 1/, 2/ 等)。ps aux
仅显示当前命名空间的进程。
如果不加 --mount-proc会怎样?
如果不加 --mount-proc
,你需要 手动重新挂载 /proc:
mount -t proc proc /proc
# 手动挂载
否则:
ps aux
会显示 宿主机的所有进程(不符合 PID 隔离的预期)。- 某些依赖 /proc 的命令(如
pstree、pgrep
)可能报错。
为什么不能复用旧的 /proc?
- 因为 /proc 的内容是动态生成的,它依赖于 当前 PID 命名空间:
- 在 新 PID 命名空间 中,进程的 PID 会重新编号(如 bash 变成 PID 1)。
但旧的 /proc 仍然关联 原命名空间,导致:/proc/1/
可能指向宿主机systemd 或 init
,而非当前 bash。ps
读取 /proc 时,会看到错误的进程信息。
--mount-proc
确保 /proc 和 当前 PID 命名空间 匹配。
验证:打开新窗口,查看两个窗口的ls -l /proc
和ps -ef
8.Mount隔离
文件系统隔离
一共需要完成三步:
- 创建--mount进程
- 创建空白文件,挂载成磁盘
- 创建mount隔离进程
创建--mount进程
shell
unshare --mount --fork /bin/bash
创建空白文件完成挂载
shell
dd if=/dev/zero of=data.img bs=8k count=10240 #创建空白文件
mkfs -t ext4 ./data.img #格式化空白文件
完成挂载隔离
shell
mkdir -p test/mt1 #创建目录
mount -t ext4 ./data.img test/mt1 #挂载到目录
df -h #新建窗口,两窗口执行该指令,验证是否完成文件系统隔离
效果:
📌 写给读者的小纸条
"这些指令组合就像厨房里的调味罐------不用记住每一瓶的位置,用的时候拉开抽屉随手拿就好。
建议把本文丢进收藏夹吃灰(偶尔能翻出来用的才是好工具),需要时Ctrl+F一搜,省下的时间够喝杯咖啡啦 ☕"
非常感谢您能耐心读完这篇文章。倘若您从中有所收获,还望多多支持呀!