在执行 Linux 命令之前了解它是否存在的方法
Way to know if Linux command exists before executing it
我想写一个生成gz文件的函数。该函数只能在Linux
上运行,所以我想使用gzip
命令(只执行外部命令)。
到目前为止,我有这个:
bool generate_gz( const String& path )
{
bool res = false;
// LINUX
#ifndef __WXMSW__
if( !gzip_command_exists())
cout << "cannot compress file. 'gzip' command is not available.n";
else
res = (0 == execute_command(String::Format("gzip %s", path.c_str())));
// WINDOWS
#else
// do nothing - result will be false
#endif
return res;
}
bool gzip_command_exists()
{
// TBD
}
问题
有没有办法实现gzip_command_exists()
?如果是这样,它是否必须涉及运行(或尝试运行)gzip
命令?
最简单的是通过system()
执行:"which gzip"
并查看系统调用的退出代码:
返回值 返回的值在错误时为 -1(例如 fork(2) 失败),否则命令的返回状态。 后一种返回状态 在 在 wait(2) 中指定的格式。 因此,命令的退出代码将是 WEXITSTATUS(status)。 如果/bin/sh 不能 执行 退出状态将是执行 exit(127) 的命令的状态。
寻找什么:
:~$ which gzip
/bin/gzip
:~$ echo $?
0
:~$ which gzip11
:~$ echo $?
1
如果您不想生成外部命令,则可以使用 stat 函数来检查文件是否存在以及它是否在 POSIX 系统上可执行。
如果您不想硬编码gzip的路径,则稍微复杂一些。您必须获取 PATH 环境变量,将其拆分为冒号,然后检查每个路径的 gzip。同样,路径变量的名称和格式是特定于 POSIX 的。检查getenv函数来读取路径,你可以使用strtok来拆分它。
但是,与仅尝试运行它并处理任何错误相比,是否值得检查是值得怀疑的。
你可以使用 popen(3) 来读取/usr/bin/which gzip
的输出 (你也可以使用它通过写popen
gzip > file.gz
命令来动态压缩)。 您还可以有:FILE* pgzipv = popen("gzip --version", "r");
并fgets
第一行,然后pclose
....
您可以考虑使用getenv("PATH")
然后在其上创建一个循环,并对通过将/gzip
附加到PATH
中的每个元素获得的每个构造路径进行access
测试,等等......您还可以fork
然后execvp
使用带有stdout
的gzip
--version
,并适当地重定向stderr
等。
请注意,当被要求执行一个不存在的程序时,popen(3) 和 system(3) 都会失败(因为它们都用-c
分叉(2) 一个/bin/sh shell)。因此,您不需要测试gzip
是否存在,并且始终需要测试system
或popen
是否成功(可能由于多种原因而失败,请参阅下面的fork
失败,以及其他失败的文档)。
挑剔一点,检查gzip
是否存在是没有用的:它[文件/bin/gzip
]可能(不太可能)在您的检查之间被删除 - 例如,使用下面的access
或如上所述的popen
- 以及您后来调用system
或popen
; 所以你的第一次检查gzip
没有带来任何东西。
在大多数 Linux 系统上,gzip
通常可在/bin/gzip
处获得(实际上始终安装gzip
); 这是文件系统层次结构标准所要求的(该标准规定如果安装了gzip
,则应位于该文件路径)。然后你可以只使用 access(2),例如使用类似
#define GZIP_PATH "/bin/gzip" /* per FSH, see www.pathname.com/fhs */
if (access(GZIP_PATH, X_OK)) { perror(GZIP_PATH); exit(EXIT_FAILURE); };
最后,您根本不需要分叉gzip
进程来gzip压缩文件。您可以(并且应该)简单地使用像 zlib 这样的库(根据 Linux 标准库作为libz.so.1
是必需的);你想要它的gzopen
、gzwrite
、gzprintf
、gzputs
、gzclose
等....功能!这将更快(不需要 fork(2) 任何外部进程)和更可靠(不依赖于某些外部程序,如gzip
;即使由于已达到限制而无法fork
也可以工作 - 参见 setrlimit(2) 与RLIMIT_NPROC
和ulimit
内置的 bash(1))
另请参阅高级 Linux 编程
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 如何检查QList中是否存在值
- 根据某个函数是否存在启用模板
- 地图计数确实很重要,或者只是检查是否存在
- C++中是否存在 std::conditional 的懒惰等价物?
- 无论如何,我可以确定构造函数是否存在吗?
- COM :是否可以查看是否存在对我的某个 COM 对象的进程外引用?我可以释放它吗?
- 堆分配的对象是否存在永不为空的唯一所有者?
- 扩展类中的可选 vir 函数,测试它在运行时是否存在
- 模板化检查是否存在带有参数列表的类成员函数?
- 是否存在包含负号的isdigit函数(过载)
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 检查编译时是否存在静态函数
- 向量是否存在行主要形式?
- 检查 TinyXML 中的元素是否存在
- 检测是否存在具有 C++17 的类成员
- 虚拟继承中是否存在多重继承?
- 我遇到了这个代码片段,不明白. 它递归检查 C++ 字符串中是否存在大写字符
- std::weak_ptr 和相应的 std::shared_ptr 之间是否存在数据竞争?
- 是否存在用于 C 或 C++ 中常见数学运算(例如最小值、最大值和平均值)的可导入库?