使用 Perl 将文本文件不完整地移动到 cifs 挂载点

Text file is moved incompletely to cifs mountpoint with Perl

好吧,这是我很久以来遇到的最奇怪的文件系统相关问题。

, that basically connects on a remote imap server, downloads emails, marks them as read, rip-off trash to download only .txt and .xml files. If .txt use Text::Unaccent 删除重音符号。

这是在 imap 远程文件夹与此服务器上本地 cifs 安装文件夹的一对一关系上完成的。删除 imap 下载和强调处理工作正常。

我的问题是:如果我下载文件、处理重音并将其移动到 cifs 安装目录,文件会被盗用(最后 4 到 10K 丢失)。如果我将它移动到同一台机器上的另一个分区,文件将以正常的方式移动(相同 md5sum,相同的文件大小,diff 没有发现任何变化)。

删除重音并移动文件的代码块:

      #If file extension = .txt
      if ("$temp_dir/$arquivo" =~ /txt$/i){

         #Put file line by line inside array
         open (LEITURA, "$temp_dir/$arquivo");
         @manipular = <LEITURA>;
         close LEITURA;

         #Open the same file to writing with other filehandler
         open (ESCRITA, ">", "$temp_dir/$arquivo");
         foreach $manipula_linha (@manipular){
           # Removes & and accents
           $manipula_linha =~ s/\&/e/g;
           $manipula_linha = unac_string("UTF-8", $manipula_linha);
           print ESCRITA $manipula_linha;
         };
      };

      # copy temp file to final destination. If cifs = crash
      # move also does not work...
      copy   "$temp_dir/$arquivo", "$dest_file";
      unlink "$temp_dir/$arquivo";

Cifs 版本:

[root@server mail_downloader]# modinfo cifs
filename:       /lib/modules/2.6.18-409.el5.centos.plus/kernel/fs/cifs/cifs.ko
version:        1.60RH
description:    VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows
license:        GPL

Perl 版本:

[root@server mail_downloader]# perl --version

This is perl, v5.8.8 built for i386-linux-thread-multi

非重音版本:

[root@server mail_downloader]# rpm -qa | grep Unaccent
perl-Text-Unaccent-1.08-1.2.el5.rf

问题:关于为什么 perl movecopy 使用 cifs 挂载点有这种行为的任何线索以及如何解决这个问题?

显然我不能 post 这里的文件内容,因为它们是 EDI 相关的东西,并且有一些财务信息。

此外,如果我评论 perl copy 在使用 cpmv 完成 unaccent 后自己处理文件,文件将正确移动到 cifs挂载点。

好吧,我并不为此感到自豪,但这是一种解决方法,它通过不使用 perl 来处理此文件移动而几乎消除了 cifs 错误。

我不使用 perl 中的 movecopy,而是通过 system 函数使用操作系统 mv 二进制文件。

旧代码块:

copy   "$temp_dir/$arquivo", "$dest_file";
unlink "$temp_dir/$arquivo";

新的核心块:

system("/bin/mv", "$temp_dir/$arquivo", "$dest_file" );

问题很明显 - 完成写入后您没有关闭文件。当你 copy/move 它到另一个文件系统时,你丢失了它的一大块还没有同步到磁盘。

     open (ESCRITA, ">", "$temp_dir/$arquivo");
     foreach $manipula_linha (@manipular){
       # Removes & and accents
       $manipula_linha =~ s/\&/e/g;
       $manipula_linha = unac_string("UTF-8", $manipula_linha);
       print ESCRITA $manipula_linha;
     };

     # Flush the file
     my $old_fh = select(ESCRITA);
     $| = 1;
     select($old_fh);

     close ESCRITA;
  };

  move   "$temp_dir/$arquivo", "$dest_file";