我有一个 tarball,其中包含许多带有 root:root 所有者和/或特殊设备 inode 的文件。cpio
创建 cpio 存档时仅接受文件系统中存在的路径。我不想sudo
将 tar 转换为 cpio,同时我想保留所有权限、所有者和特殊 inode。
有一些干净的方法来处理这个问题吗?
编辑1:
我相信这fakeroot
可以被视为某种干净的方式。然而它并没有按预期扩展 - 速度差异接近 1,000 倍:
[user@computer root]$ ls -l ../fanbox.tar
-rw-rw-r-- 1 user user 56555520 May 22 03:33 ../fanbox.tar
[user@computer root]$ time tar -x --delay-directory-restore -f ../fanbox.tar
tar: dev/null: Cannot mknod: Operation not permitted
tar: dev/random: Cannot mknod: Operation not permitted
tar: dev/urandom: Cannot mknod: Operation not permitted
tar: Exiting with failure status due to previous errors
real 0m0.255s
user 0m0.062s
sys 0m0.193s
[user@computer root]$ rm -rf *
[user@computer root]$ time fakeroot tar -x --delay-directory-restore -f ../fanbox.tar
real 3m49.381s
user 0m0.812s
sys 0m2.760s
[user@computer root]$
根据time
命令的输出,我猜这是因为fakeroot
和之间的通信faked
。
作为参考,当我在脚本中fakeroot
更改时,2M tarball 和 50M tarball 之间没有太大区别。sudo bash
而且我认为问题在于 tarball 中的文件数量,而不是大小:我在包含两个 5M 二进制文件的 ~10M tarball 上使用了相同的脚本,并且脚本并不那么慢。
答案1
您可以使用fakeroot
。顾名思义,它通过使用LD_LIBRARY_PATH
/LD_PRELOAD
库包装器拦截多个系统调用来伪造 root 用户,让进程相信它正在以 root 身份运行。创建它的目的是为了构建和打包应用程序而无需 root,包括使用make install
通常以 root 身份运行的应用程序。它特别适合创建档案。
在此期间,分叉守护进程faked
将运行以记住所有伪造的文件所有权或子进程认为它们创建的特殊文件的信息。因此,所有操作都必须在同一个“实例”中完成,否则faked
将退出并忘记它所记住的内容。
$ fakeroot
# tar xf ...
# find foo ... | cpio -o ...
# exit
$
faked
显示的交互的其他示例:
$ mknod /tmp/vaporware b 8 0
mknod: /tmp/vaporware: Operation not permitted
$ fakeroot
# mknod /tmp/vaporware b 8 0
# ls -l /tmp/vaporware
brw-r--r-- 1 root root 8, 0 May 18 08:33 /tmp/vaporware
# exit
$ ls -l /tmp/vaporware
-rw-r--r--. 1 user user 0 May 18 08:33 /tmp/vaporware
答案2
尝试使用 bsd tar (不是 GNU tar)——魔法@
就是在你的 tarball 文件名之前加上一个:
bsdtar --format=cpio -cf - @root.tar.gz > root.cpio
答案3
您可以将其用作lxc-usernsexec
提取和重新创建存档的环境。
lxc-usernsexec
mkdir tmp
cd tmp
tar xf ../archive.tar
find . -print0 | cpio -0o > ../archive.cpio
exit
这假设您已正确设置 Linux 容器,以便$HOME/.config/lxc/default.conf
存在(并且/etc/subuid
设置/etc/subgid
正确)。欲了解更多信息,请参阅
https://wiki.debian.org/LXC#Unprivileged_container
关于 Debian Buster 的说明:
$ lxc-usernsexec
Failed to find subuid or subgid allocation
这似乎是一个错误,但以下脚本修复了此问题:
#!/bin/bash
ARGS=()
while read -ru6 what equals rest
do
[ ".$what" = ".lxc.idmap" ] || continue
[ ".$equals" = ".=" ] || continue
ARGS+=(-m "${rest// /:}")
done 6<"$HOME/.config/lxc/default.conf"
exec /usr/bin/lxc-usernsexec "${ARGS[@]}" -- "$@"