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


22

从C语言开始,运行标准实用程序(例如ps)而没有其他方法的最简单方法是什么?

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


脑子里有POSIX所说的,对于许多命令,其中包括ed(1)(对mksh来说很重要),如果它们可用,它们也必须在下可以访问/bin,即/bin/ed必须可用如果已安装ed。我现在找不到它,但是我知道LSB依赖于它,并且我已经成功地使用它作为理由来捍卫bug报告,因此至少在某些时候它必须是正确的。(或者这不是POSuX,我记错了,但是其余的都是真的。)
mirabilos

Answers:


33

不,它不是,主要是因为它不需要系统默认遵循或符合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"...);

或者,您可以在构建时确定要运行的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"...);

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


那么,您为#!做些什么呢?
约书亚

13
@Joshua:您祈祷/usr/bin/env存在并且主要符合POSIX。
凯文

3
@Kevin或您熟悉古宇宙的怪癖并调整#!行以使用正确的路径。
cas

3
@Kevin:号/usr/bin/env是一个偶数少便携式比(实际上)破解/bin/sh。每POSIX,写一个shell脚本的可移植的方法是,没有#!在所有。如果文件是可执行文件,但ENOEXEC不是有效的二进制文件,execvp则通过标准外壳执行该文件。:-)当然,在实践中这不是一个好主意,您应该使用#!/bin/sh
R ..

2
@GeoffNixon,您所指的那部分是您不愿意,不想或不想使用_POSIX_C_SOURCE的替代方法。它$PATH从外壳而不是从C 进行设置。
StéphaneChazelas

3

实际上,我会在很大程度上回答。POSIX保证:

  1. 这里面一个绝对路径的每个指定实用的符合标准的版本,
  2. 并且,您必须能够找到该绝对路径,并且能够执行此实用程序。

虽然它并不一定保证每个实用程序应在所有系统(特定的目录/bin/ps),它总是保证能够在系统默认路径可以发现,作为一个可执行文件。

事实上,在标准做到这一点的唯一标准规定的方法是(C)中通过unistd.h的_CS_PATH,或壳,通过组合commandgetconf实用工具,即PATH="$(command -p getconf PATH)" command -v ps必须始终返回的唯一绝对路径 POSIX兼容ps在特定系统上提供。也就是说,虽然实现定义了系统默认PATH变量中包括哪些路径,但这些实用程序在其中指定的路径之一中必须始终可用,唯一且合规。

请参阅:< unistd.h >,命令


但是对于sh来说,有一个鸡和鸡蛋的问题。这PATH=$(command -p getconf PATH)仅在POSIX环境中的POSIX Shell中有效。POSIX并没有说明您如何进入该环境,而只是对其进行了记录。例如,在Solaris上,您有一个/usr/xpg4/bin/getconf和和一个/usr/xpg6/bin/getconf_CS_PATH为该标准的两个不同版本返回不同的值,并且默认值/usr/xpg4/bin也不/usr/xpg6/bin$PATH。有一个/usr/bin/getconf它IIRC给你XPG4一致性。
StéphaneChazelas

即使对于Solaris 11+(经UNIX 03+认证)版本也是如此吗?我一直阅读```应用程序...应该由对getconf PATH返回的PATH的询问来确定,确保返回的路径名是绝对路径名而不是内置的shell。例如,要确定标准SH实用程序的位置:命令-v SH在一些实现中,这可能会返回:在/ usr / XPG4 / bin / sh的```意味着这必须是一个符合POSIX标准的条目sh从任何默认的shell 。
杰夫·尼克松

1
POSIX中没有任何内容表明getconf$PATH给定系统的默认情况下应该有一个命令。例如,获得POSIX环境可能涉及启动仿真层,否则,您将根本不会运行任何类似Unix的命令(例如Windows)。进入兼容环境后,getconf PATH$PATH将可以进入兼容实用程序,但是如果您处于POSIX环境中,情况可能已经如此。请注意,getconf ps可能会返回ps。其ps内置是允许的。
StéphaneChazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.