【问题标题】:Perl, can't capture return codes?Perl,无法捕获返回码?
【发布时间】:2020-09-24 18:53:32
【问题描述】:

并提前感谢您。 我不是 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 条件允许处理或执行。

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

【问题讨论】:

  • 感谢 Schwern,是的,我的问题也是,Windows... arg!我试图寻找文本,但没有成功。
  • 确认您使用的是use strict; use warnings;。否则,添加这些并修复它们产生的错误和致命错误,或在此处显示错误。

标签: perl return-value


【解决方案1】:

system返回进程的退出码,也在$?中。

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

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 分配给了一个词法变量,因为它是一个全局变量,并且会被另一个系统调用覆盖。

【讨论】:

  • 非常感谢 Schwern,我明天可以试试这个,然后马上回来找你。学习一门新语言总是令人尴尬,同样的做法不同:) 但谢谢!!!
  • 有点傻。这不起作用。给出... 退出代码:512,错误:系统找不到指定的文件。再一次...退出代码:512,错误:尝试对不是套接字的东西进行操作。仍然没有得到好的返回码来做出决定。
  • @GLMills 您打印了$^E 并得到了与$? 相同的结果,512?请给我perl -v好吗?
  • 与此问题无关,但@Schwern,您收到我最近关于 Method::Signatures 和 Mite 的电子邮件了吗?
  • 大家好,对不起,谢谢!有点不幸,但我回来了:) - 嘿,好吧,事实证明我正在经历的是 NAS Share 实施和安全性。他们映射/安装驱动器不是持久性的,也不是不需要 uid/pwd。磁盘和安全规则是这里的问题。感谢您向我展示如何从 Perl 获得 Win last 错误响应。现在让驱动器正确映射。谢谢大家!
猜你喜欢
  • 2018-04-19
  • 2013-03-15
  • 1970-01-01
  • 2017-02-03
  • 2019-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多