Проверьте, изменено ли содержимое файла или нет, используя Perl

#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 На каждом сервере есть каталог для хранения временных данных. Если вам не разрешено его использовать, вы должны хранить свои данные в базе данных. Или вам нужно создать уникальные ограничения в базе данных, чтобы предотвратить дубликаты. В этом случае вы всегда можете импортировать все, и база данных отклонит уже импортированные значения.