GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Ist es möglich, eine .tar.gz-Datei direkt von Stdin zu erstellen? Oder muss ich bereits gezippte Dateien zusammenfügen?

Ich werde Ihnen genau sagen, was ich brauche, um die kryptische Frage im Titel zu klären. Ich erstelle derzeit geplante MySQL-Sicherungen aller meiner Datenbanken mit etwas wie:

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

Das ist in Ordnung, aber ich bin bereit, eine separate Datei für jede einzelne Datenbank zu erstellen, da dies es einfacher macht, einen Blick auf gesicherte Daten zu werfen oder eine einzelne Datenbank wiederherzustellen:

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

Ich möchte alle Dumps für jedes einzelne Backup in einer einzigen .tar speichern Datei, also mysql-backup.tar.gz mit all den gedumpten Datenbanken darin. Ich weiß, dass ich .sql einfach verlassen kann Dateien unkomprimiert und dann tar -cz *.sql , aber 1) Ich suche nach einer Möglichkeit, große Dateien nicht vorübergehend zu speichern . In meinem aktuellen Skript nämlich mysqldump wird in gzip geleitet , sodass keine große Datei erstellt wird.

2) Gibt es eine ähnliche Möglichkeit, wie ich .tar.gz erstellen kann von stdin ?

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

Akzeptierte Antwort:

Ich habe Python zusammengeschustert, um zu tun, was Sie wollen. Es verwendet die Tarfile von Python Bibliothek, um stdin an eine tar-Datei anzuhängen, und sucht dann einfach im tar nach, um den Header mit der richtigen Größe bei eof neu zu schreiben. Die Verwendung wäre:

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

Hier ist das tarappend Python-Skript:

#!/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)

Linux
  1. Wie man Dateien tariert (komprimiert), bestimmte Dateien oder Verzeichnisse ausschließt

  2. Lum – Spalten aus zwei separaten Dateien zusammenführen?

  3. Selbstextrahierende Skripte:Tar -xo und Dd?

  4. Ich muss eine Reihe von Benutzern erstellen?

  5. Wie kann man unter Linux Binärdateien von Textdateien unterscheiden?

So extrahieren oder entpacken Sie tar.gz-Dateien von der Linux-Befehlszeile

So tarieren Sie bestimmte Dateitypen (Erweiterungen) in einem Verzeichnis

Linux-tar-Befehl zum Komprimieren und Extrahieren von Dateien

Extrahieren Sie eine einzelne Datei aus einer riesigen TGZ-Datei

So erstellen Sie eine lokale Tar-Datei aus einem Remote-Verzeichnis

Datei zu tbz-Dateien hinzufügen