Ведение журнала Perl не работает при долгом системном вызове

У меня есть Perl-скрипт, который вызывает командную строку AWS для загрузки файла на S3. Он использует Log4Perl для регистрации информации о загрузке. Когда загрузка небольшая, несколько секунд, регистрация работает нормально, но когда файл больше и занимает несколько минут, ничего не регистрируется. Файл загружается нормально, но файл журнала не создается.

Вот как я это делаю:

#get start time
my @dt = localtime;
my $TransferStartDate = strftime("%Y-%m-%d", @dt);
my $TransferStartTime = strftime("%H:%M:%S", @dt);

my $aws_command = "/path/to/aws/bin/aws s3 mv $local_file s3://" . $s3_bucket;
my $aws_status = system( $aws_command);

#get stop time
@dt = localtime;
my $TransferEndDate = strftime("%Y-%m-%d", @dt);
my $TransferEndTime = strftime("%H:%M:%S", @dt);

my $log_conf = "
   log4perl.rootLogger                 = $log_level, LOG1
   log4perl.appender.LOG1              = Log::Log4perl::Appender::File
   log4perl.appender.LOG1.filename     = /path/to/logs/aws_s3_log-$TransferEndDate.txt
   log4perl.appender.LOG1.mode         = append
   log4perl.appender.LOG1.layout       = Log::Log4perl::Layout::PatternLayout
   log4perl.appender.LOG1.layout.ConversionPattern = %d %p %m %n
";

Log::Log4perl::init(\$log_conf);
my $logger = Log::Log4perl->get_logger();

$logger->info( "Transfer command = $aws_command" );
$logger->info( "Transfer start = $TransferStartDate $TransferStartTime" );
$logger->info( "Transfer end = $TransferEndDate $TransferEndTime" );

#check return code 
if ( $aws_status == 0 ) 
{
    $logger->info( "Transfer completed successfully");
}
elsif ( $aws_status == 1 ) 
{
    $errstring = "s3 transfer failed status = $aws_status";
    $logger->error( $errstring );
}
elsif ( $aws_status == 2 ) 
{
    $errstring = "Syntax error on AWS S3 command status = $aws_status";   
    $logger->error( $errstring );
}
elsif ( $aws_status == 130 ) 
{
    $errstring = "transfer interrupted by Ctrl-C or other SIGINT status = $aws_status";   
    $logger->error( $errstring );
}
elsif ( $aws_status == 255 ) 
{
    $errstring = "Command failed status = $aws_status";   
    $logger->error( $errstring );
}
elsif ( $aws_status == 512 ) 
{
    $errstring = "s3 command formatted incorrectly status = $aws_status";
    $logger->error( $errstring );
}
else 
{
    $errstring = "Error with AWS s3 command status = $aws_status"; 
    $logger->error( $errstring );
}

Любые идеи, что я делаю неправильно? Использование системы для совершения вызова должно привести к остановке Perl-скрипта до завершения загрузки, верно?


person familydweeb    schedule 17.07.2018    source источник
comment
system ожидает завершения команды, если только команда не запускает фоновый процесс, не дожидаясь его. Когда вы запускаете команду из командной строки, появляется ли подсказка сразу после ее завершения?   -  person choroba    schedule 17.07.2018
comment
Вы должны добавлять use strict и use warnings в начало каждой программы Perl, которую вы пишете, и исправлять любые возникающие ошибки или предупреждения. Это особенно важно, прежде чем просить весь мир о помощи с вашим кодом.   -  person Borodin    schedule 17.07.2018
comment
Когда длинная передача запускается из командной строки, она ожидает завершения передачи, прежде чем вернется приглашение.   -  person familydweeb    schedule 17.07.2018
comment
Сценарий имеет строгое использование и предупреждения об использовании - есть некоторый вспомогательный код, который здесь не включен, где параметры командной строки проверяются и загружаются в переменные, которые вы видите в отрывке кода.   -  person familydweeb    schedule 17.07.2018
comment
Остальная часть скрипта работает нормально? Если вы добавите отпечатки этих сообщений о состоянии на экран, что они говорят? Это так же, как когда он работает?   -  person zdim    schedule 17.07.2018
comment
Все остальное работает нормально, и ведение журнала отлично работает для небольших переводов. Если это большой перевод, сам перенос работает, но ничего не регистрируется, как будто он никогда не возвращается к сценарию для завершения. Есть ли лучший способ, чем система, для вызова программы AWS?   -  person familydweeb    schedule 17.07.2018
comment
Если файл журнала не создается, похоже, что команда не завершилась и, возможно, ожидает ввода данных пользователем. Вы пытались перенести создание регистратора до выполнения системного вызова? Я бы также немного подчистил код, поместив сообщения о состоянии в хэш-таблицу вместо блока if/elsif/else.   -  person Ron Bergin    schedule 17.07.2018
comment
Если вы хотите больше контролировать выполнение, используйте один из модулей IPC. IPC::Run или IPC::Open2 или IPC::Open3   -  person Ron Bergin    schedule 17.07.2018
comment
До сих пор не ясно - продолжается ли сценарий после system(...) для тех длинных прогонов, когда файл журнала не создается? Можете ли вы добавить отпечатки статуса на экран?   -  person zdim    schedule 18.07.2018


Ответы (1)


Поскольку вы записываетесь в файл, я бы добавил $|=1; в самое начало скрипта.

Также я думаю, что вам следует создать экземпляр логгера раньше, до запуска aws_command, и запустить его с помощью ``:

$|=1;
my @dt = localtime;
my $TransferStartDate = strftime("%Y-%m-%d", @dt);
my $TransferStartTime = strftime("%H:%M:%S", @dt);

my $log_conf = "
   log4perl.rootLogger                 = $log_level, LOG1
   log4perl.appender.LOG1              = Log::Log4perl::Appender::File
   log4perl.appender.LOG1.filename     = /path/to/logs/aws_s3_log-$TransferStartDate.txt
   log4perl.appender.LOG1.mode         = append
   log4perl.appender.LOG1.layout       = Log::Log4perl::Layout::PatternLayout
   log4perl.appender.LOG1.layout.ConversionPattern = %d %p %m %n
 ";


Log::Log4perl::init(\$log_conf);
my $logger = Log::Log4perl->get_logger();

my $aws_command = "/path/to/aws/bin/aws s3 mv $local_file s3://" . $s3_bucket;
my $aws_output = `$aws_command`;
my $aws_status = $?;

#get stop time
@dt = localtime;
my $TransferEndDate = strftime("%Y-%m-%d", @dt);
my $TransferEndTime = strftime("%H:%M:%S", @dt);

$logger->info( "Transfer command = $aws_command" );
$logger->info( "Transfer result = $aws_result" );

Не уверен, что это решит вашу проблему, но может помочь вам сузить диагностику.

person PKI Guy    schedule 25.07.2018