我对这个perl脚本有一个非常奇怪的问题。基本点是有时文件写入/追加不会发生。在程序运行时,要么所有的写入都会发生,要么都不会。这是子程序,有一些注释:
sub process_svs {
my $F;
open($F, '<', $_[0]);
if($log_dups==1) {
open($dfh, '>>',"./duplicates.txt");
}
while (my $line = <$F>) {
chomp $line;
if($line =~ /somepattern/) {
if (! -e "somefile") {
copy("source","dest") or warn ("couldn't copy");
} elsif($log_dups==1) {
system("touch ./duplicates.txt"); # ghetto workaround
print $dfh "./".$_[0]."_files/".$1.",v already exists\n" or die("Couldn't write duplicate"); # problem line
}
}
}
close $F;
}
stdout的print语句总是有效,但如果删除touch ./duplicates.txt
垃圾,则不会向duplicates.txt
写入任何内容。
另一个“奇怪”的事情是,在程序的早期,我使用perl mkdir
创建一个目录,如果程序运行时该目录存在,我不需要解决方法,duplicates.txt写作工作正常。如果我删除目录,并让程序mkdir
,它不起作用。看起来很相关,但我无法弄清楚由于目录和文本文件不在同一个位置,或以任何方式相关,我能想到的。
此外,我已通过调试器运行它,并且可以看到正在执行的写调用,但在写入后立即检查duplicates.txt没有显示任何内容。
非常感谢任何可能的原因。
如果您想查看经过修改但更完整的脚本版本,请访问:
use strict;
use warnings;
use File::Copy;
my $svs = $ARGV[0];
my $rhis_str = system("rhis $svs > ./tmp_history");
my $fh;
my $dfh;
my @versions;
my $all_revs = 0;
my $current_rev = "";
my $log_dups = 0;
sub process_svs {
my $F;
open($F, '<', $_[0]);
if($log_dups==1) {
open($dfh, '>>',"./duplicates.txt");
}
while (my $line = <$F>) {
chomp $line;
if($line =~ /something/) {
if (! -e "something") {
copy("source","dest") or warn ("couldn't copy ");
} elsif($log_dups==1) {
system("touch ./duplicates.txt"); # ghetto workaround
print $dfh "something already exists\n" or die("Couldn't write duplicate");
}
}
}
close $F;
}
for(my $i = 0; $i <= scalar @ARGV; $i++) {
my $arg = $ARGV[$i];
if($arg eq "-a") {
$all_revs = 1;
} elsif($arg eq "-r") {
$all_revs = 0;
$current_rev = $ARGV[$i+1];
} elsif($arg eq "--log-dups") {
$log_dups = 1;
}
}
open($fh, '<','./tmp_history') or die(">>> Failed to open ./tmp_history");;
mkdir "./".$svs."_files";
if($all_revs == 1) {
print ">>> Processing all revisions of ".$svs;
if($log_dups==1) {
print" (and logging duplicates)\n";
}
while(my $line = <$fh>) {
chomp $line;
if ($line =~ /something/) {
push @versions, $1;
}
}
}
system("some_cmd &>/dev/null");
process_svs($svs);
}
答案 0 :(得分:4)
您没有检查您的文件是否已打开。这是一个非常非常基本的错误,你应该立即解决这个问题。在每个or die $!
之后添加open
,或者更好的是use autodie
,它会为您捕获所有IO异常,并为您提供良好,一致的错误消息。
最重要的是,这会告诉你为什么无法打开。 $!
告诉您为什么失败了。你在print
的支票上没有这个。
print $dfh "./".$_[0]."_files/".$1.",v already exists\n" or die("Couldn't write duplicate"); # problem line
您正在检查print
是否失败,但您不包括$!
。要么添加$!
die "Couldn't write to duplicate: $!"
或use autodie
,请删除or die
子句,让autodie处理它。我推荐第二个。
我怀疑您会发现其他内容正在打开和打印之间删除duplicates.txt
。
引起我注意的第二件事就是在这里。
if($log_dups==1) {
open($dfh, '>>',"./duplicates.txt");
}
您正在使用全局变量$log_dups
来决定是否打开文件进行写入(而不是检查文件是否成功)。这应该是一个传递给函数的变量,它只是一个很好的编程实践。稍后您决定是否根据该全局变量打印到$dfh
。
if (! -e "something") {
copy("source","dest") or warn ("couldn't copy ");
} elsif($log_dups==1) {
system("touch ./duplicates.txt"); # ghetto workaround
print $dfh "something already exists\n" or die("Couldn't write duplicate");
}
由于$log_dups
是全球性的,因此可能会在决定打开$log_dups
和写入duplicates.txt
之间改变$log_dups
。为了避免所有这些问题,并使代码更简单,$dfh
应该是传递给函数的参数。
此外,文件句柄duplicates.txt
莫名其妙地是全局的。同样的问题,其他东西可能会关闭它。它也不会在函数结束时自动关闭,这可能会在程序退出之前将写入$dfh
缓冲。 my $rhis_str = system("rhis $svs > ./tmp_history");
应该是一个词汇。
其他问题......
$rhis_str
rhis
将包含./file
计划的退出状态。我不认为这就是你想要的。无论如何你都不会使用这个变量。
无需将open
传递给file
,只需传递$('.validation-summary-errors').append(response.Message.join('<br>'));
即可安全且易于阅读。隐含在当前工作目录中。
如果您修复了这些基本问题并仍然遇到问题,请使用修改后的代码编辑您的问题,我们可以再次查看。