c ++ - способ узнать, существует ли команда Linux перед ее выполнением

0

Я хотел бы написать функцию, которая генерирует 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
    код завершения выполнения команды говорит мне, существовал ли он и произошел сбой в процессе или просто не существовал? Я хотел бы различать эти неудачи.
Показать ещё 5 комментариев
Теги:
gzip

3 ответа

4
Лучший ответ

Самое простое - выполнить через system(): "which gzip" и посмотреть код выхода системного вызова:

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ Возвращаемое значение -1 при ошибке (например, fork (2) не удалось) и статус возврата команды в противном случае. Этот последний статус возврата находится в формате, указанном в ожидании (2). Таким образом, код выхода команды будет WEXITSTATUS (статус). В случае, если /bin/sh не может быть выполнен, статус выхода будет таковым из команды, которая выполняет выход (127).

Что искать:

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

Если вы не хотите создавать внешнюю команду, вы можете использовать функцию stat, чтобы проверить, существует ли файл и если он выполняется в системе POSIX.

Это вы не хотите жестко кодировать путь к gzip, это немного сложнее. Вам нужно будет получить переменную среды PATH, разделить ее на двоеточие, а затем проверить каждый путь для gzip. Опять же, имя и формат переменных пути являются специфичными для POSIX. Проверьте функцию getenv, чтобы прочитать путь, и вы можете использовать strtok для его разделения.

Это сомнительно, если стоит проверить, хотя, наоборот, просто пытается запустить его и обработать любые ошибки.

3

Вы можете использовать popen (3) для чтения вывода /usr/bin/which gzip (и вы также можете использовать его для сжатия на лету write- popen -ing gzip > file.gz command). вы также можете: FILE* pgzipv = popen("gzip --version", "r"); и fgets первая строка затем pclose....

Вы могли бы рассмотреть возможность использования getenv("PATH")то делает петлю на него с access теста к каждому сконструированной путиполученного путем добавления /gzip к каждому элементу в PATH , и т.д... Вы можете также fork затем execvp с помощью gzip --version с stdout и stderr соответствующим образом перенаправлены и т.д.

Обратите внимание, что и popen (3), и система (3) не сработают, если вас попросят выполнить несинхронную (CN04) xisting-программу (так как оба fork (2) a /bin/sh shell с -c). Таким образом, вам не нужно проверять наличие gzip и вам всегда нужно проверять успех system или popen (что может быть неудачно по многим причинам, см. Ниже для отказа fork и документации для других сбоев).

Чтобы быть придирчивым, проверка того, что gzip существует, бесполезна: [файл /bin/gzip ] может (маловероятно) быть удален между вашей проверкой -e.g.с access как показано ниже, или с именем popen как above- и последующим вызовом system или popen ;поэтому ваша первая проверка на gzip ничего не принесет.

В большинстве Linux-систем gzip обычно доступен в /bin/gzip (и на практике gzip всегда устанавливается); это требуется стандартом иерархии файловой системы (в котором говорится, что если gzip установлен, он должен находиться на этом пути к файлу). Тогда вы можете просто использовать доступ (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 -c ompress файл. Вы могли (и должны) просто использовать библиотеку, такую как zlib (которая требуется в соответствии с базой Linux Standard как libz.so.1); вам нужны его gzopen, gzwrite, gzprintf, gzputs, gzclose т. д.... функции! Это было бы быстрее (нет необходимости в fork (2) любом внешнем процессе) и более надежной (без зависимости от какой-либо внешней программы, такой как gzip; будет работать, даже если fork невозможен, поскольку пределы достигнуты - см. Setrlimit (2) с RLIMIT_NPROC и ulimit встроенный bash (1))

См. Также Расширенное программирование на Linux

  • 0
    Спасибо за совет. кажется, что я добавляю сложность к реализации, используя вместо этого zlib . Я хотел бы понять, что я получу, используя zlib вместо активации внешней команды, которая будет доступна в 99% случаев?
  • 0
    С zlib (который доступен и установлен в каждой системе Linux, о которой я слышал) вы не зависите от внешних ресурсов. Таким образом, используя zlib, вы снижаете сложность своего программного обеспечения!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню