我想system
从我的 C++ 代码中调用一个 Linux 程序,但我想先检查该程序是否安装在用户的机器上。
在 Ubuntu 中,我可以确定是否使用系统调用安装了与该程序关联的包dpkg -s gifsicle
并解析其输出。gifsicle
这是程序名称。
但是,该程序(例如gifsicle
)可能是从源代码编译的,因此不会出现在 Ubuntu 软件包存储库中。
确定程序(例如gifsicle
)在执行 C++ 代码的系统上是否可用的一种好的编程方式是什么?
我想system
从我的 C++ 代码中调用一个 Linux 程序,但我想先检查该程序是否安装在用户的机器上。
在 Ubuntu 中,我可以确定是否使用系统调用安装了与该程序关联的包dpkg -s gifsicle
并解析其输出。gifsicle
这是程序名称。
但是,该程序(例如gifsicle
)可能是从源代码编译的,因此不会出现在 Ubuntu 软件包存储库中。
确定程序(例如gifsicle
)在执行 C++ 代码的系统上是否可用的一种好的编程方式是什么?
你可以which
先调用。
退出状态指示它是否可以在路径上找到指定的可执行文件。
Linux 没有标准的包管理器,所以dpkg
肯定是错误的答案。
出于安全和正确性的原因,依靠用户的 PATH 来定位可执行文件可能是不明智的。因此,您可能应该已经/usr/bin/gifsicle
在调用system
.
如果是这样,您的问题的简单答案是:
if (access("/usr/bin/gifsicle", X_OK) == 0) {
system("/usr/bin/gifsicle -my -args");
}
else if (errno == EACCESS) {
/* gifsicle not found */
}
else {
/* access() failed! Operating system is broken or Windows (or both) */
}
/usr/bin/gifsicle
(如果你放入一个变量,奖励积分)
更难 - 但可以说“更正确” -答案是避免system
并自己做,检查它是否导致或类似的结果。但是,将故障传达回父进程可能会很烦人。fork
execl
execl
ENOENT
基本上,要涵盖手动安装程序并且未在已安装软件包数据库中注册的情况,您必须扫描整个文件系统以确保未安装该程序。
如果您确定程序在用户的 PATH 中,则可以调用该which
命令(也可以使用system()
)。
但是,对此的常见解决方案是允许用户通过配置选项覆盖可执行文件的路径。例如,可以将Doxygen配置为调用dot来生成图表。默认情况下,它会尝试dot
在 PATH 环境变量中调用。如果找不到,它会警告用户它找不到dot
程序并且DOT_PATH
没有设置配置值。该解决方案的优点是简单并且也适用于其他系统。
正如您所说,确定是否安装了某些东西并非易事。确实,“已安装”并没有明确的定义;包管理器很接近,但并非一切都通过包管理器。
为什么不尝试调用可执行文件?如果调用失败,并system
表明未找到可执行文件,那么只需假定它没有安装和/或不可用——这有关系吗?- 并继续使用一些后备替代方案。