c ++ - 在执行之前知道Linux命令是否存在的方法

时间:2014-01-23 09:45:05

标签: c++ linux gzip

我想编写一个生成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命令?

3 个答案:

答案 0 :(得分:4)

最简单的方法是通过system()"which gzip"执行并查看系统调用的退出代码:

  

返回值          错误时返回的值为-1(例如fork(2)失败),否则返回命令的返回状态。后者返回状态   在...          wait(2)中指定的格式。因此,命令的退出代码将是WEXITSTATUS(状态)。如果/ bin / sh不能   执行,          退出状态将是退出(127)的命令。

寻找什么:

:~$ which gzip
/bin/gzip
:~$ echo $?
0
:~$ which gzip11
:~$ echo $?
1

答案 1 :(得分:4)

如果您不想生成外部命令,可以使用stat函数检查文件是否存在以及它是否可在POSIX系统上执行。

你不想硬编码gzip的路径它稍微复杂一点。您将必须获取PATH环境变量,将其拆分为冒号,然后检查gzip的每个路径。路径变量的名称和格式也是POSIX特定的。检查getenv函数以读取路径,然后可以使用strtok将其拆分。

但是,值得检查是否值得怀疑,而不仅仅是尝试运行它并处理任何错误。

答案 2 :(得分:3)

您可以使用popen(3)来读取/usr/bin/which gzip的输出(您还可以通过写入popen - gzip > file.gz命令使用它来动态压缩)。您还可以:FILE* pgzipv = popen("gzip --version", "r");fgets第一行然后pclose ....

您可以考虑使用getenv("PATH"),然后使用access测试对每个构建的路径进行循环,方法是将/gzip附加到PATH中的每个元素}等等......您还可以fork然后execvp使用gzip --version stdoutstderr适当重定向等等。< / SUP>

请注意,当被要求执行不存在的程序时,popen(3)system(3)都会失败(因为他们fork(2) /bin/sh一个-c shell )。因此,您不需要测试gzip的存在,并且您始终需要测试systempopen的成功(由于多种原因可能会失败,请参阅下面的{ {1}}失败,以及其他失败的文档。)

要挑剔,检查fork是否存在是无用的:它[文件gzip]可能(不太可能)在您的支票之间被移除 - 例如。如上所述/bin/gzip或上面有access,以及稍后调用popensystem;因此,首先检查popen是否带来任何结果。

在大多数Linux系统上,gzip通常可以gzip使用(实际上/bin/gzip始终安装); 这是file system hierarchy standard所要求的(如果安装了gzip,它应该位于该文件路径上)。然后你可以使用access(2)例如代码如

gzip

最后,您根本不需要将#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 - 压缩文件。你可以(而且你应该)只是使用像zlib 这样的库(根据Linux Standard Base需要gzip);你想要它的libz.so.1gzopengzwritegzprintfgzputs等......功能!这样会更快(不需要fork(2)任何外部进程)并且更可靠(不依赖于某些外部程序,如gzclose;即使gzip不可能也会有效,因为限制已经已达成 - 请setrlimit(2) fork RLIMIT_NPROC内置bash(1)

另见Advanced Linux Programming