루프가 Perl scrpt의 의도대로 작동하지 않는 경우

루프가 Perl scrpt의 의도대로 작동하지 않는 경우

매 시간마다 data.list의 변경 사항을 자동으로 확인하는 Perl 스크립트를 만들려고 합니다. username/project/tota/datas/data.list파일이 있는 위치에 있고 나머지 코드를 실행합니다. 제 경우에는 줄 수를 세어 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.listThank all 에서 변경 사항을 자동으로 검색하는 방법을 찾으면 됩니다.

새로 편집됨: 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
}

문제는 내가 그것을 실행할 때마다, 항상감지된 변경 사항으로 시작그런 다음 no로 들어갑니다.변화 감지됨매 시간마다, 이 부분을 어떻게 바꿀 수 있는지 모르겠어요

답변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있고 이미 배포판용으로 패키지되어 있을 수도 있습니다. 데비안에서는 패키지에 있습니다 libdigest-sha-perl.


왜 Perl에서 이 작업을 필요로 하는지 또는 수행하고 싶은지 잘 모르겠습니다. 매시간 파일이 변경되었는지 확인하고 싶다면 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

관련 정보