Насколько стабильны оболочки Unix «API-интерфейсы stdin / stdout»?

grepping, awking, sedding и piping – повседневная рутина пользователя любой Unix-подобной операционной системы, может быть, она находится в командной строке или внутри скрипта оболочки (в дальнейшем называются фильтрами ).

По сути, при работе со стандартными программами Unix CLI и встроенными оболочками (теперь называются командами ) фильтры нуждаются в точном ожидаемом формате для stdin, stdout и stderr на каждом шаге фильтра для правильной работы. Я называю этот точный ожидаемый формат некоторой команды API этой команды в следующем.

Как кто-то с фоном веб-разработки, я сравниваю этот вид сбора данных и обработки данных технически с помощью веб-скрепок – техника, которая очень нестабильна, когда есть небольшое изменение в представлении данных.

Теперь мой вопрос касается стабильности API-интерфейсов Unix.

  1. Выполняют ли команды в Unix-подобных операционных системах официальную стандартизацию в отношении их ввода и вывода?
  2. Были ли в истории случаи, когда обновление какой-либо важной команды приводило к нарушению функциональности какого-либо фильтра, который был создан с использованием старой версии указанной команды?
  3. Имеют ли команды Unix со временем созревание, что абсолютно невозможно изменить таким образом, чтобы какой-то фильтр мог сломаться?
  4. В случае, если фильтры могут время от времени ломаться из-за изменения командных API, как я могу как разработчик защитить свои фильтры от этой проблемы?

6 Solutions collect form web for “Насколько стабильны оболочки Unix «API-интерфейсы stdin / stdout»?”

В стандарте POSIX 2008 есть раздел, описывающий «Shell and Utilities» . Как правило, если вы придерживаетесь того, что ваши сценарии должны быть достаточно перспективными, за исключением, возможно, для устареваний, но это вряд ли произойдет за одну ночь, поэтому у вас должно быть достаточно времени для обновления ваших сценариев.

В некоторых случаях, когда формат вывода для одной утилиты широко варьируется в разных платформах и версиях, стандарт POSIX может включать в себя опцию, обычно называемую -p или -P которая определяет гарантированный и предсказуемый формат вывода. Примером этого является утилита time , которая имеет широко различающиеся реализации. Если вам нужен стабильный формат API / вывода, вы будете использовать time -p .

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

Я попытаюсь ответить из своего опыта.

  1. Команды действительно не соответствуют формальной спецификации, но они соблюдают требование потреблять и генерировать текст, ориентированный на линию.

  2. Да, конечно. До того, как утилиты GNU стали стандартом де-факто, многие производители имели бы причудливый выход, особенно в отношении ps и ls . Это вызвало много боли. Сегодня только HP предлагает сверхпривычные команды. Исторически сложилось так, что утилиты Berkeley Software Distribution (BSD) были серьезным перерывом в прошлом. Спецификация POSIX была перерывом с прошлым, но теперь она широко принята.

  3. Команды Unix действительно созрели с течением времени. По-прежнему невозможно разбить какой-то скрипт, написанный для более старой версии. Подумайте о недавней тенденции к UTF-8 в качестве кодирования текстового файла. Это изменение потребовало изменения основных утилит, таких как tr . В прошлом простой текст был почти всегда ASCII (или что-то близкое), поэтому прописные буквы составляли числовой диапазон, как и строчные буквы. Это больше не относится к UTF-8, поэтому tr получает возможность принимать различные параметры командной строки, чтобы указать такие вещи, как «верхний регистр» или «буквенно-цифровой».

  4. Один из лучших способов «пробить» ваши фильтры – не зависеть от конкретного макета текста. Например, не делайте cut -c10-24 , что зависит от положения строки. cut -f2 этого используйте cut -f2 , который cut -f2 поле с разделителем табуляции. awk разбивает любую входную строку на $ 1, $ 2, $ 3 … которые по умолчанию разделены пробелами. В зависимости от концепций более высокого уровня, таких как «поля», а не концепций более низкого уровня, таких как позиция столбца. Кроме того, используйте регулярные выражения: sed и awk могут делать вещи с регулярными выражениями, которые не заботятся о некоторой дисперсии ввода. Другой трюк состоит в том, чтобы обработать вход в нечто, формат которого может быть разборчивым. Используйте tr -cs '[a-zA-z0-9]' '[\n]' чтобы разбить текст на одно слово в строке без знаков препинания. Вам просто все равно, как выглядит исходный текст в этом случае.

Во-первых, очень короткие ответы на ваши вопросы:

  1. Формальная стандартизация соглашений ввода / вывода: нет
  2. Поломка в прошлом из-за изменения выпуска: да
  3. Абсолютно невозможно сломать будущие фильтры: нет
  4. Как я могу защитить себя от изменений: быть консервативным

Когда вы говорите «API», вы используете термин, который (для хорошего или плохого) подразумевает слишком большую формальность вокруг соглашений ввода / вывода фильтров. Очень (и я имею в виду «очень») в целом, основные соглашения для данных, которые можно легко фильтровать,

  • каждая строка ввода является полной записью
  • в каждой записи поля разделяются известным символом разделителя

Классическим примером будет формат / etc / passwd. Но эти соглашения по умолчанию, вероятно, в какой-то степени нарушаются, чем к письму.

  • Существует множество фильтров (часто написанных на awk или perl), которые обрабатывают многострочные форматы ввода.
  • Существует множество шаблонов ввода (например, / var / log / messages), где нет четко определенной структуры поля, и должны использоваться более общие методы на основе регулярных выражений.

Ваш четвертый вопрос, как защитить себя от изменений в структуре вывода, действительно единственный, о котором вы можете что-либо сделать.

  • Как сказал @ jw013 , посмотрите, что говорят стандарты posix. Конечно, posix не определяет все команды, которые вы хотите использовать в качестве исходных источников.
  • Если вы хотите, чтобы ваши сценарии были переносимыми, постарайтесь избегать идиосинкразий любой версии какой-либо команды, которой вы случайно не являетесь. Например, во многих версиях стандартных Unix-команд GNU есть нестандартные расширения. Они могут быть полезны, но вы должны избегать их, если хотите максимальную мобильность.
  • Попытайтесь узнать, какие подмножества аргументов команд и форматы вывода имеют тенденцию быть стабильными на разных платформах. К сожалению, для этого требуется доступ к нескольким платформам вместе со временем, поскольку эти различия не будут записываться нигде, даже неофициально.

В конце концов, вы не можете полностью защитить себя от проблем, о которых вы беспокоитесь, и нет единого места для поиска «окончательного» утверждения о том, что должна выполнить определенная команда. Для многих сценариев оболочки, особенно написанных для личного или маломасштабного использования, это просто не проблема

Только охватывая 1) вашего вопроса.

Естественно, API-интерфейсы могут всегда меняться по желанию своих создателей и, соответственно, разрывать зависимое программное обеспечение на любом языке. Тем не менее, отличная идея API-интерфейсов ввода-вывода Unix «заключается в том, что практически нет (может быть, 0x0a как конец строки). Хороший скрипт фильтрует данные с помощью инструментов Unix, а не создает их. Это означает, что ваш скрипт может сломаться, потому что спецификация ввода или вывода изменилась, но не потому, что формат ввода-вывода (опять же, на самом деле отсутствует) отдельных инструментов, используемых в скрипте, изменился (потому что что-то действительно не существует не может измениться).

Перейдя по списку базовых инструментов, есть несколько, которые я бы назвал продюсером , а не только фильтром:

  • wc – печатать количество байтов, слов, строк – очень простой формат, поэтому совершенно маловероятно изменить и, кроме того, вряд ли будет использоваться в скрипте.
  • diff – там развивались разные выходные форматы, но я не слышал о каких-либо проблемах. Также обычно не используется без надзора.
  • date – Теперь мы действительно должны заботиться о том, что мы производим, особенно в отношении языковой системы. Но в противном случае выходной формат RFC'ed, если вы точно не укажете его сами.
  • cal – давайте не будем говорить об этом, я знаю, что формат вывода сильно отличается от разных систем.
  • ls , who , w , last – я не могу помочь, если вы хотите разобрать ls, это просто не должно было быть. Кроме того, who, w, last, являются более интерактивными пользователями; Если вы используете их в сценарии, вы должны заботиться о том, что вы делаете.
  • время было указано в другом сообщении. Но да, это то же самое, что и с ls. Больше для интерактивного / местного использования. И встроенный bash сильно отличается от версии GNU, а версия GNU имеет незафиксированные ошибки в течение многих лет. Просто не полагайтесь на это.

Вот инструменты, которые ожидают, что конкретный формат ввода более конкретный, чем байтовый поток:

  • bc , dc – калькуляторы. Уже на более хакерской стороне вещей (на самом деле, я не использую их в скриптах) и, по-видимому, очень стабильные форматы ввода-вывода.

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

  • Все инструменты, использующие регулярное выражение regex, могут изменять значение, основанное на локали системы (например, LC_COLLATE), и существует множество тонкостей и особенностей в реализациях регулярных выражений.
  • Просто не используйте причудливые переключатели. Вы можете легко использовать man 1p find например, для чтения справочной страницы POSIX, а не для системной man-страницы. В моей системе мне нужно установить manpages-posix.

И даже при использовании таких переключателей, как правило, ошибки не будут введены тонко и отравить ваши данные. Большинство программ просто откажутся работать с неизвестным коммутатором.

В заключение я бы сказал, что оболочка имеет потенциал быть одним из самых портативных языков (она переносима, когда вы выполняете сценарий портативно). Сравните с вашими любимыми языками сценариев, где возникают тонкие ошибки, или ваша любимая скомпилированная программа, которая будет уступать компиляции.

Кроме того, в редких местах, где поломка может произойти из-за несовместимости, вероятно, это было бы не из-за вызванного времени, а из-за разнообразия в разных системах (что означает, что если это сработает для вас, то это произошло 20 лет назад и будет через 20 лет , слишком). Это следствие простоты инструментов.

Существуют только де-факто стандарты IO – пробельные и нулевые выходные данные.

Что касается совместимости, мы обычно возвращаемся к проверке номеров версий отдельных фильтров. Не то, чтобы они сильно менялись, но когда вы хотите использовать совершенно новую функцию и все еще хотите, чтобы сценарий работал в более старых версиях, вы должны каким-то образом «ifdef». Механизм представления возможностей практически не существует, за исключением случаев написания сценариев вручную.

Сценарии разрываются, а некоторые чаще других. Старое и известное программное обеспечение имеет тенденцию оставаться относительно одинаковым, и часто имеет флаги совместимости, когда они все равно меняются.

Сценарии, написанные на одной системе, как правило, продолжают работать, но часто ломают друг друга.

  • Настройка рабочей среды - Konsole или другой терминал - открытие нескольких вкладок и запуск некоторых команд
  • API для IPROUTE2 на любом языке программирования
  • В системах Unix, почему мы должны явно открывать файлы `open ()` и `close ()`, чтобы они могли читать `read ()` или `write ()` them?
  • Как Gnome часы / календарь апплета получить информацию о погоде, закате и времени восхода?
  • Изменение кода для отправки аргумента API - Bash - Pastebin
  • что такое «API пространства ядра и пользователя»?
  • «Sh», запущенный с помощью execl (), становится зомби
  • Почему BSD использует конкретные имена драйверов для сетевых интерфейсов? Это подразумевает ограничения?
  • Получение часовых поясов в странах
  • Как автоматизировать загрузку последнего файла, загруженного в папку Google Диска?
  • Как я могу наблюдать за графическим интерфейсом рабочего стола с оболочкой?
  • Linux и Unix - лучшая ОС в мире.