引言: 💡 阅读策略建议 本文设计为「工具字典」,无需死记硬背,遇到问题时直接按场景查阅即可。 你只需要: 🔸 了解每个指令能解决什么问题 🔸 收藏本文作为实战弹药库 🔸 需要时用 Ctrl+F 精准提取
文章目录
- 1.什么是Namespace?
- 2.dd命令
- 3.mkfs命令
- 4.df命令
- 5.mount命令
- 6.unshare 命令
- 7.PID隔离
- 8.Mount隔离
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可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准数据。
语法:
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 为 ascii
- ebcdic:转换 ascii 为 ebcdic
- ibm:转换 ascii 为 alternate ebcdic
- block:把每一行转换为长度为 cbs,不足部分用空格填充
- unblock:使每一行的长度都为 cbs,不足部分用空格填充
- lcase:把大写字符转换为小写字符
- ucase:把小写字符转换为大写字符
- swap:交换输入的每对字节
- noerror:出错时不停止
- sync: 将每个输入块填充到 ibs 个字节,不足部分用空(NULL)字符补齐。
- –help: 显示帮助信息
- –version: 显示版本信息
示例:创建指定大小空白文件
- 输入文件:特殊文件设备,产生连续不断的空白字符流。
- 输出文件:空白镜像文件。
dd if=/dev/zero of=test.img bs=8k count=1024
效果如下: 示例2: 大小写转换
vim in.txt #创建文件,在里面写入 hello world
dd if=in.txt of=out.txt conv=ucase
效果:
3.mkfs命令
功能:
- 用于在设备上创建 Linux 文件系统(俗称格式化),例如格式化 U 盘等存储设备。
语法:
mkfs [-V] [-t fstype] [fs-options] filesys [blocks]
参数说明
- -V:启用详细显示模式。
- -t fstype:指定要创建的文件系统类型(如 ext3、ext4)。
- filesys:指定目标设备的文件名(如 /dev/sdb1)。
- blocks:指定文件系统的磁盘块数。
- fs-options:传递给具体文件系统的额外参数。
示例: 把镜像文件格式化为磁盘文件。
mkfs -t ext4 ./test.img
效果:
4.df命令
- 功能:用于显示 Linux 系统上文件系统的磁盘使用情况统计。
语法:
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:显示文件系统类型。 示例:
df
df -a
df -h
df -t ext4
5.mount命令
- 功能:用于将文件系统加载到指定的挂载点。该命令常用于挂载光盘等存储设备,因为在 Linux 系统中插入光盘后不会自动挂载,需手动使用 mount 命令完成挂载操作。
语法:
mount -t [文件系统类型] [选项] [设备源] [挂载点]
什么是挂载?例子:插入U盘,然后弹出磁盘E:
Linux 挂载特点
- 灵活组合:
- Linux 系统下不同目录可以挂载到不同的分区或磁盘设备。
- 目录与磁盘分区是分离的,可通过挂载自由组合。
- 数据分布:
- 不同目录的数据可以跨越多个磁盘分区或不同的磁盘设备。
- 挂载实质:
- 挂载的本质是为磁盘设备添加访问入口(挂载点)。
示例: 用上文格式化好的test.img文件,挂载到目录,如目录mkdir testmount(先创建好该目录) 挂载:
mount ./test.img /testmount
查看:
df -h
现在我们就把一个空白镜像文件挂载成磁盘。
6.unshare 命令
- 功能:用于在不共享父进程命名空间的情况下运行指定程序。
语法:
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子进程并与父进程隔离:
unshare -u /bin/bash
验证:
hostname test #设置主机名,为test
hostname #查看主机名,并新窗口查看主机名是否一样。
exit #退出子进程
hostname #查看主机名
效果:
7.PID隔离
示例:
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。这样:
如果没有 –fork:
- /bin/bash的 PID 仍然是原命名空间的 PID(非 1),导致新 PID 命名空间无 init 进程,破坏隔离性。
添加 –fork:
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命名空间 的进程信息。
示例(正确用法):
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进程
unshare –mount –fork /bin/bash
创建空白文件完成挂载
dd if=/dev/zero of=data.img bs=8k count=10240 #创建空白文件
mkfs -t ext4 ./data.img #格式化空白文件
完成挂载隔离
mkdir -p test/mt1 #创建目录
mount -t ext4 ./data.img test/mt1 #挂载到目录
df -h #新建窗口,两窗口执行该指令,验证是否完成文件系统隔离
效果: 📌 写给读者的小纸条 “这些指令组合就像厨房里的调味罐——不用记住每一瓶的位置,用的时候拉开抽屉随手拿就好。 建议把本文丢进收藏夹吃灰(偶尔能翻出来用的才是好工具),需要时Ctrl+F一搜,省下的时间够喝杯咖啡啦 ☕”
非常感谢您能耐心读完这篇文章。倘若您从中有所收获,还望多多支持呀!
评论前必须登录!
注册