【问题标题】:system() occasionally returns 2system() 偶尔返回 2
【发布时间】:2015-08-27 22:19:21
【问题描述】:

我使用system() 库函数编写了一个函数,如下所示:

int execute(const char* cmd)
{
  int ret = system(cmd);

  if (ret != -1)
  {
    if (WIFEXITED(ret))
      ret = WEXITSTATUS(ret);
    else
      ret = -1;
  }

  LINFO( "execute %s, ret = %d", cmd, ret);  // logging
  return ret;
}

然后,我用下面的 shell 脚本调用它:

#!/bin/sh
PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
cd $(dirname $0)

agent_name=`grep 'agent_name' ../etc/config.ini |awk '{ print $3 }'`
py='../../python26/bin/python'

check_alive()
{
    status=`ps -ef | grep "$agent_name" | grep -v "grep" |wc -l`

    if [ $status -ne 0 ]; then
        # process exist
        echo "$agent_name already exist"
        exit 1
    fi    

}

check_alive
eval '$py ../bin/agent.py -d'

status=`ps -ef | grep "$agent_name" | grep -v "grep" |wc -l`
if  [ $status -lt 1 ] 
then
    echo "run failed"
    exit -1
else
    echo "run succ"
    exit 0
fi

但有时会有一个奇怪的返回码 2,如下所示:

[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 2
[INFO]execute ./admin/trystart.sh, ret = 2
[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 1
[INFO]execute ./admin/trystart.sh, ret = 2

我想了解为什么返回码是 2。

================新 2015/06/12 13:54====================== ======

我发现当system()返回2时,bash的错误信息如下:

bash: xmalloc: locale.c:73: cannot allocate 2 bytes (0 bytes allocated)

【问题讨论】:

  • 这是一个格式很好的问题。无需改进。顺便说一句,原因可能在return ret 后面,其中ret = system(cmd)system(cmd) 可能等于2
  • @JamesSmith 如果system 返回2,那么他会遇到!= -1 的情况,WIFEXITED 应该返回 false,ret 应该设置为 -1 我相信。跨度>
  • 顺便说一句。查看pgrep 而不是您的管道,eval 完全没有必要。
  • @EtanReisner 抱歉,我一定忽略了这一点。但是,WEXITEDSTATUS(ret) 会返回 2 吗?
  • @EtanReisner 如果 eval 失败,那么这个脚本会提前退出并返回 2?

标签: c shell system


【解决方案1】:

您的 shell 正在返回状态码 2。如果没有更多细节,将难以诊断。添加由 shell 生成的实际错误消息很有用。

如果你的 shell 是 bash -- 现在看起来是 -- 那么状态返回码 2 表示内存分配错误,这由bash 生成的错误消息确认:

bash: xmalloc: locale.c:73: cannot allocate 2 bytes (0 bytes allocated)

据我所知,第 73 行是由新启动的bash 进程执行的第一次内存分配(由错误消息的指示确认尚未分配任何字节),所以看起来很可能问题是 malloc 无法分配任何内存。

可能确实没有可用内存,特别是如果您在没有配置交换配置的严重拥塞系统上运行。但是互联网上散布着一些提示,这表明这可能与内存保护选项有关;特别是 sbrk 不可用但 malloc 库希望能够使用它的配置。

您可能希望通过验证是否可以可靠地启动新 shell 来开始进一步诊断:

for i in {0..999}; do sh -c 'exit 0' || echo Failure $?; done

较早的猜测,可能对其他人有用。建议修复调用exit,即使它可能与此问题中的特定问题无关。

dash shell 被许多发行版用作/bin/sh 实现,当 shell 由于错误条件而退出时返回状态代码 2。

上述脚本的一个可能罪魁祸首是

 exit -1

状态返回码是八位无符号值;换句话说,合法的返回码范围是从 0 到 255。-1 不在这个范围内,你不应该在调用 exit 时使用它。

Bash 的 exit 内置函数(如 C 中的 exit 函数)仅使用提供的返回码的低位字节,因此使用 bash 您会看到返回码为 255。但内置的破折号 exit 期望它的参数是一个无符号数,并抱怨 -1 不是一个有效的数字。

由于exit 是一个特殊的内置函数并且shell 不是交互式的,因此错误会导致shell 退出,如the Posix standard 所述。由于 shell 错误而退出时,Dash 将退出代码设置为 2。

【讨论】:

  • 啊,我在想 255 在被记录之前就被截断了。这更有意义。
  • 但即使我重置脚本的内容 ./admin/trystart.sh only 'exit 1',问题再次发生。
  • 我发现system()返回2时,bash的错误信息为:“bash: xmalloc: locale.c:73: cannot allocate 2 bytes (0 bytes assigned)”
  • @Hetiu:有趣。好吧,我当时的猜测是错误的。我编辑了答案,但我没有任何真正可靠的补充。你使用的是什么 bash 版本?您是从 centos 存储库还是以其他方式更新了 bash?
  • @rici 最后,当我使用 gcc -m32 构建调用方 c 代码并在 64 位系统中运行时,出现了这个问题。如本文所述:bugzilla.redhat.com/show_bug.cgi?id=870914
猜你喜欢
  • 2014-01-04
  • 2011-06-11
  • 2015-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-12
  • 2014-09-18
相关资源
最近更新 更多