#perl
Вопрос:
Я хочу создать скрипт, который может обнаруживать любые изменения, внесенные в файл. Это мой исходный код. Как только я обнаружу изменение, я буду использовать curl
его для загрузки новых данных в онлайн-базу данных.
Приведенный ниже пример является всего лишь онлайн-решением, также приветствуются другие типы поиска.
Что мне нужно в качестве псевдокода:
if (file content changed)
{
#upload data
printf "file content changed, newest data uploaded";
}else{
printf "file content no change";
#do nothing
}
Фактический код, проверяющий, изменилось ли содержимое файла:
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) {
printf "changes were made";
### $curl upload data details here......................
$old_digest = $digest;
$old_mtime = $mtime;
$old_size = $size
}
} else {
printf "no changes were made";
};
sleep 3600; # sleep 1 hour between iterations of the loop
}
Проблема с этим кодом заключается в том, что каждый раз, когда я запускаю этот скрипт, он всегда начинается с того, что были внесены изменения, даже если файл был сохранен нетронутым. Что я должен изменить? Должен ли я исключить время?
Комментарии:
1. Два варианта: предположим, что он не изменился , или сохранен
$old_mtime
,$old_size
и$old_digest
где-то постоянно (например, на диске).2. есть ли способ получить доступ к загруженным данным, можете ли вы получить свои
$old_mtime
,$old_size
, и$old_digest
, и инициализировать их самостоятельно только в том случае, если вы не можете получить доступ к этим данным?3. @ikegami есть другой способ? что ты имеешь в виду, это не изменилось
4. @vanHoesel что ты имеешь в виду ? я могу получить доступ к своим загруженным данным, я могу читать, но не писать для них. я хочу, чтобы что-то произошло только в том случае, если данные были изменены.
5. Да, вы всегда сравниваете с 0/0/пустой строкой при запуске программы. Либо сохраните правильные значения между запусками, либо предположите, что файл не менялся между запусками.
Ответ №1:
Вы можете использовать модуль хранения для сохранения ваших «старых» значений.
Пример:
#! /usr/bin/perl
use strict;
use warnings;
use Storable;
use Digest::SHA qw(sha256_hex);
use Data::Dumper;
$Data::Dumper::Terse = 1;
my $old;
if (-e 'old') {
$old = retrieve ('old');
} else {
$old = {mtime => 0, size => 0, digest => ''};
}
END {
store $old, 'old';
}
print "$: old: ", Dumper ($old);
my $filename = 'data.list';
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}) {
printf "$: changes were maden";
$old->{digest} = $digest;
$old->{mtime} = $mtime;
$old->{size} = $size;
print "$: new: ", Dumper ($old);
} else {
print "$: no changes were maden";
}
} else {
print "$: no changes were maden";
}
Инициализировать data.list
:
$ echo 1 > data.list
Старые значения инициализируются во время первого запуска:
$ ./storable.pl
2605: old: {
'size' => 0,
'mtime' => 0,
'digest' => ''
}
2605: changes were made
2605: new: {
'size' => 2,
'mtime' => 1624266579,
'digest' => '4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865'
}
При повторном запуске старые значения считываются из файла «old».:
$ ./storable.pl
2610: old: {
'size' => 2,
'mtime' => 1624266579,
'digest' => '4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865'
}
2610: no changes were made
Но когда вы изменяете файл, изменение будет обнаружено:
$ echo 2 > data.list
$ ./storable.pl
2615: old: {
'digest' => '4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865',
'mtime' => 1624266579,
'size' => 2
}
2615: changes were made
2615: new: {
'digest' => '53c234e5e8472b6ac51c1ae1cab3fe06fad053beb8ebfd8977b010655bfdd3c3',
'mtime' => 1624266608,
'size' => 2
}
Вместо sleep
этого я бы использовал cron-работу.
Комментарии:
1. привет, могу я узнать, где хранились эти значения? просто любопытно, потому что его пост-это то, чем я тоже занимаюсь
2. Привет, сивинг, спасибо за это, но, похоже, я должен хранить значение у кого-то и каждый раз перечитывать его снова. я не могу хранить значения/файл на облачном сервере
3. @WenhanXiao В файле под названием «старый». Посмотрите на
END
квартал.4. @HelpMeAndroidStudio На каждом сервере есть каталог для хранения временных данных. Если вам не разрешено его использовать, вы должны хранить свои данные в базе данных. Или вам нужно создать уникальные ограничения в базе данных, чтобы предотвратить дубликаты. В этом случае вы всегда можете импортировать все, и база данных отклонит уже импортированные значения.