1. 什么是 unshare
?
unshare
是 Linux 中的一个命令,用于在新的命名空间中运行程序。命名空间是 Linux 内核提供的一种隔离机制,允许进程组拥有独立的系统资源视图,如进程 ID、网络、挂载点等。unshare
常用于容器技术的底层实现中,帮助创建隔离的环境。
2. 常见的命名空间类型
Linux 支持多种命名空间,每种命名空间隔离不同的资源:
- PID 命名空间:隔离进程 ID。
- Mount 命名空间:隔离文件系统挂载点。
- UTS 命名空间:隔离主机名和域名。
- Network 命名空间:隔离网络接口、IP 地址、路由表等。
- User 命名空间:隔离用户和组 ID。
- IPC 命名空间:隔离进程间通信资源。
- Cgroup 命名空间:隔离控制组(cgroup)视图。
示例 1:创建新的 PID 命名空间
步骤 1:创建新的 PID 命名空间
root@compute01:~# unshare --pid --fork bash
步骤 2:查看进程列表
root@compute01:~# ps -aux | head -n10
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 167080 12288 ? Ss 2024 0:40 /lib/systemd/systemd --system --deserialize 23
root 2 0.0 0.0 0 0 ? S 2024 0:01 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 2024 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 2024 0:00 [rcu_par_gp]
root 5 0.0 0.0 0 0 ? I< 2024 0:00 [slub_flushwq]
root 6 0.0 0.0 0 0 ? I< 2024 0:00 [netns]
root 8 0.0 0.0 0 0 ? I< 2024 0:00 [kworker/0:0H-kblockd]
root 11 0.0 0.0 0 0 ? I< 2024 0:00 [mm_percpu_wq]
root 12 0.0 0.0 0 0 ? S 2024 0:00 [rcu_tasks_rude_]
- 问题:
ps -aux
仍然显示主机上的所有进程,因为/proc
文件系统未隔离。
步骤 3:重新挂载 /proc
文件系统
root@compute01:~# mount -t proc proc /proc
步骤 4:再次查看进程列表
root@compute01:~# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 8160 4308 pts/2 S 14:10 0:00 bash
root 11 0.0 0.0 10732 3664 pts/2 R+ 14:10 0:00 ps -aux
- 结果:只显示当前命名空间中的进程。
示例 2:创建新的 Mount 命名空间
步骤 1:创建新的 Mount 命名空间
root@compute01:~# unshare --mount --fork bash
步骤 2:查看当前挂载点
root@compute01:~# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg0-lv--0 xfs 1.8T 1.3T 516G 72% /
tmpfs tmpfs 1008G 892K 1008G 1% /dev/shm
tmpfs tmpfs 202G 4.3M 202G 1% /run
tmpfs tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs tmpfs 202G 8.0K 202G 1% /run/user/1001
tmpfs tmpfs 202G 8.0K 202G 1% /run/user/0
/dev/sda1 vfat 1.1G 6.1M 1.1G 1% /boot/efi
步骤 3:创建并挂载临时文件系统
root@compute01:~# mkdir /tmp/mnt
root@compute01:~# mount -t tmpfs tmpfs /tmp/mnt
步骤 4:再次查看挂载点
root@compute01:~# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg0-lv--0 xfs 1.8T 1.3T 516G 72% /
tmpfs tmpfs 1008G 892K 1008G 1% /dev/shm
tmpfs tmpfs 202G 4.3M 202G 1% /run
tmpfs tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs tmpfs 202G 8.0K 202G 1% /run/user/1001
tmpfs tmpfs 202G 8.0K 202G 1% /run/user/0
/dev/sda1 vfat 1.1G 6.1M 1.1G 1% /boot/efi
tmpfs tmpfs 1008G 0 1008G 0% /tmp/mnt
- 结果:
/tmp/mnt
挂载点只在当前命名空间中可见。
步骤 5:退出命名空间并验证
root@compute01:~# exit
root@compute01:~# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg0-lv--0 xfs 1.8T 1.3T 516G 72% /
tmpfs tmpfs 1008G 892K 1008G 1% /dev/shm
tmpfs tmpfs 202G 4.3M 202G 1% /run
tmpfs tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda1 vfat 1.1G 6.1M 1.1G 1% /boot/efi
tmpfs tmpfs 202G 8.0K 202G 1% /run/user/1001
tmpfs tmpfs 202G 8.0K 202G 1% /run/user/0
- 结果:退出命名空间后,
/tmp/mnt
挂载点不再可见。
示例 3:创建新的 UTS 命名空间
步骤 1:创建新的 UTS 命名空间
root@compute01:~# unshare --uts --fork bash
步骤 2:查看当前主机名
root@compute01:~# hostname
compute01
步骤 3:修改主机名
root@compute01:~# hostname newhostname
root@compute01:~# hostname
newhostname
- 结果:主机名已修改为
newhostname
,且只影响当前命名空间。
步骤 4:退出命名空间并验证
root@compute01:~# exit
root@compute01:~# hostname
compute01
- 结果:退出命名空间后,主机名恢复为
compute01
。
示例 4:创建新的 Network 命名空间
步骤 1:创建新的 Network 命名空间
root@compute01:~# unshare --net --fork bash
步骤 2:查看网络接口
root@compute01:~# ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
- 结果:只显示
lo
回环接口,其他网络接口被隔离。
步骤 3:退出命名空间并验证
root@compute01:~# exit
root@compute01:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff
- 结果:退出命名空间后,恢复显示所有网络接口。
示例 5:创建新的 User 命名空间
步骤 1:创建新的 User 命名空间
root@compute01:~# unshare --user --map-root-user --fork bash
步骤 2:查看当前用户
root@compute01:~# id
uid=0(root) gid=0(root) groups=0(root)
- 结果:当前用户在命名空间中拥有 root 权限。
步骤 3:退出命名空间并验证
root@compute01:~# exit
root@compute01:~# id
uid=1000(user) gid=1000(user) groups=1000(user)
- 结果:退出命名空间后,恢复为普通用户权限。
总结
通过以上测试示例,你可以清晰地看到 unshare
命令如何创建和隔离不同的命名空间:
- PID 命名空间:隔离进程视图,需要重新挂载
/proc
文件系统。 - Mount 命名空间:隔离文件系统挂载点,挂载操作只影响当前命名空间。
- UTS 命名空间:隔离主机名和域名。
- Network 命名空间:隔离网络接口、IP 地址和路由表。
- User 命名空间:隔离用户和组 ID。