首页 > 解决方案 > Perl,无法捕获返回码?

问题描述

并提前感谢您。我不是 Perl 开发人员,但是,我真的爱上了 Perl。就像 bash/unix 脚本一样,功能强大。。我想学习它作为我的脚本语言,但是,此时我没有那个时间。

我的问题是返回码。

问题描述:我使用Nagios Core进行监控。我的任务是监视远程服务器上的日志文件,当日志中存在某个语句时,拉出该行,提取文件名,然后将该文件复制回摄取端点。我正在使用用 Perl 编写的 Nagios 插件,Check_logfiles。一个非常优秀和强大的插件。我可以在 Perl 的脚本中编写钩子来对触发的事件执行任务。

这是我在 check_logfiles 配置中作为子例程调用编写的插件脚本。

$scriptpath = 'C:\Program Files (x86)\Nagios\NCPA\contrib';
$protocolsdir = 'C:\Program Files (x86)\Nagios\NCPA\protocols';
$seekfilesdir = 'C:\Program Files (x86)\Nagios\NCPA\seek';

$MACROS = {
    LOGS_DIR => 'C:\APMConnect\Logs',
    PP_INGESTION_EP => 'C:\APMConnect\AutoDataLoader\Scandir\ManageAPM',
    SRC_DIR => 'E:\Zip File Archive'
};

#$postscript = 'custom_mail_alert.pl';
#$postscriptparams = '--sender alpcts000000881@ge.com --recpt gary.l.mills@ge.com --subject "Notification - APM Loader refeed performed" --message "$CL_SERVICEOUTPUT$" --log-file "C:\APMConnect\Logs\AutoLoader.log" --send_if_rc_gt 1 --display-name "Aviation Preprocessor Notification"';
#$postscriptstdin = '$CL_HOSTNAME$\t$CL_SERVICEDESC$\t$CL_SERVICESTATEID$\t$CL_SERVICEOUTPUT$\n';
    
@searches = (
  {
    tag => '504 Gateway Time-Out',
    logfile => '$LOGS_DIR$\AutoLoader.log',
    rotation => 'AutoLoader.log.\d{1,2}',
    type => 'rotating',
    criticalpatterns => [
        '^java.lang.Exception:Method failed: HTTP/1.1 504 Gateway Time-out Please check configuration details and replace or update the file :.*'
    ],
    options => 'protocol,perfdata,script,supersmartscript',
    script => sub {
        use File::Copy;
        
        $map_drive = 'C:\Windows\System32\net.exe use E: \\win.alphp031.corp.bp.com\APM_Data_Storage /USER:lp814555sv xnEDs7PaD3g /PERSISTENT:YES';
        my $status = system("$map_drive 2>&1");
        my $exit_code = ($status >> 8) & 0xff;
        
#       if ( $exit_code!=0 ) {
#           printf "Exit Code: $exit_code\n";
#           printf "Status: $status\n";
#           printf 'CRITICAL - APM Data Storage NAS Share Cannot be mounted!';
#           return 2;
#       }
#       my $file_name = "BHPJanFP_2018-06-25-06-43-09.csv";
#       my $source_dir = 'C:\Users\212555427\TEMP\A';
        my $target_dir = 'C:\Users\212555427\TEMP\B';
#       my $sout = 'java.lang.Exception:Method failed: HTTP/1.1 504 Gateway Time-out Please check configuration details and replace or update the file : \\ALPCTS000000881\Archivedir\PROCESS_ADL\FaultData20200826144206065.zip';
        
        my $_source_dir = $ENV{CHECK_LOGFILES_SRC_DIR};
        my $_target_dir = $ENV{CHECK_LOGFILES_PP_INGESTION_EP};
        my $sout = $ENV{CHECK_LOGFILES_SERVICEOUTPUT};
        my $result = rindex($sout, 'FaultData');
        my $_file_name = substr($sout, $result, length($sout));
        opendir(my $DIR, $_source_dir) || die "Can't opendir $_source_dir: $!"; 

        if( -f "$_source_dir/$_file_name" ) {
            copy ("$_source_dir\\$_file_name", "$target_dir\\$_file_name") || die "File Copy Failed: $!";
            if ( $? == 0 ) {
                printf 'OK - File Copy Successful!';
                printf " Copied File to Refeed APM: $_source_dir\\$_file_name";
                return 0;
            } else {
                printf 'CRITICAL - File Copy Failed!';
                printf " Source dir: $_source_dir\\$_file_name";
                return 2;
            }
        } else {
            printf 'CRITICAL - File Copy Failed, File CANNOT be located!';
            printf "Source dir: $_source_dir\\$_file_name";
            return 2;
        }
        closedir($DIR);
    }
  }
);

我的问题从这里开始,映射 NAS 驱动器。我不知道如何获取和/或操作返回码。因为存在 NAS 驱动器已安装并因此正在使用的情况。如果此条件存在,我也想允许执行,如果它已成功安装。

my $status = system("$map_drive 2>&1");

当磁盘已经安装时,我得到了这个

C:\Program Files (x86)\Nagios\NCPA\plugins\check_logfiles-3.12\plugins-scripts>check_logf
check_logfiles.cfg"
System error 85 has occurred.

The local device name is already in use.

CRITICAL - (1 errors in check_logfiles.protocol-2020-09-24-13-40-27) - 
Exit Code: 2
Status: 512

我需要继续执行这个状态和 0 或成功挂载的状态。

你如何捕捉这些返回码?

所以我基本上需要像伪代码这样的东西......

my $status = system("$map_drive 2>&1");
if ( $status != 0 || $status != rc = System error 85 has occurred ) {
   printf 'CRITICAL - APM Data Storage NAS Share Cannot be mounted!';
   return 2;  (*** 2 here is for Nagios )

我找到了我相信的系统的返回码,找不到 net 命令?来自https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-

ERROR_ALREADY_ASSIGNED

85 (0x55)

本地设备名称已被使用。

但在做了之后……我的 $status = system("$map_drive 2>&1"); 我的 $exit_code = ($status >> 8) & 0xff;

对于已经使用或已安装的情况,我得到“2”。

确保调用中断或退出的所有其他条件以及两个 GOOD 条件允许处理或执行。

我希望这是有道理的,请告诉我,谢谢!

标签: perlreturn-value

解决方案


system返回进程的退出代码,也在$?.

$^E返回“扩展的操作系统错误”并用于具有不同方式返回进程错误代码的操作系统。在 Windows 上,这是GetLastError的结果,它给出了系统错误代码

在 Win32 下,$^E 总是返回由 Win32 调用“GetLastError()”报告的最后一个错误信息,它描述了 Win32 API 中的最后一个错误。大多数特定于 Win32 的代码将通过 $^E 报告错误。ANSI C 和类 Unix 调用设置为“errno”,因此大多数可移植 Perl 代码将通过 $! 报告错误。

所以你的支票应该是......

my $exit = system("$map_drive 2>&1");
my $error = $^E;
if ( $exit != 0 || $error == 85 ) {

我已重命名 $status 以避免混淆。而且我已经将 $^E 分配给了一个词法变量,因为它是一个全局变量,并且会被另一个系统调用覆盖。


推荐阅读