あらまし
先日、Jenkins で保存していたビルド成果物がディスク領域を圧迫してしまい、Jenkinsが止まってしまいました。
早急にディスク領域を空けないとプロジェクトに支障をきたしてしまいます。
成果物をfoo.tar.bz2
のように、tar+bzip2形式で保存したので、これをより圧縮率の高いtar+xz形式に変換することで、ディスク領域を空けることができました。
本題
Linuxカーネルのソースコードを使って、実際にやってみましょう。
.tar.bz2の場合
recompress-bz2.sh に tar+bzip2形式のファイルを食わせればOKです。
#!/bin/bash -ue
BZ2=$1
XZ=${1%.bz2}.xz
trap "echo $0 trapped.; rm -f $XZ" 1 2 3 15
if bzcat $BZ2 | xz -v > $XZ
then
trap "echo $0 trapped." 1 2 3 15
rm -f $BZ2
else
rm -f $XZ
fi
$ wget https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.12.tar.bz2
$ ls -lh linux-3.12.tar.bz2
-rw-r--r-- 1 hogefoo hogefoo 87M 11月 4 08:47 linux-3.12.tar.bz2
$ sh recompress-bz2.sh linux-3.12.tar.bz2
100 % 75.2 MiB / 518.8 MiB = 0.145 2.0 MiB/s 4:16
$ ls -lh linux-3.12.tar.*
-rw-r--r-- 1 hogefoo hogefoo 76M 3月 14 01:00 linux-3.12.tar.xz
もとの.tar.bz2
ファイルは消え、.tar.xz
ファイルができています。
容量はざっと 11MB減りました 。
.tar.gzの場合
.tar.bz2の場合とあんまり変わりません。
#!/bin/bash -ue
GZ=$1
XZ=${1%.gz}.xz
trap "echo $0 trapped.; rm -f $XZ" 1 2 3 15
if zcat $GZ | xz -v > $XZ
then
trap "echo $0 trapped." 1 2 3 15
rm -f $GZ
else
rm -f $XZ
fi
$ wget https://www.kernel.org/pub/linux/kernel/v3.0/linux-3.12.tar.gz
$ ls -lh linux-3.12.tar.gz
-rw-r--r-- 1 hogefoo hogefoo 110M 11月 4 08:47 linux-3.12.tar.gz
$ sh recompress-gz.sh linux-3.12.tar.gz
100 % 75.2 MiB / 518.8 MiB = 0.145 2.0 MiB/s 4:13
$ ls -lh linux-3.12.tar.*
-rw-r--r-- 1 hogefoo hogefoo 76M 3月 14 01:17 linux-3.12.tar.xz
こちらは34MB減っています 。
解説
tar形式
そもそも、foo.tar.bz2
というのは、foo.tar
というtar形式のファイルをbzip2で圧縮したファイルです。
tar形式に圧縮機能はなく、コンテナとしてファイルとそのメタ情報を記録する機能しかありません。
なのでbzip2やgzipの圧縮から解いて、ただのtar形式にしてからxzで圧縮すれば、tar.xzの出来上がりです。
tar.bz2やtar.gzからtarへ
bzcat
やzcat
を用いると、 簡単に.tar.bz2 や.tar.gzをtar形式として標準出力に流す ことができます。
$ bzcat foo.tar.bz2 > foo.tar
$ zcat bar.tar.gz > bar.tar
tarからtar.xzへ
xz -
で、 標準入力をxzで圧縮して標準出力に流すことができます 。
$ cat foo.tar | xz - > foo.tar.xz
recompress-bz2.sh
やrecompress-gz.sh
では、-v
を付けて、進捗を表示させています。
tar.bz2やtar.gz から、tar.xzへ
標準出力へtar形式を流す方法と、標準入力をxzで圧縮する方法がわかりました。
あとはくっつけるだけです。
$ bzcat foo.tar.bz2 | xz - > foo.tar.xz
$ zcat bar.tar.gz | xz - > bar.tar.xz
おしまい。
蛇足
拡張子
Bash
の機能を用いて、拡張子の変換を行ってます。
POSIX Shellでできるかどうかは調べてません。
追記 コメント欄より
POSIX シェルでも出来ます!
とのことです。THX! @magicant
GZ=$1
XZ=${1%.gz}.xz
${1%.gz}
は$1
の末尾から.gz
を削った結果を返します。
Ctrl-Cの対応
trap
を用いて、Ctrl-Cで止められた時の処理をしています。
trap "echo $0 trapped.; rm -f $XZ" 1 2 3 15
または
trap "echo $0 trapped.; rm -f $XZ" HUP INT QUIT TERM
第一引数はシグナルを受けたときに実行する処理、
第二引数はシグナルを示しています。
ここでシグナルは番号、名前の両方が使えますが、
OSによって番号がは異なることがあるため、名前を用いた方が移植性が高いようです。
コメント欄参照。 THX! @magicant
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
一般的に、1 2 3 15
をおさえておけばよいそうです。
また、再圧縮が終わってrm -rf $GZ
する前にtrap "echo $0 trapped." 1 2 3 15
として、削除処理上書きして無効にすることで、せっかく出来たtar.xzファイルを削除してしまわないようにしています。
他の方法
tar xvzf
なりtar xvjf
なりで解凍してからtar xvJf
で圧縮することもできますが、
ディスク領域と時間の無駄なのであんまりオススメできません。
参考
trap
については、以下を参考にしました。
シグナルと trap コマンド - UNIX & Linux コマンド・シェルスクリプト リファレンス
#!/bin/bash -ue
については、 @youcune の以下の記事を参考にしました
シェルスクリプトを書くときはset -euしておく
bash
, bzcat
, zcat
, xz
については、man bash
, man bzip2
, man gzip
, man xz
を参考にしました。
おことわり
異常処理とか適当なので、データ消失等の事故については自己責任でおねがいします。
もし危ないところに気づいたら編集リクエストなりコメントなりで御指摘いただけると幸いです。
また、語の統一がかなり適当なので、あとで編集するかもです。
大意は変わらないはずです。
あしからず。