我有一个 tarball,它包含的文件没有正确的用户和组所有权。文件是被拥有的jenkins:jenkins
,我希望它们被拥有naftuli:othergroup
。
有没有办法让我就地编辑 tarball,以便它包含的文件归 拥有naftuli:othergroup
?
我面临的问题是,在创建 tarball 时,用户jenkins
没有chown
不同用户和组的权限。在提取时,我将有权创建用户提到的这些文件,因此我需要编辑 tarball 中的用户 ID 和组 ID。
答案1
存档::焦油或类似的软件将是一种方法。
% touch foo
% tar cvf x foo
foo
% tar tvf x
-rw-rw-r-- 1 jdoe12 jdoe12 0 May 6 20:36 foo
% perl -MArchive::Tar -e '$t=Archive::Tar->new;$t->read("x");$t->chown("foo","root");$t->write("y")'
% tar tvf y
-rw-rw-r-- 1 root jdoe12 0 May 6 20:36 foo
%
答案2
您无法在提取时显式更改权限,但可以在创建时将首选身份放入 tarball 中(即使不作为 运行root
)。
tar cvf /tmp/tarball.tar --owner=naftuli --group othergroup files...
如果源系统不知道您的帐户详细信息,您可以在名称后添加首选 uid 和 gid(例如--owner=naftuli:3000
)。
或者,如果您已经有一个 tarball,您可以以您自己的身份提取 jenkins 创建的文件 ( naftuli:othergroup
),并且因为您不是,所以root
这些文件将归您所有。
答案3
Archive::Tar
请注意使用将存档读取到内存中的答案。使用Python的tarfile
模块,可以避免这种情况。不幸的是,我stdin
还没有设法从流媒体中extractfile
尝试寻找。
#!/usr/bin/env python3
import tarfile
import sys
with tarfile.open(name=sys.argv[1], mode="r") as in_tar, \
tarfile.open(fileobj=sys.stdout.buffer, mode="w|") as out_tar:
for member in in_tar.getmembers():
member.uname = member.gname = "root"
if member.isfile():
with in_tar.extractfile(member) as file:
out_tar.addfile(member, file)
else:
out_tar.addfile(member)
更新:以下 Go 程序可以在流上运行:
package main
import (
"archive/tar"
"io"
"log"
"os"
)
func main() {
tr := tar.NewReader(os.Stdin)
tw := tar.NewWriter(os.Stdout)
for {
hdr, err := tr.Next()
if err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
hdr.Uname, hdr.Gname = "root", "root"
if err := tw.WriteHeader(hdr); err != nil {
log.Fatal(err)
}
if hdr.Typeflag == tar.TypeReg {
if _, err := io.Copy(tw, tr); err != nil {
log.Fatal(err)
}
}
}
if err := tw.Close(); err != nil {
log.Fatal(err)
}
}
答案4
如果您使用的是 macOS,其 tar 版本有一个“mtree”扩展可以执行此操作。生成的 tar 文件可以在 Linux 中提取(即,它是可移植的)。
来自 macOS tar 联机帮助页的示例部分:
$ cat input.mtree
#mtree
usr/bin uid=0 gid=0 mode=0755 type=dir
usr/bin/ls uid=0 gid=0 mode=0755 type=file content=myls
$ tar -cvf output.tar @input.mtree
#mtree
输入文件顶部的注释是必需的。还有uname
和gname
选项(而不是uid
/ gid
)用于设置符号名称而不是数值。请参阅man mtree 5
参考资料 获取所有关键字的列表。