![Perl スクリプトのループが意図したとおりに動作しない場合](https://rvso.com/image/192207/Perl%20%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%97%E3%81%8C%E6%84%8F%E5%9B%B3%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8A%E3%82%8A%E3%81%AB%E5%8B%95%E4%BD%9C%E3%81%97%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88.png)
私は、ファイルがある場所にある data.list の変更を 1 時間ごとに自動的にチェックし username/project/tota/datas/data.list
、残りのコードを実行する Perl スクリプトを作成しようとしています。私の場合は、その中の行数をカウントしdata.list
、CURL を使用してオンライン データベースにアップロードします。
#Look for changes every 6 hours
If (changes to data.list)
{
count number of lines,
upload data
}
else ( no change )
{
do nothing
}
行数を数えてデータをアップロードする部分です。変更を自動的に検索する方法を見つける必要があります。data.list
皆さんありがとう
新しく編集しました: casからこの回答を得ました。
use Digest::SHA qw(sha256_hex);
my $filename = 'username/project/tota/datas/data.list';
my $old_mtime = 0;
my $old_size = 0;
my $old_digest = '';
while(1) { # loop forever
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks) = stat($filename);
if ($mtime != $old_mtime || $size != $old_size) {
# slurp in entire file and get its sha256 hash
local $/;
open(my $fh, "<", $filename) or die "couldn't open $filename: $!\n";
my $digest = sha256_hex(<$fh>);
close($fh);
if ($digest ne $old_digest) {
print "change detected";
$old_digest = $digest;
$old_mtime = $mtime;
$old_size = $size
}
} else {
print "no change detected";
};
sleep 3600; # sleep 1 hour between iterations of the loop
}
これの問題点は、実行するたびに常に変更が検出されたら開始そしてそれは変更が検出されました1時間ごとに、この部分を変更する方法をご存知ですか
答え1
知りたいことだけならもしファイルが変更されたが、正確に知る必要はない何変更があったかどうかを確認する最も簡単な方法は、現在のファイルのハッシュを以前のファイルのハッシュと比較することです。
これをさらに最適化して、最初にファイルのタイムスタンプとファイル サイズを比較することで、コストのかかるハッシュ計算を回避することができます。
例えば、SHA256を使用してダイジェスト::SHA:
use Digest::SHA qw(sha256_hex);
my $filename = 'username/project/tota/datas/data.list';
my $old_mtime = 0;
my $old_size = 0;
my $old_digest = '';
while(1) { # loop forever
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks) = stat($filename);
if ($mtime != $old_mtime || $size != $old_size) {
# slurp in entire file and get its sha256 hash
local $/;
open(my $fh, "<", $filename) or die "couldn't open $filename: $!\n";
my $digest = sha256_hex(<$fh>);
close($fh);
if ($digest ne $old_digest) {
# the file has changed. upload it
#....your curl upload code here...
# don't forget to update the old_* variables
$old_digest = $digest;
$old_mtime = $mtime;
$old_size = $size
}
} else {
# either the file hasn't changed or someone evil has modified it while
# making sure the file size and mtime remains the same.
# you'd need something like Digest::SHA to detect that :-)
};
sleep 3600; # sleep 1 hour between iterations of the loop
}
CPAN からインストールできますDigest::SHA
が、おそらくすでにディストリビューション用にパッケージ化されているでしょう。Debian では、libdigest-sha-perl
パッケージに含まれています。
なぜ Perl でこれを行う必要があるのか、または行いたいのかはわかりません。ファイルが 1 時間ごとに変更されたかどうかをチェックするだけであれば、次のような単純なシェル スクリプトを cron から実行する方がよいでしょう。
#!/bin/bash
# run this as "/path/to/script-name.sh /path/to/data.list"
filename="$1"
checksumfile='/var/tmp/data.list.sha256'
# cd to the directory containing data.list
cd "$(dirname "$filename")"
if [ ! -e "$checksumfile" ] || ! sha256sum --quiet -c "$checksumfile" ; then
# upload your file with curl
# ... your curl code here ...
# generate sha256 checksum file
sha256sum "$(basename "$filename")" > "$checksumfile"
# make sure it's RW by everyone
chmod a+rw "$checksumfile"
fi