【问题标题】:Different Exit Status in Perls system than in BashPerls 系统中的退出状态与 Bash 中的不同
【发布时间】:2017-12-25 19:00:26
【问题描述】:

我想检查用户是否有权访问某个 samba 共享。我目前正在使用Version 4.3.11-Ubuntu 中的命令smbclient 执行此操作。

显然使用exit 状态来评估成功不是一个好主意,如以下问题所述:Exit codes of smbclient

不过我还是有一些奇怪的行为。使用 Perls system 函数调用程序时,我得到不同的退出状态。

perldoc -f system 告诉我这个:

返回值是程序返回的退出状态 “等待”呼叫。

从命令行调用时,我得到EXIT 1

user@host:~$ smbclient //server/share MyFalsePassword --user=any.user -c "cd somefolder;"; echo "EXIT $?"
WARNING: The "syslog" option is deprecated
session setup failed: NT_STATUS_LOGON_FAILURE
EXIT 1

调用相同的 whitin Perl 我得到 EXIT 256

user@host:~$ perl -E 'say "EXIT " . system("smbclient //server/share MyFalsePassword --user=any.user -c \"cd somefolder;\"");'
WARNING: The "syslog" option is deprecated
session setup failed: NT_STATUS_LOGON_FAILURE
EXIT 256

我在变量$? whitin Perl 中也有值256

注意:如果我使用正确的凭据,我会在两个(Bash 和 Perl)中得到 EXIT 0

我的问题:如果我使用错误的凭据,为什么会从 Bash 和 Perl 获得不同的退出状态?如何正确检查?

我在 Ubuntu 16.04 上使用 Perl v5.22。

【问题讨论】:

标签: bash perl samba


【解决方案1】:

system返回的退出状态是一个两字节的数字,它将程序返回的退出码打包成高位,如果进程被杀死则设置低8位通过一个信号。低 7 位为信号编号,第 8 位显示内核是否被转储。

因此,要真正退出程序,请按照您引用的文档中的下一句话说

要获得实际的退出值,右移八位

256 >> 8 给我们1

system 的回报可在variable $? 中找到,如system 中所述进行询问

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
        ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}

退货最好保存或$? 在它被清除之前立即检查。


using IPC::System::Simple 可以避免位移,直接返回程序的退出值。感谢daxim 的评论。要调查信号,我们仍然需要$?,但这种情况出现的频率要低得多。该模块简化了systemqx 的使用和错误检查。

【讨论】:

  • 这出乎意料的复杂。这里应该提到:stackoverflow.com/questions/799968/…你之前引用的那句话我已经看过了。您的解释有助于理解文档。谢谢! CPAN 上是否没有提供不需要位操作的接口的模块?对于以后需要查看此代码的任何人来说,这都是一种痛苦。
  • "如果系统返回非零,你可以询问变量$?" 不需要检查$?和@987654337的返回值@:它们是相同的。
  • @Borodin 我的意思是将$? 检查与最常做的事情system(...) == 0 or ...(或system(...) and ...)联系起来。我的意思是人们通常首先检查system 的返回。也许它确实有点笨拙:(
  • @BorisDäppen 您提到的链接讨论了在$? 中具有状态的呼叫之间的差异,所以我会说,是的,您期望这个被提及是正确的。我不知道会拆分命令的实际退出的模块,但是有很多模块包含system(或qx)以便很好地访问STDOUTSTDERR,检查错误等。我会环顾四周...
  • 对于那些认为每次都做这个算术是愚蠢的并且应该被抽象出来的人,请参阅allowed exit values in IPC::System::Simple
【解决方案2】:

这没有很好的记录,最有用的信息在 perldoc perlvar 是这么说的

  • $CHILD_ERROR
  • $?

    最后一个管道关闭、反引号命令、成功调用wait()waitpid()system() 运算符返回的状态。这只是传统 Unix wait() 系统调用返回的 16 位状态字(或者被编造出来的样子)。因此,子进程的退出值实际上是 ($? >> 8),$? & 127 给出进程死亡的信号(如果有),$? & 128 报告是否存在核心转储。

因此,system 的返回值 256 对应于退出值 256 >> 8,这是您期望的 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 2013-02-28
    • 2013-02-10
    相关资源
    最近更新 更多