はじめに
運営しているサイトで
「毎月送られてくるファイルデータとデータベースに保存してある先月分のデータを付き合わせて差分を同期する」
という運用作業が必要になったので差分を表示するスクリプトを作ってみた。
環境情報
- AWS(Amazon Linux AMI 2018.03.0 (HVM))
- Perl (v5.16.3)
開発
昔から運用業務用のスクリプトはシェルスクリプトかPerlと相場は決まっていて
今回はDB接続が必要だったのでPerlで作成した。
仕様要件としては、
- ファイル内のIDとデータベース内のIDの差分を調べることができる
- 引数でファイルを指定できる
- 差分を標準出力で表示できる
- 想定される差分はファイル側への追加のパターンのみ
と言うことでチャチャッと作っていく。
引数からファイル名を取得する
# 引数を取得
my $file = shift;
# 引数がないときは、使用方法を示して終了
unless ($file) {
die "Usage: $0 file";
}
ファイルデータを読み込む
# ファイルを読み込む
open(my $fh, "<", $file)
or die "Cannot open $file for read: $!";
# ファイルデータを格納
my $files = [];
while (my $line = <$fh>) {
# 改行を取り除く
chomp $line;
push @$files, $line;
}
close $fh;
データベースデータを読み込む
# データベース接続準備
my $dsn = "dbi:mysql:database=xxxxxxxxxx;host=localhost;port=3306";
my $user = "root";
my $password = "";
# データベースハンドルを作成
my $dbh = DBI->connect( $dsn, $user, $password, {
AutoCommit => 0,
PrintError => 0,
RaiseError => 1,
ShowErrorStatement => 1,
AutoInactiveDestroy => 1
})|| die $DBI::errstr;
# データを取得
my $sth = $dbh->prepare("SELECT columns_name FROM table_name;");
$sth->execute();
# 取得したデータを格納
my $dbs = [];
while (my $ary_ref = $sth->fetchrow_arrayref) {
push @$dbs, $ary_ref->[0];
}
# 後始末
$sth->finish;
$dbh->disconnect;
データを突き合わせる
my $is_registered;
for my $data ( @$files ) {
$is_registered = 0;
for my $tmp ( @$dbs ) {
# データが存在したらフラグを立てて離脱
if ( $data eq $tmp ) {
$is_registered = 1;
last;
}
}
# 対象を出力
print "$data\n" if $is_registered eq 0;
}
はい、終了。お疲れ様でした。
あとは毎回エクセルファイルで渡してくるのをcsv形式にしてもらうよう調整してデータ登録もこのスクリプトでできるようにしなきゃ。
以下、全文。
diff_data.pl
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
# 引数の処理
my $file = shift;
# 引数がないときは、使用方法を示して終了
unless ($file) {
die "Usage: $0 file";
}
# ファイルを読み込む
open(my $fh, "<", $file)
or die "Cannot open $file for read: $!";
# ファイルデータを格納
my $files = [];
while (my $line = <$fh>) {
# 改行を取り除く
chomp $line;
push @$files, $line;
}
close $fh;
# データベース接続準備
my $dsn = "dbi:mysql:database=xxxxxxxxxx;host=localhost;port=3306";
my $user = "root";
my $password = "";
# データベースハンドルを作成
my $dbh = DBI->connect( $dsn, $user, $password, {
AutoCommit => 0,
PrintError => 0,
RaiseError => 1,
ShowErrorStatement => 1,
AutoInactiveDestroy => 1
})|| die $DBI::errstr;
# データを取得
my $sth = $dbh->prepare("SELECT columns_name FROM table_name;");
$sth->execute();
# 取得したデータを格納
my $dbs = [];
while (my $ary_ref = $sth->fetchrow_arrayref) {
push @$dbs, $ary_ref->[0];
}
# 後始末
$sth->finish;
$dbh->disconnect;
my $is_registered;
for my $data ( @$files ) {
$is_registered = 0;
for my $tmp ( @$dbs ) {
if ( $data eq $tmp ) {
# データが存在したらフラグを立てて離脱
$is_registered = 1;
last;
}
}
# 対象を出力
print "$data\n" if $is_registered eq 0;
}