POSIX 是否保证任何标准实用程序的路径?

PSk*_*cik 25 c path posix exec

在 C 中,运行标准实用程序(例如 ps)而不是其他的最简单方法是什么?

例如,POSIX 是否保证存在标准ps/bin/ps或者我应该将 PATH 环境变量重置为我所获得的值confstr(_CS_PATH, pathbuf, n);,然后通过 PATH-search 运行该实用程序?

Sté*_*las 35

不,不是,主要是因为它不要求系统默认符合,或符合POSIX 标准(排除任何其他标准)。

例如,Solaris(经过认证的兼容系统)为其实用程序选择了向后兼容性/bin,这解释了为什么这些实用程序以神秘的方式运行,并在不同的位置(/usr/xpg4/bin, /usr/xpg6/bin... 用于不同版本的 XPG(现已合并)提供符合 POSIX 的实用程序POSIX) 标准,那些实际上是 Solaris 中可选组件的一部分)。

即使sh不保证在/bin. 在 Solaris 上,/bin/sh在 Solaris 10 之前一直是 Bourne shell(因此不符合 POSIX),而现在在 Solaris 11 中是 ksh93(仍然不完全符合 POSIX,但实际上比 更符合 POSIX /usr/xpg4/bin/sh)。

在 C 中,您可以使用exec*p()并假设您处于 POSIX 环境中(特别是关于PATH环境变量)。

您还可以设置PATH环境变量

#define _POSIX_C_SOURCE=200809L /* before any #include */
...
confstr(_CS_PATH, buf, sizeof(buf)); /* maybe append the original
                                      * PATH if need be */
setenv("PATH", buf, 1);
exec*p("ps"...);
Run Code Online (Sandbox Code Playgroud)

或者,您可以在构建时确定要运行的 POSIX 实用程序的路径(请记住,在某些系统(如 GNU 系统)上,您需要更多步骤,例如设置POSIXLY_CORRECT变量以确保合规性)。

您还可以尝试以下操作:

execlp("sh", "sh", "-c", "PATH=`getconf PATH`${PATH+:$PATH};export PATH;"
                         "unset IFS;shift \"$1\";"
                         "exec ${1+\"$@\"}", "2", "1", "ps", "-A"...);
Run Code Online (Sandbox Code Playgroud)

希望有一个shin $PATH,它像 Bourne 一样,还有一个getconf并且它是您感兴趣的 POSIX 版本的那个。

  • @Joshua:你祈祷 `/usr/bin/env` 存在并且大部分是 POSIX 兼容的。 (14认同)
  • @Kevin:不。`/usr/bin/env` 是 ** 比 `/bin/sh` 更不便携**(实际上)的 hack。根据 POSIX,编写 shell 脚本的可移植方式是**完全没有 `#!` **。如果文件是可执行的,但`ENOEXEC`(不是有效的二进制文件),`execvp` 将通过标准shell 执行它。:-) 当然在实践中这是一个坏主意,你应该只使用`#!/bin/sh`。 (5认同)
  • @Kevin 或者您熟悉您的古 unix 的怪癖并调整 #! 行以使用正确的路径。 (3认同)
  • @GeoffNixon,您所指的那部分是您不、不能或不想使用 _POSIX_C_SOURCE 时的替代方案。它从 shell 而不是 C 中设置 `$PATH`。 (2认同)