Текстовый файл не полностью перемещен в точку монтирования cifs с помощью Perl

Что ж, это самая странная проблема, связанная с файловой системой, с которой я столкнулся за долгое время.

У меня есть скрипт, который в основном подключается к удаленному серверу imap, загружает электронные письма, помечает их как прочитанные, срывает мусор для загрузки только файлов .txt и .xml. Если .txt, используйте Text::Unaccent для удаления диакритических знаков.

Это делается при отношении 1-к-1 удаленной папки imap к локальной смонтированной папке cifs на этом сервере. Удалить загрузку imap и обработку акцентуации работает просто отлично.

Моя проблема: ЕСЛИ я загружаю файл, обрабатываю выделение и перемещаю его в смонтированный каталог cifs, файл срывается (отсутствуют последние 4–10 КБ). Если я перемещу его в другой раздел на том же компьютере, файлы будут перемещены в разумном порядке (тот же 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";

Cif-версия:

[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

Перл версия:

[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 move или copy ведут себя так с точкой монтирования cifs и как это решить?

Очевидно, я не могу публиковать содержимое файлов здесь, потому что они связаны с EDI и содержат некоторую финансовую информацию.

Кроме того, если я прокомментирую perl copy, сам обработаю файл после того, как снят акцент с использованием cp или mv, файл будет правильно перемещен в точку монтирования cifs.


person Community    schedule 17.08.2017    source источник


Ответы (2)


Проблема действительно очевидна - вы не закрываете файл после того, как закончили запись в него. Когда вы копируете/перемещаете его в другую файловую систему, вы теряете его часть, которая не была синхронизирована с диском.

     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";
person Chris Turner    schedule 18.08.2017
comment
Что ж. Мне стыдно. У меня была эта функция без акцента, написанная на другом скрипте для тестирования, и я забыл портировать close ESCRITA на этот. Думаю, вы правы. - person ; 18.08.2017
comment
После получения писем с 4 .txt файлами проблема повторяется снова. Я думаю, это не связано ТОЛЬКО с закрытием файла. Нет dmesg сообщений о недоступности cif... - person ; 18.08.2017
comment
Проблема не в cifs, а в буферизации локальной файловой системы. Я ожидал, что закрытие файла приведет к сбросу содержимого на диск, но похоже, что ему нужна помощь. Я обновил свой ответ методом очистки файла, который должен работать. - person Chris Turner; 21.08.2017

Ну, я не горжусь этим, но это обходной путь, который в значительной степени устраняет ошибку cifs, не используя perl для обработки этого перемещения файла.

Вместо того, чтобы использовать move и copy из perl, я буду использовать mv двоичный файл операционной системы через system функцию.

Старый кусок кода:

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

Новый кусок ядра:

system("/bin/mv", "$temp_dir/$arquivo", "$dest_file" );
person Community    schedule 17.08.2017