system() 偶尔 returns 2

system() occasionally returns 2

我使用 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 [=12=])

agent_name=`grep 'agent_name' ../etc/config.ini |awk '{ print  }'`
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

但有时会出现奇数return2的代码,如下:

[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

我想明白为什么会有一个return代码为2。

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

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

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

您的 shell 正在 return 编辑 2 的状态代码。如果没有更多细节,将很难诊断。添加 shell 产生的实际错误消息很有用。

如果您 shell 是 bash -- 现在看来是 -- 那么状态 return 代码 2 表示内存分配错误,这由bash 生成的错误消息:

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

据我所知,第 73 行是由新启动的 bash 进程执行的第一次内存分配(错误消息指示尚未分配任何字节证实了这一点),所以问题似乎是 malloc 无法分配任何内存。

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

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

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

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

dash shell,被许多发行版用作 /bin/sh 实现,当 shell 作为错误条件的结果。

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

 exit -1

状态return代码是八位无符号值;换句话说,合法的 return 代码范围从 0 到 255。-1 不在该范围内,您不应该在对 exit.

的调用中使用它

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

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