例えばレンタルサーバ等でWEBサイトを運用していたりすると、ドメインごとにディレクトリを分けてVirtualHost設定で複数WEBサイトを立ち上げるというケースがしばしばある。とくに小規模なサイトだと、商用環境とステージング環境、開発環境とかをそれぞれ別ディレクトリにしてサブドメインで仮想化しているというケースは多いのではないだろうか。
そういうケースで、それぞれのディレクトリ内のファイルやサブディレクトリの構成は原則的に一緒なんだけど、ホントに同一構成になっているのか、ディレクトリ間の構成を比較したい時がある。
まぁ、最適解としては、比較元となるディレクトリの構成全体をgithubのリポジトリ化しておくことだ。そうしておけば、git diff
で差分チェック、git pull
でコンテンツ同期ということがお手軽にできるようになる。
しかしWEBサイト等の実際の運用を行っている場合、運営側がアップロードした画像ファイル等のアプリケーションに関わらないリソースは.gitignore
でリポジトリの管理対象外にしていることが多く、それらのリソースを含めた純粋な構成比較をしようとするとgitコマンドだけでは完結できない。
そこで、2つのディレクトリ間の構成内容を再帰的に比較して、差分があればその内容を出力してくれるBash関数を作ってみた。
# Checksum for comparing file structure between directories
#
# @param {string} directory1(path from current dir)
# @param {string} directory2 (path from current dir)
function dirsum() {
if [ $# -ne 2 ]; then
echo "Specify the directory to compare." 1>&2
else
CURRENT=$(pwd)
if [ -d $1 ]; then
cd $1
FILES1=$(find . | wc -l)
CHKSUM1=$(find . | env LC_ALL=C sort | md5sum -b) # easily check
# CHKSUM1=$((find . -type f -exec md5sum -b {} \; && find .) | env LC_ALL=C sort | md5sum -b) # detailed check
echo "Checksum hash: $CHKSUM1 Total files found: $FILES1 <- Dir: $1"
else
CHKSUM1=""
echo "Directory: $1 does not exist."
fi
cd $CURRENT
if [ -d $2 ]; then
cd $2
FILES2=$(find . | wc -l)
CHKSUM2=$(find . | env LC_ALL=C sort | md5sum -b) # easily check
# CHKSUM2=$((find . -type f -exec md5sum -b {} \; && find .) | env LC_ALL=C sort | md5sum -b) # detailed check
echo "Checksum hash: $CHKSUM2 Total files found: $FILES2 <- Dir: $2"
else
CHKSUM2=""
echo "Directory: $2 does not exist."
fi
cd $CURRENT
if [ -n "$CHKSUM1" -a -n "$CHKSUM2" ]; then
if [ "$CHKSUM1" = "$CHKSUM2" ]; then
echo "Checksum hash matched."
else
echo "Checksum hash is different."
diff -r $1 $2
fi
fi
fi
}
alias dirsum=dirsum
alias dsum=dirsum
この処理では# easily check
でサブディレクトリ名とファイル名の構成が一致しているかの簡易的なチェックしかしていない。もしファイル内容まで含めた差分を検証したい場合は、# easily check
の行をコメントアウトして、# detailed check
の行を有効にすることで対応できる。ただし、検証するディレクトリ内のファイル数が多いと詳細チェックにはかなりの時間がかかるので、注意が必要だ。
さて、上記のBash関数を.bashrc
に追加して反映させると、dirsum
コマンド(ショートハンドのdsum
でもOK)で2つのディレクトリ間の差分を検証できるようになる。
$ dsum www_production www_staging
Checksum hash: 51e38a180b74829e7cb97a7bada2a2a9 *- Total files found: 8694 <- Dir: www_production
Checksum hash: 51e38a180b74829e7cb97a7bada2a2a9 *- Total files found: 8694 <- Dir: www_staging
Checksum hash matched.
$ dsum www_production www_staging
Checksum hash: 51e38a180b74829e7cb97a7bada2a2a9 *- Total files found: 8694 <- Dir: www_production
Checksum hash: de8161f8f26e014ce7bf7b02ef5845e3 *- Total files found: 8693 <- Dir: www_staging
Checksum hash is different.
www_production/assets/db-backup のみに存在: My_Site_2019_01_11_1547181637_206b5af_wpdb.zip
例えば、差分があった場合に担当者へメールする等の処理を追加し、cronで定期的に差分検証するようにすれば、WEBサイトの改竄検知にも使えるかもしれない。