나는 이것을 Stackexchange에 게시하려고 시도했지만 Linux에만 국한된 것이기 때문에 여기에서 정답을 얻을 가능성이 더 높을 것이라고 생각합니다. csv의 데이터를 업데이트하는 sh 스크립트가 있고 sh 스크립트에서 두 csv 파일 간의 데이터를 일치시키는 perl 스크립트($match)를 실행하고 $matches 파일을 일치 결과로 채웁니다. 질문과 관련된 유일한 내용이므로 스크립트 끝 부분의 스니펫만 표시하겠습니다.
#!/bin/sh
export PATH="/opt/bin:/opt/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/sbin:/usr/syno/bin:/usr/local/sbin:/usr/local/bin"
match=/home/perl_experiments/newitems/match.pl
matches=/home/perl_experiments/newitems/matches.txt
/usr/bin/perl $match > $matches
if [[ -s $matches ]] ; then
date >> $log
echo "matches has data." >> $log
$sendmail
else
date >> $log
echo "matches is empty." >> $log
exit
fi
편집: 여기 $match 스크립트가 있습니다.
#!/usr/bin/perl
my @csv2 = ();
open CSV2, "<csv2" or die;
@csv2=<CSV2>;
close CSV2;
my %csv2hash = ();
for (@csv2) {
chomp;
my ($title) = $_ =~ /^.+?,\s*([^,]+?),/; #/ match the title
$csv2hash{$_} = $title;
}
open CSV1, "<csv1" or die;
while (<CSV1>) {
chomp;
my ($title) = $_ =~ /^.+?,\s*([^,]+?),/; #/ match the title
my %words;
$words{$_}++ for split /\s+/, $title; #/ get words
## Collect unique words
my @titlewords = keys(%words);
my @new; #add exception words which shouldn't be matched
foreach my $t (@titlewords){
push(@new, $t) if $t !~ /^(and|the|to|uk)$/i;
}
@titlewords = @new;
my $desired = 5;
my $matched = 0;
foreach my $csv2 (keys %csv2hash) {
my $count = 0;
my $value = $csv2hash{$csv2};
foreach my $word (@titlewords) {
my @matches = ( $value=~/\b$word\b/ig );
my $numIncsv2 = scalar(@matches);
@matches = ( $title=~/\b$word\b/ig );
my $numIncsv1 = scalar(@matches);
++$count if $value =~ /\b$word\b/i;
if ($count >= $desired || ($numIncsv1 >= $desired && $numIncsv2 >= $desired)) {
$count = $desired+1;
last;
}
}
if ($count >= $desired) {
print "$csv2\n";
++$matched;
}
}
print "$_\n\n" if $matched;
}
close CSV1;
~
이제 스크립트를 테스트하기 위해 의도적으로 일치하는 데이터를 2개의 csv에 남겨 두었습니다. 스크립트를 수동으로 실행하면 예상대로 작동하고 $log 파일에 "데이터와 일치"라는 메시지가 표시됩니다. 그러나 crontab에서 실행하면(수동으로 실행하는 것처럼 루트로) $matches-에 데이터가 생성되지 않으며 $log 파일 항목에 "matches isempt"라는 메시지가 표시됩니다.
다음은 확실히 스크립트를 실행하는 내 crontab 항목입니다. 예상한 출력이 생성되지 않습니다.
*/10 09-21 * * 1,2,3,4,5 root /home/perl_experiments/newitems/newitems.sh
제 질문은, 왜 이런 일이 발생하며 crontab 실행이 수동 실행과 동일하도록 무엇을 수정할 수 있습니까?입니다. 이것이 sh 스크립트 내에서 Perl 스크립트를 실행하는 데 문제가 있는 crontab과 관련이 있을 수 있습니까?
내가 말했듯이, 수동으로 실행하면 정확히 내가 기대한 대로 작동하지만, crontab을 실행하면 일치하는 항목이 생성되지 않습니다. 제안을 환영합니다.
답변1
귀하의 Perl 스크립트에는
open CSV2, "<csv2" or die;
...
open CSV1, "<csv1" or die;
이 파일들은 어디에 있나요? cron의 현재 디렉터리는 사용자의 홈 디렉터리입니다. 파일이 "newitems" 디렉터리에 있으면 cd
먼저 해당 디렉터리로 이동해야 합니다.
프로그램의 환경에 대해 다른 가정을 하지 않도록 하세요.
나는 이것이 crontab에서 한 번 활성화할 수 있는 편리한 명령이라는 것을 알았습니다.
#* * * * * { date; pwd; echo "env:"; env; echo "set:"; set; } > ~/cron.env
@Otheus의 좋은 지적:
if ! /usr/bin/perl "$match" > "$matches"; then
status=$?
echo "$match script returned unsuccessfully"
exit $status
fi