从 C 语言中,运行标准实用程序(例如 ps)而不是其他的最简单方法是什么?
例如,POSIX 是否保证ps
有一个标准,/bin/ps
或者我应该将 PATH 环境变量重置为我得到的值confstr(_CS_PATH, pathbuf, n);
,然后通过 PATH 搜索运行该实用程序?
答案1
不,不是,主要是因为它不要求系统符合默认情况下,或遵守仅有的POSIX 标准(排除任何其他标准)。
例如,Solaris(经过认证的兼容系统)为其实用程序选择了向后兼容性/bin
,这解释了为什么这些实用程序以神秘的方式运行,并在不同的位置提供符合 POSIX 标准的实用程序(/usr/xpg4/bin
对于/usr/xpg6/bin
不同版本的 XPG(现已合并) 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"...);
或者您可以在构建时确定要运行的 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"...);
希望有一个sh
in $PATH
,它是类似 Bourne 的,也有一个 agetconf
并且它是您感兴趣的 POSIX 版本的那个。
答案2
其实我主要会回答是的。 POSIX 确实保证:
- 那儿是每个指定实用程序的符合标准的版本的绝对路径,
- 并且,您必须能够找到此绝对路径,并能够执行此实用程序。
虽然不一定保证每个实用程序都位于所有系统的特定目录中 ( /bin/ps
),但它始终保证能够可以在系统默认路径中找到,作为可执行文件。
事实上,在标准中执行此操作的唯一标准指定方法是(在 C 中)通过 的unistd.h
_CS_PATH,或者在 shell 中,通过command
和getconf
实用程序的组合,即PATH="$(command -p getconf PATH)" command -v ps
必须始终返回唯一的绝对路径这ps
在特定系统上提供的POSIX 兼容。也就是说,虽然它是实现定义的哪个路径包含在系统默认的 PATH 变量中,这些实用程序必须始终在其中指定的路径之一中可用、唯一且合规。