我尝试将其发布在 Stackexchange 上,但我认为我可能有更多机会在这里得到正确答案,因为它非常特定于 Linux。我有一个 sh 脚本,它更新 csv 中的数据,然后从 sh 脚本中运行 perl 脚本 ($match),该脚本匹配两个 csv 文件之间的数据,并使用匹配结果填充文件 $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 运行时(以 root 身份运行,就像我手动运行它一样),它不会在 $matches- 中生成任何数据,并且 $log 文件条目状态为“matches 为空”。
这是我的 crontab 条目,它肯定会运行脚本,只是不会产生预期的输出:
*/10 09-21 * * 1,2,3,4,5 root /home/perl_experiments/newitems/newitems.sh
所以我的问题是,为什么会发生这种情况,我可以修改什么来确保 crontab 执行与我的手动执行相同?这是否与 crontab 在 sh 脚本内运行 perl 脚本时出现问题有关?
正如我所说,当手动运行时,它完全符合我的预期,但是当运行我的 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