표준 입력에서 직접 .tar.gz 파일을 생성할 수 있습니까? 또는 이미 gzip으로 압축된 파일을 함께 패키지해야 합니다.

표준 입력에서 직접 .tar.gz 파일을 생성할 수 있습니까? 또는 이미 gzip으로 압축된 파일을 함께 패키지해야 합니다.

제목에 있는 미스터리를 해명하기 위해 필요한 내용을 정확히 말씀드리겠습니다. 현재 다음과 같이 모든 데이터베이스의 예약된 MySQL 백업을 수행하고 있습니다.

mysqldump ... | gzip -c > mysql-backup.gz

괜찮습니다. 하지만 덤프된 데이터를 보거나 단일 데이터베이스를 복원하는 것이 더 쉽기 때문에 각 데이터베이스에 대해 별도의 파일을 만들 의향이 있습니다.

for db in $dbs; do mysqldump ... $db | gzip -c > mysql-backup-$db.gz; done

.tar각 백업의 모든 덤프를 하나의 파일, 즉 모든 덤프가 포함된 데이터베이스 에 저장하고 싶습니다 mysql-backup.tar.gz. .sql그러면 파일을 압축하지 않은 채로 둘 수 있다는 것을 알고 있지만 tar -cz *.sql,1) 대용량 파일을 임시로 저장하지 않아도 되는 방법을 찾고 있어요. 실제로 현재 스크립트에서는 큰 파일이 생성되지 않도록 mysqldump파이프하고 있습니다 .gzip

.tar.gz2) 표준 입력에서 생성하는 비슷한 방법이 있습니까??

3 ) tar -c *.sql.gz?tar -cz *.sql

답변1

나는 당신이 원하는 것을하기 위해 파이썬을 함께 엮었습니다. 그것은 사용한다파이썬 타르 파일라이브러리는 tar 파일에 stdin을 추가한 다음 tar를 살펴보고 eof에서 올바른 크기로 헤더를 다시 작성합니다. 사용법은 다음과 같습니다:

rm -f mytar
for db in $dbs
do mysqldump ... $db | gzip -c |
   tarappend -t mytar -f mysql-backup-$db.gz
done
tar tvf mytar

이것은 tarappend파이썬 스크립트입니다:

#!/usr/bin/python
# concat stdin to end of tar file, with given name. meuh on stackexchange
# $Id: tarappend,v 1.3 2015/07/08 11:31:18 meuh $

import sys, os, tarfile, time, copy
from optparse import OptionParser
try:
    import grp, pwd
except ImportError:
    grp = pwd = None

usage = """%prog: ... | %prog -t tarfile -f filename
Appends stdin to tarfile under the given arbitrary filename.
tarfile is created if it does not exist.\
"""

def doargs():
    parser = OptionParser(usage=usage)
    parser.add_option("-f", "--filename", help="filename to use")
    parser.add_option("-t", "--tarfile", help="existing tar archive")
    (options, args) = parser.parse_args()
    if options.filename is None or options.tarfile is None:
        parser.error("need filename and tarfile")
    if len(args):
        parser.error("unknown args: "+" ".join(args))
    return options

def copygetlen(fsrc, fdst):
    """copy data from file-like object fsrc to file-like object fdst. return len"""
    totlen = 0
    while 1:
        buf = fsrc.read(16*1024)
        if not buf:
            return totlen
        fdst.write(buf)
        totlen += len(buf)

class TarFileStdin(tarfile.TarFile):
    def addstdin(self, tarinfo, fileobj):
        """Add stdin to archive. based on addfile() """
        self._check("aw")
        tarinfo = copy.copy(tarinfo)
        buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
        bufoffset = self.offset
        self.fileobj.write(buf)
        self.offset += len(buf)

        tarinfo.size = copygetlen(fileobj, self.fileobj)
        blocks, remainder = divmod(tarinfo.size, tarfile.BLOCKSIZE)
        if remainder > 0:
            self.fileobj.write(tarfile.NUL * (tarfile.BLOCKSIZE - remainder))
            blocks += 1
        self.offset += blocks * tarfile.BLOCKSIZE
        # rewrite header with correct size
        buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
        self.fileobj.seek(bufoffset)
        self.fileobj.write(buf)
        self.fileobj.seek(self.offset)
        self.members.append(tarinfo)

class TarInfoStdin(tarfile.TarInfo):
    def __init__(self, name):
        if len(name)>100:
            raise ValueError(name+": filename too long")
        if name.endswith("/"):
            raise ValueError(name+": is a directory name")
        tarfile.TarInfo.__init__(self, name)
        self.size = 99
        self.uid = os.getuid()
        self.gid = os.getgid()
        self.mtime = time.time()
        if pwd:
            self.uname = pwd.getpwuid(self.uid)[0]
            self.gname = grp.getgrgid(self.gid)[0]

def run(tarfilename, newfilename):
    tar = TarFileStdin.open(tarfilename, 'a')
    tarinfo = TarInfoStdin(newfilename)
    tar.addstdin(tarinfo, sys.stdin)
    tar.close()

if __name__ == '__main__':
    options = doargs()
    run(options.tarfile, options.filename)

답변2

쉬운 일이 아닙니다. tar파일 내용뿐만 아니라 파일 메타데이터(이름, 타임스탬프, 권한, 소유자 등)도 기록됩니다. 이 정보는 어딘가에서 와야 하며 파이프라인에 상주하지 않습니다.

데이터베이스 덤프를 파일(아마도 관련 데이터베이스 이름을 따서 명명됨)로 압축하고 해당 파일을 tar 아카이브에 추가한 후 다음 데이터베이스로 이동하기 전에 파일을 삭제할 수 있습니다. 이렇게 하면 .gz.tar 파일이 생성되는데, 이는 특이하지만 결코 문제가 되지 않으며 아마도 전체 데이터베이스 덤프를 gzip으로 압축하는 것보다 더 많은 디스크를 사용하지 않을 것입니다(압축 효율이 약간 떨어집니다. 데이터베이스 경계를 ​​넘어 공유할 수 없습니다).

답변3

아니요, 이 기능이 너무 그리워요.Ask Ubuntu에 대한 질문.

아카이브되는 파일이 연관된 파일 시스템 메타데이터가 없는 원시 파일인 경우 tar내부 디렉터리/파일 트리를 구축하는 데 필요한 파일 이름이나 경로가 없습니다(최소한 말하면).

파일 압축/압축 풀기/보관을 위한 특수 라이브러리가 있는 Perl에서 뭔가를 수행할 수 있다고 생각합니다. 이 답변을 최대한 활용할 수 있는지 확인하십시오.Ask Ubuntu에 대한 관련 답변.

답변4

이것이 내가 한 일입니다. tmp 파일을 만든 다음 삭제합니다.

temp=$(mktemp)
trap "rm $temp" EXIT
echo 'blabla' >$temp
tar czf - $temp

관련 정보