タイトルにある謎を解明するために必要な内容を正確に申し上げます。現在、次のようにすべてのデータベースのスケジュールされたMySQLバックアップを実行しています。
mysqldump ... | gzip -c > mysql-backup.gz
大丈夫です。ただし、ダンプされたデータを表示したり、単一のデータベースを復元したりする方が簡単なため、各データベースごとに別々のファイルを作成することになります。
for db in $dbs; do mysqldump ... $db | gzip -c > mysql-backup-$db.gz; done
.tar
各バックアップのすべてのダンプを1つのファイル、つまりすべてのダンプを含むデータベースに保存したいと思いますmysql-backup.tar.gz
。.sql
これにより、ファイルを圧縮せずに残すことができることがわかりますがtar -cz *.sql
、1)大容量ファイルを一時的に保存する必要がない方法を探しています。。実際、現在のスクリプトでは大きなファイルが生成されないようにmysqldump
パイプしています。gzip
.tar.gz
2)標準入力から生成する同様の方法はありますか??
3)tar -c *.sql.gz
?tar -cz *.sql
答え1
私はあなたがしたいことをするためにPythonを一緒に編みました。それを使うPython tarファイルライブラリは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
Pythonスクリプトです:
#!/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