システムの開発や検証を進めていく中で、ログや一時ファイルが大量に蓄積されていくのが常でした。手動での圧縮や削除は時間の無駄であり、運用中のタスクに組み込むにはある程度汎用性と安全性を備えたスクリプトが必要だと感じていました。
そこで、自分の開発環境で実際に使うことを前提に、任意のファイルやディレクトリを自動的に圧縮し、必要に応じて削除まで行う汎用スクリプトを作成しました。
この記事では、そのスクリプトの構成や設計方針、実行方法までを具体的に解説していきます。
自動圧縮スクリプトの概要と役割
日々の開発作業や検証作業を行っていると、ログファイルや一時ディレクトリが大量に生成され、定期的な整理が必要になります。これらを手動で圧縮・削除する作業は時間と労力を奪うため、自動化によって大幅な効率化が期待できます。
本記事では、私自身が開発環境での運用効率を上げるために作成した、自動圧縮スクリプトの設計とその目的、活用方法について解説します。
圧縮処理にはzstd形式を採用し、ログ出力やエラーハンドリングにも対応しているため、システム運用の一部としても実用的に利用できます。
自動圧縮スクリプトの目的
圧縮スクリプトを作成した背景には、開発中に発生する多量のログファイルやテンポラリデータの存在があります。
特に複数のスクリプトやアプリケーションをテストしている環境では、ディスク容量を圧迫し、パフォーマンス低下やファイル断片化の要因にもなりかねません。 このスクリプトの目的は、単にファイルを圧縮するだけではなく、以下のようなニーズに応えることです。
目的
- 任意のファイルまたはディレクトリを対象とした圧縮処理
- 圧縮後に元ファイルを削除するか保持するかを選択可能
- cronなどと連携し、定期的な運用処理に組み込み可能
- エラー発生時にもログで追跡できる堅牢な構成
このように、現場の実運用を強く意識した設計思想に基づいています。
スクリプトの特長と設計方針
このスクリプトの設計には、次のような方針を採用しています。用途をログファイルに限定せず、任意のファイル・ディレクトリに対応しているため、アーカイブやバックアップ処理にも応用可能です。
方針
- 対象ファイル・出力先・モード(削除 or 保持)を引数で指定
- 圧縮にはzstdを使用し、高速かつ高圧縮率を実現
- 圧縮レベルを環境変数で制御できる柔軟性
- 一時ファイルや出力ファイルの存在チェック・整合性検証を内蔵
特に安全性を重視し、以下のような保護ロジックも実装しています:
対策内容 | 説明 |
---|---|
再帰圧縮の防止 | 出力先がソースパス配下である場合はエラー終了 |
不正な出力先の排除 | ディレクトリパスが出力先に指定された場合は異常終了 |
圧縮レベルの検証 | 1〜20以外の圧縮レベル指定はエラー扱い |
出力ファイルの上書き制御 | 同名ファイルが存在する場合は削除してから再出力 |
これらの要素によって、実行時の安全性とトラブル時の保守性が確保されており、開発者・管理者双方の運用負担を大きく軽減する構成となっています。
スクリプト構造と設計要素
この自動圧縮スクリプトは、日常の開発業務において即戦力となるよう設計されています。複数のファイル形式や実行環境に柔軟に対応できるよう、構造は極力シンプルかつ汎用性を重視したものとなっています。
ここでは、スクリプトを構成する要素を理解するために、事前に必要となる環境や定義済みの変数、内部関数の概要について解説します。
スクリプトの前提条件と依存関係
このスクリプトを正しく動作させるためには、いくつかの前提となる環境と依存ツールが必要です。まず、共通のログ出力処理を行うために
logger.shrc と
utils.shrc の読み込みが必要です。これらは共通のログ出力関数やエラー処理、文字コード設定処理などを含んでいます。
また、圧縮処理には zstd コマンドが使用されているため、対象サーバーに以下のパッケージがインストールされている必要があります。
dnf install -y zstd
事前に環境変数 TMP_PATH が有効であることも重要です。一時ファイルの生成や処理状況ファイルの保存先としてこの変数を利用しています。
使用される変数と引数一覧
スクリプト内では、実行にあたって以下の変数や引数が使用されています。すべての処理は、getoptsを用いたコマンドライン引数から取得される形式となっています。
項目 | 内容 | 補足 |
---|---|---|
src_path | 圧縮対象のファイルまたはディレクトリ | -s オプションで指定 |
dst_file | 出力先となる.zstファイルのフルパス | -d オプションで指定 |
mode | 0=保持 / 1=削除 | -m オプションで指定 |
ZSTD_LEVEL | 圧縮レベル(1〜20) | 環境変数で制御可能 |
tmp_tar | 中間tarファイルの一時保存パス | 内部で自動生成 |
これらの変数に対してバリデーションを行い、未定義・不正な形式・ディレクトリの階層関係などを厳密にチェックします。
実装されている関数の解説
このスクリプトにはいくつかの独自関数が定義されており、それぞれに役割があります。以下に主要な関数の概要を示します。
関数名 | 役割 |
---|---|
checkArgs | 入力引数と環境条件の整合性チェック |
usage | 使い方を標準出力へ表示(エラー時や不正オプション時) |
terminate | スクリプト終了時の一時ファイル削除処理 |
特に checkArgs は中心的な関数であり、存在しないファイルや出力先がディレクトリになっていないか、削除モード時に再帰圧縮となる危険がないかなど、実行前にすべてチェックしています。
また trap によってスクリプトが終了した場合でも、一時的に作成された .tar ファイルを安全に削除する設計となっています。
trap 'terminate; [ -f "$tmp_tar" ] && rm -f "$tmp_tar"' 0 1 2 3 15
このように、単純な処理でありながら、実運用で想定されるエラーや事故を事前に防止できる構造を意識しています。
自動圧縮スクリプトの導入手順
ここからは、自動圧縮スクリプトを実際に導入して運用するための具体的な手順を解説します。ファイルの配置先や権限の考慮点、実行オプションの指定方法、さらにzstd圧縮時のパフォーマンスやファイル処理の挙動についても触れていきます。
前提となる実行環境
Beエンジニアでシェルスクリプトを実行する環境は下記の通りとします。
実行環境
BASE_DIR(任意のディレクトリ)
- scripts
- bin(実行スクリプト格納領域)
- <<各種実行スクリプト>>.sh (実行ファイル)
- com(共通スクリプト格納領域)
- logger.shrc(共通ログ出力ファイル)
- utils.shrc(共通関数定義ファイル)
- etc(設定ファイル等の格納領域)
- infraMessage.conf(メッセージ定義ファイル)
- log(スクリプト実行ログの格納領域)
- スクリプト名.log
- tmp(テンポラリ領域)
- rep(レポート出力領域)
- bin(実行スクリプト格納領域)
汎用Zstandard圧縮スクリプト
以下は、任意のファイルやディレクトリを対象にzstd形式で圧縮し、必要に応じて元ファイルを削除できる汎用スクリプトです。cronやlogrotateと連携した定期処理にも組み込みやすく、開発・検証環境を問わず幅広く活用できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
#!/bin/sh #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # # compress.sh # ver.1.3.0 2025.07.25 # # Usage: # sh compress.sh -s <src_path> -d <dst_file> -m <mode> # # Description: # 任意のファイル/ディレクトリをzstd形式で圧縮する汎用スクリプト # - モード: 圧縮後に元データを削除(1)または保持(0) # - ログ出力対応(logger.shrc 準拠) # # 使用例: # sh compress.sh -f /var/log/hoge.log -t /tmp/hoge.zst -m 1 # #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # <変更履歴> # Ver. 変更管理No. 日付 更新者 変更内容 # 1.0 〇〇〇〇〇 20xx/xx/xx Bepro 初版 #_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ # ------------------------------------------------------------------ # 初期処理 # ------------------------------------------------------------------ . "$(dirname "$0")/../com/logger.shrc" . "$(dirname "$0")/../com/utils.shrc" setLANG utf-8 # ------------------------------------------------------------------ # variables (変数の宣言領域) # ------------------------------------------------------------------ scope="var" # 圧縮レベル指定(デフォルト: 9) ZSTD_LEVEL=${ZSTD_LEVEL:-9} # Initialization src_path="" dst_file="" mode="" # ---------------------------------------------------------- # functions # ---------------------------------------------------------- terminate() { if [ -f "$status_file" ]; then rm -f "$status_file" fi } # ---------------------------------------------------------- # Check the validity of the argument. # ---------------------------------------------------------- # param 1 src_file or directory # param 2 dst_file # param 3 mode 0:do nothing 1:remove # return N/A # ---------------------------------------------------------- checkArgs() { if [ -z "$1" ] || [ -z "$2" ]; then logOut "ERROR" "Incorrect number of arguments." exitLog 2 fi logOut "DEBUG" "arg1 is [ $1 ]." if [ ! -e "$1" ]; then logOut "ERROR" "Not found such file or directory [ $1 ]." exitLog 2 fi logOut "DEBUG" "arg2 is [ $2 ]." if echo "$2" | grep -q '/$'; then logOut "ERROR" "[ $2 ] directory is set as an output file." exitLog 2 fi if [ ! -e "${2%/*}" ]; then logOut "ERROR" "Not found such file or directory [ ${2%/*} ]." exitLog 2 fi if [ -f "$2" ]; then rm -rf "$2" logOut "INFO" "Removed the [ $2 ] because the same name dst file exist." fi # Check mode. logOut "DEBUG" "arg3 is [ $3 ]." if echo "$3" | grep -Eq "[^01]"; then logOut "ERROR" "An unexpected value [ $3 ]." exitLog 2 fi # Check directory parent-child relationship. abs_src=$(cd "$(dirname "$1")" && pwd)/$(basename "$1") abs_dst_dir=$(cd "$(dirname "$2")" && pwd) abs_dst="$abs_dst_dir/$(basename "$2")" if [ "$3" -eq 1 ] && echo "$abs_dst" | grep -q "^$abs_src"; then logOut "ERROR" "Output file is under source path (recursive compression not allowed)." exitLog 2 fi # 圧縮レベルの範囲チェック(1~19推奨) if ! echo "$ZSTD_LEVEL" | grep -Eq '^[1-9]$|^1[0-9]$|^20$'; then logOut "ERROR" "ZSTD_LEVEL must be between 1 and 20. [ current: $ZSTD_LEVEL ]" exitLog 2 fi } # ---------------------------------------------------------- # how to use. # ---------------------------------------------------------- # return N/A # ---------------------------------------------------------- usage() { cat <<EOUSAGE ----------------------------------------------------------------- Usage: $0 -s <src_path> -d <dst_file> -m <mode> Options: -s src_path : 圧縮対象のファイルまたはディレクトリ(必須) -d dst_file : 出力先のファイル名(必須・.zst拡張子が推奨) -m mode : モード(0=保持 / 1=削除) ----------------------------------------------------------------- EOUSAGE } # ---------------------------------------------------------- # pre-process # ---------------------------------------------------------- step="pre" # Get the value from the argument. while getopts s:d:m: opts; do case $opts in s) src_path=$OPTARG ;; d) dst_file=$OPTARG ;; m) mode=$OPTARG ;; *) logOut "ERROR" "Illegal option." usage exitLog 2 ;; esac done startLog logOut "INFO" "args: [ $* ]" trap "terminate" 0 1 2 3 15 mode=${mode:-"0"} # Check the validity of the argument. checkArgs "$src_path" "$dst_file" "$mode" case "$os" in AIX) TAR="/usr/bin/tar" ;; Linux|FreeBSD) TAR="/bin/tar" ;; *) TAR="$(command -v tar)" ;; esac # Change current directory. cd "${src_path%/*}" || exit 1 # ---------------------------------------------------------- # main-routine # ---------------------------------------------------------- step="main" # 一時ファイル作成 status_file="$TMP_PATH/compress.status.$$" tmp_tar="$TMP_PATH/tmp_compress_$$.tar" trap 'terminate; [ -f "$tmp_tar" ] && rm -f "$tmp_tar"' 0 1 2 3 15 # tarで一時ファイルに書き出し $TAR cf "$tmp_tar" "./${src_path##*/}" tar_rc=$? # zstdで圧縮(tar成功時のみ) if [ "$tar_rc" -eq 0 ]; then zstd -${ZSTD_LEVEL} -T0 -o "$dst_file" "$tmp_tar" zstd_rc=$? rm -f "$tmp_tar" else zstd_rc=1 fi # 成否判定 if [ "$tar_rc" -eq 0 ] && [ "$zstd_rc" -eq 0 ]; then logOut "INFO" "Succeeded in compression [ $dst_file ]." else logOut "ERROR" "Failed to compression [ $dst_file ]." rm -f "$dst_file" exitLog 2 fi # モードに応じて元ファイル削除 if [ "$mode" -eq "1" ]; then rm -rf "$src_path" fi # ---------------------------------------------------------- # post-process # ---------------------------------------------------------- step="post" exitLog 0 |
共通ログ出力関数(logger.shrc)、共通ユーティリティ関数(utils.shrc)を前提とした構成となっているため、実行前にこれらの読み込み設定もご確認ください。
スクリプトの配置と権限設定
スクリプトは、他の管理系シェルスクリプト群と統一的に扱えるよう、適切なディレクトリに配置することを推奨します。下記は想定されるディレクトリ構成の例です。
ディレクトリ | 用途 |
---|---|
/home/bepro/projects/scripts/bin | 実行スクリプト格納場所 |
/home/bepro/projects/scripts/com | 共通ライブラリ(logger.shrcなど) |
/home/bepro/projects/scripts/tmp | 一時ファイル格納用 |
配置後は、以下のコマンドで実行権限を付与してください。
chmod +x /home/bepro/projects/scripts/bin/compress.sh
必要に応じてスーパーユーザー権限での実行も検討します。
スクリプトの実行方法とモード指定
スクリプトは、
-s に対象ファイルまたはディレクトリ、
-d に出力先ファイル、
-m に削除フラグ(0または1)を指定して実行します。
以下は保持モード(元ファイルを残す)の例です。
sh compress.sh -s /var/log/hoge.log -d /tmp/hoge.zst -m 0
元ファイルを削除する場合は -m 1 を指定します。
sh compress.sh -s /var/log/hoge.log -d /tmp/hoge.zst -m 1
どちらのモードでも、圧縮前に出力先ファイルが存在していれば自動的に削除されます。また、出力先がソースディレクトリ配下にある場合はエラーで終了します。
zstd圧縮レベルと一時ファイル処理の動作仕様
スクリプトは、圧縮前に中間ファイル( .tar)を一時的に作成し、それをzstdで圧縮する形式です。これにより複数ファイルを含むディレクトリもまとめて圧縮可能となります。
/home/bepro/projects/scripts/tmp/tmp_compress_12345.tar
この一時ファイルは処理完了後に自動的に削除され、圧縮失敗時も残りません。
圧縮レベルは環境変数 ZSTD_LEVEL によって制御できます。標準では9に設定されていますが、任意に変更可能です。
export ZSTD_LEVEL=19
圧縮レベルは 1〜20 の範囲で指定可能ですが、パフォーマンスと圧縮率のバランスを考慮すると、9〜15程度が推奨です。
また、スクリプト実行時には trap 処理が有効となっており、強制終了された場合でも .tar 一時ファイルは安全に削除されます。
このように、安全性と運用性を両立した仕組みによって、定期処理や手動圧縮などさまざまな場面で安心して活用できるスクリプトとなっています。
実運用における活用例と応用展開
この自動圧縮スクリプトは、単なる手動実行ツールとしてだけでなく、運用現場での定期処理やエラー監視の一部として組み込むことが可能です。ここではlogrotateやcronとの連携による活用例や、ディレクトリごとの定期バックアップ、エラー処理ログの可視化といった実践的な応用例をご紹介します。
ログローテート後の自動圧縮への応用
Linuxシステムでは、 logrotate によってログを日次や週次で分割・退避する運用が一般的です。自動圧縮スクリプトをこの処理の直後に組み合わせることで、ログファイルを不要に保持することなく、圧縮して退避できます。
以下は logrotate の postrotate セクションでスクリプトを呼び出す例です。
/var/log/hoge.log {
daily
rotate 7
missingok
notifempty
postrotate
/home/bepro/projects/scripts/bin/compress.sh -s /var/log/hoge.log.1 -d /tmp/hoge.log.1.zst -m 1
endscript
}
このように連携させることで、ログローテート直後に古いログを即座に圧縮・削除でき、ディスク使用量の抑制に役立ちます。
logrotateとの機能的な違い
logrotateという仕組みがLinuxには標準搭載されており、ログファイルのローテートや圧縮、世代管理などを自動で行うことができます。しかしこのスクリプトは、logrotateではカバーしきれない運用ニーズを補う目的で設計しています。
logrotateは通常 /var/log/ 配下のログファイルなど、あらかじめ定義された対象に対して設定ファイルベースで動作します。そのため、アプリケーションが吐き出す中間ファイルや、開発中に発生する作業ログ、CSVやバックアップファイルなどの圧縮には不向きです。また、圧縮形式はデフォルトでgzipとなっており、圧縮率や速度の調整も限定的です。
それに対して本スクリプトは、任意のファイルやディレクトリを対象に、zstd形式による高速かつ高圧縮な処理を行えるよう設計しています。圧縮レベルも環境変数で制御可能であり、cronやバッチから直接呼び出すことができるため、柔軟な運用が可能です。
以下に、logrotateとの違いを整理した比較表を掲載します。
比較項目 | logrotate | 本スクリプト |
---|---|---|
対象 | /var/log配下のログが中心 | 任意のファイル・ディレクトリ |
圧縮形式 | gzip(zstdは別途設定要) | zstd(レベル制御可) |
実行方式 | 設定ファイル+自動実行 | コマンド+引数で直接実行 |
主な用途 | ログファイル管理 | ログ以外も含めた柔軟な圧縮 |
このように、logrotateとは用途も思想も異なるため、補完的に併用することで幅広い圧縮・保守業務に対応できるようになります。
定期バックアップやデータ退避の自動化
cronなどのスケジューラを用いることで、特定ディレクトリを日次や週次で自動圧縮し、バックアップ用ストレージや退避先ディレクトリへ保存する運用も実現可能です。
以下は、毎日3時に /home/user/workdir/ を圧縮して /backup/ に保存するcron設定の例です。
0 3 * * * /home/bepro/projects/scripts/bin/compress.sh -s /home/user/workdir -d /backup/workdir_$(date +\%F).zst -m 0
このようにcronと組み合わせることで、システム運用中の一部として圧縮処理を完全自動化することが可能です。
エラー処理とログ出力による保守性の向上
スクリプトは
logger.shrc と連携しており、INFO・DEBUG・ERRORレベルでのログ出力に対応しています。これにより、圧縮成功・失敗、入力エラー、削除処理などの履歴をすべてログファイルに記録することができ、トラブル発生時の原因特定が容易になります。
たとえば、圧縮対象が存在しない場合や出力ファイルが誤ってディレクトリになっていた場合には、以下のようなログが出力されます。
[ERROR] Not found such file or directory [ /var/log/not_exist.log ]
[ERROR] [ /tmp/ ] directory is set as an output file.
また、処理成功時には以下のようなログが記録されます。
[INFO] Succeeded in compression [ /tmp/archive.zst ]
これにより、定期処理としてcronなどで実行する場合でも、後からログを確認するだけで処理成否を把握することができます。
保守・運用フェーズでは、このようなログ出力の仕組みがあることで、人的トラブル対応の時間を大幅に短縮できます。
アーカイブの解凍方法について
このスクリプトで作成されるファイルは、
.tar でまとめた内容を
.zst で圧縮した形式となっています。そのため、解凍には
unzstd で展開した後に
tar で中身を取り出すという手順が必要です。
以下がその手順です。
.zst を .tar に展開します
unzstd archive.zst
展開された .tar を解凍します
tar -xf archive.tar
一行で完結させたい場合は、以下のコマンドで .zst ファイルを直接解凍できます。
zstd -d --stdout archive.zst | tar -xf -
この方法で、圧縮時と同じディレクトリ構造でファイルを復元することができます。