更改 tarball 中文件的用户 ID 和组 ID 所有权?

更改 tarball 中文件的用户 ID 和组 ID 所有权?

我有一个 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输入文件顶部的注释是必需的。还有unamegname选项(而不是uid/ gid)用于设置符号名称而不是数值。请参阅man mtree 5参考资料 获取所有关键字的列表。

相关内容