私はこれをStackexchangeに公開しようとしましたが、Linuxに限定されているので、ここで正解を得る可能性が高いと思います。 csvのデータを更新するshスクリプトがあり、shスクリプトで2つの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