Страницы

Поиск по вопросам

вторник, 7 января 2020 г.

Функция, возвращающая текст для exit status codes, defined in sysexits.h?

#c #linux


Кто-нибудь знает функцию, подобную strerror или strsignal только для exit status кодов?
Или, может, какой-то исходник для sh/perl/python/... с сообщениями "общего пользования"
(согласен, дурацкая формулировка) откуда можно скопипастить.
Сами коды и  тексты в виде комментариев есть в файле /usr/include/sysexits.h,  ничего
лучшего strexit и sysexits из Sendmail (естественно, с почтовой спецификой) я что-то
найти не могу.
Update
Решил взять такие сообщения
const char *SysExitMsg[] =
{
        /* 64 USAGE */          "command line usage error",
        /* 65 DATAERR */        "data format error",
        /* 66 NOINPUT */        "cannot open input",
        /* 67 NOUSER */         "addressee unknown",
        /* 68 NOHOST */         "host name unknown",
        /* 69 UNAVAILABLE */    "service unavailable",
        /* 70 SOFTWARE */       "internal software error",
        /* 71 OSERR */          "system error (e.g., can't fork)",
        /* 72 OSFILE */         "critical OS file missing",
        /* 73 CANTCREAT */      "can't create (user) output file",
        /* 74 IOERR */          "input/output error",
        /* 75 TEMPFAIL */       "temp failure; user is invited to retry",
        /* 76 PROTOCOL */       "remote error in protocol",
        /* 77 NOPERM */         "permission denied",
        /* 78 CONFIG */         "configuration error",
        0
};

Комментарии приветсвуются.
Кстати, сразу вопрос в тему, с каким кодом лучше выходить по out of memory?
(мне кажется, что OSERR).
Update 2
Хочу уточнить вопрос. На самом деле более всего мне интересен именно текст сообщений.
Вот еще один вариант из Sendmail sysexits.c
char *SysExMsg[] =
{
        /* 64 USAGE */          " 500 5.0.0 Bad usage",
        /* 65 DATAERR */        " 501 5.6.0 Data format error",
        /* 66 NOINPUT */        ":550 5.3.0 Cannot open input",
        /* 67 NOUSER */         " 550 5.1.1 User unknown",
        /* 68 NOHOST */         " 550 5.1.2 Host unknown",
        /* 69 UNAVAILABLE */    " 554 5.0.0 Service unavailable",
        /* 70 SOFTWARE */       ":554 5.3.0 Internal error",
        /* 71 OSERR */          ":451 4.0.0 Operating system error",
        /* 72 OSFILE */         ":554 5.3.5 System file missing",
        /* 73 CANTCREAT */      ":550 5.0.0 Can't create output",
        /* 74 IOERR */          ":451 4.0.0 I/O error",
        /* 75 TEMPFAIL */       " 450 4.0.0 Deferred",
        /* 76 PROTOCOL */       " 554 5.5.0 Remote protocol error",
        /* 77 NOPERM */         ":550 5.0.0 Insufficient permission",
        /* 78 CONFIG */         " 554 5.3.5 Local configuration error"
};
    


Ответы

Ответ 1



API для статуса завершения программ (exit(status), return 0 в main(), итд) не предполагает наличия какого-либо текста. За исключением значений return 0, exit(EXIT_STATUS), exit(EXIT_FAILURE) общепринятых стандартов не существует. Каждая программа может свою схему придумывать что оставшиеся коды означают и печатается ли что-либо перед завершением с определённым кодом. В POSIX только 8-бит интерпретируются как код завершения (WEXITSTATUS(status)). На Windows GetExitCodeProcess() возвращает целых 32-бита. Это позволяет некоторым программам использовать десятки кодов возврата. Объяснения что каждый код означает можно найти в их документации, например, если curl возвращает 47, то это означает: Too many redirects. When following redirects, curl hit the maximum amount. Другой пример bash, где 128 + N статус означает, что команда завершилась с сигналом N (точный список сигналов зависит от системы, например, на linux). Программа может использовать один и тот же статус для разных ошибок, например, grep возвращает 2 на любую ошибку (такую как неверная опция командной строки или несуществующий входной файл) на моей системе. grep возвращает 0 в случае успеха (что-то найдено) и 1, если не найдено (как правило). Многие другие поисковые команды, следуют этой схеме. Другая полезная схема: использовать статус 2 для неверного использования программы (несуществующие опции, их несовместимое сочетание, значения опций вне допустимых диапазонов, итд) и 1 для остальных ошибок. 2 указывает на ошибку автора скрипта (баг), а 1 на возможно временную ошибку в окружении (например, нет интернета, файла). Подавляющее большинство программ используют только два статуса: успех и провал. Существуют рекомендации по формату сообщений об ошибках, например, в GNU. Основные задачи сообщений об ошибках—это указать пути решения возникшей проблемы пользователю (что может быть очень специфично для конкретного приложения) или помочь найти причину бага в программе программисту (ещё более специфично для приложения). Использование абстрактных общих неспецифичных для конкретной программы сообщений таких как в sysexits.h не помогает ни первому ни второму случаю. Чтобы увидеть варианты сообщений, можно посмотреть на базу правил для ошибок у замечательной утилиты thefuck, которая пытается автоматически поправить возникшие ошибки в командной строке. В: Кто-нибудь знает функцию, подобную strerror или strsignal только для exit status кодов? Стандартной такой функции нет и не должно быть. Отдельные программы могут реализовывать подобные функции, например, в самом вопросе ссылка на sm_strexit(). Чем более специфичны сообщения для программы тем лучше. Например, представим какой-то программе для работы нужен файл, а он не существует и программа вынуждена завершится. Если программа напишет безличное и общее сообщение: «input/output error», то это почти бесполезно. Полезное сообщение должно как минимум упомянуть имя файла: «%s file not found» (поддержка шаблонов нужна). А человеческое сообщение по-хорошему упомянет что случилось и как решить проблему на языке пользователя, упоминая низкоуровневые детали такие как IOError только если необходимо, например, если пользователь Питон-программист, то вот полезное сообщение об ошибке: «Словарь произношений не найден. Причина: X файл не существует. Чтобы загрузить, выполните import nltk; nltk.download("cmudict")» что является более адекватным чем абстрактное «input/output error». Разница между ними—это основная причина почему exceptions используются для обработок ошибок во многих языках: информация, доступная в месте где произошла ошибка (например, системный вызов вернул errno.ENOENT: no such file or directory), отличается от информации выше по стеку где эту ошибку можно исправить. Сообщение об ошибке при выходе из программы находится на самом верху и должно использовать язык понятный человеку, ответственному за решение проблемы (например, пользователь программы). В выбранном примере можно обсудить, почему программа автоматически не выполнила необходимые действия (не зря thefuck существует), но в любом случае действия крайне вероятно будут уникальны для программы и поэтому наличие функции с абстрактным сообщением подталкивало бы программиста к выводу менее полезного сообщения. Если рассматривать утилиты, принадлежащие только определённому семейству, то возможно имеет смысл синхронизировать некоторые сообщения об ошибках, чтобы одинаковые проблемы, которые могут быть разрешены одинаково в рамках семейства, были бы одинаково решены (излишнее разнообразие не нужно). Кратко: не следует поощрять сообщения типа «input/output error» в качестве сообщений об ошибке при выходе из программы и поэтому им не место в "базе знаний". В: ...На самом деле я ловил (год уже прошел) в wait чужие коды возврата от заранее не известно каких команд и выводил текстовое сообщение. Вот и хотел посмотреть, что (помимо найденного мной) пишут люди (совершенно не обязательно, что я этим реально воспользуюсь :-)). IMHO приятней видеть что-то более осмысленное, нежели abc exited with code NNN. Понятно (к сожалению, не мой случай), что если есть возможность вытащить из stderr (или лога) оригинальное сообщение, то надо это делать Если задача, найти примеры сообщений, которые реальные программы перед выходом печатают, то либо запускать эти программы с разными параметрами и перехватывать вывод, либо смотреть в исходники (если достаточно только значение exit status без точного сообщения, то может быть достаточно документацию для соответствующей команды посмотреть). Обычно программы используют аналог функции, которая форматирует сообщение об ошибке и (опционально) выходит с заданным кодом, например, error() функция из coreutils/gnulib. Простой grep 'error (' возвращает сотни сообщений. Кстати, в подавляющем большинстве случаев единственный код выхода используется: EXIT_FAILURE (с разными сообщениями естественно). Вот результат grep для coreutils' checkout—выборка сообщений, которые перед выходом печатаются утилитами типа cp, date, wc, dd, chown, etc: $ grep -A2 '\

Комментариев нет:

Отправить комментарий