Насколько стабильны оболочки Unix «API-интерфейсы stdin / stdout»?
grepping, awking, sedding и piping – повседневная рутина пользователя любой Unix-подобной операционной системы, может быть, она находится в командной строке или внутри скрипта оболочки (в дальнейшем называются фильтрами ).
По сути, при работе со стандартными программами Unix CLI и встроенными оболочками (теперь называются командами ) фильтры нуждаются в точном ожидаемом формате для stdin, stdout и stderr на каждом шаге фильтра для правильной работы. Я называю этот точный ожидаемый формат некоторой команды API этой команды в следующем.
- Не удается запустить php cli в webuser, но будет выполняться как root
- Как автоматизировать загрузку последнего файла, загруженного в папку Google Диска?
- что такое «API пространства ядра и пользователя»?
- Очень странная проблема, что-то блокирует определенные ссылки в локальном домене
- Получение часовых поясов в странах
Как кто-то с фоном веб-разработки, я сравниваю этот вид сбора данных и обработки данных технически с помощью веб-скрепок – техника, которая очень нестабильна, когда есть небольшое изменение в представлении данных.
Теперь мой вопрос касается стабильности API-интерфейсов Unix.
- Выполняют ли команды в Unix-подобных операционных системах официальную стандартизацию в отношении их ввода и вывода?
- Были ли в истории случаи, когда обновление какой-либо важной команды приводило к нарушению функциональности какого-либо фильтра, который был создан с использованием старой версии указанной команды?
- Имеют ли команды Unix со временем созревание, что абсолютно невозможно изменить таким образом, чтобы какой-то фильтр мог сломаться?
- В случае, если фильтры могут время от времени ломаться из-за изменения командных API, как я могу как разработчик защитить свои фильтры от этой проблемы?
6 Solutions collect form web for “Насколько стабильны оболочки Unix «API-интерфейсы stdin / stdout»?”
В стандарте POSIX 2008 есть раздел, описывающий «Shell and Utilities» . Как правило, если вы придерживаетесь того, что ваши сценарии должны быть достаточно перспективными, за исключением, возможно, для устареваний, но это вряд ли произойдет за одну ночь, поэтому у вас должно быть достаточно времени для обновления ваших сценариев.
В некоторых случаях, когда формат вывода для одной утилиты широко варьируется в разных платформах и версиях, стандарт POSIX может включать в себя опцию, обычно называемую -p
или -P
которая определяет гарантированный и предсказуемый формат вывода. Примером этого является утилита time
, которая имеет широко различающиеся реализации. Если вам нужен стабильный формат API / вывода, вы будете использовать time -p
.
Если вам нужно использовать утилиту фильтра, которая не покрыта стандартом POSIX, то вы в значительной степени находитесь на пути к разработчикам пакетов распространения / вверх по течению, так же, как вы находитесь во власти удаленных веб-разработчиков при выполнении веб-скрепок.
Я попытаюсь ответить из своего опыта.
-
Команды действительно не соответствуют формальной спецификации, но они соблюдают требование потреблять и генерировать текст, ориентированный на линию.
-
Да, конечно. До того, как утилиты GNU стали стандартом де-факто, многие производители имели бы причудливый выход, особенно в отношении
ps
иls
. Это вызвало много боли. Сегодня только HP предлагает сверхпривычные команды. Исторически сложилось так, что утилиты Berkeley Software Distribution (BSD) были серьезным перерывом в прошлом. Спецификация POSIX была перерывом с прошлым, но теперь она широко принята. -
Команды Unix действительно созрели с течением времени. По-прежнему невозможно разбить какой-то скрипт, написанный для более старой версии. Подумайте о недавней тенденции к UTF-8 в качестве кодирования текстового файла. Это изменение потребовало изменения основных утилит, таких как
tr
. В прошлом простой текст был почти всегда ASCII (или что-то близкое), поэтому прописные буквы составляли числовой диапазон, как и строчные буквы. Это больше не относится к UTF-8, поэтомуtr
получает возможность принимать различные параметры командной строки, чтобы указать такие вещи, как «верхний регистр» или «буквенно-цифровой». -
Один из лучших способов «пробить» ваши фильтры – не зависеть от конкретного макета текста. Например, не делайте
cut -c10-24
, что зависит от положения строки.cut -f2
этого используйтеcut -f2
, которыйcut -f2
поле с разделителем табуляции.awk
разбивает любую входную строку на $ 1, $ 2, $ 3 … которые по умолчанию разделены пробелами. В зависимости от концепций более высокого уровня, таких как «поля», а не концепций более низкого уровня, таких как позиция столбца. Кроме того, используйте регулярные выражения:sed
иawk
могут делать вещи с регулярными выражениями, которые не заботятся о некоторой дисперсии ввода. Другой трюк состоит в том, чтобы обработать вход в нечто, формат которого может быть разборчивым. Используйтеtr -cs '[a-zA-z0-9]' '[\n]'
чтобы разбить текст на одно слово в строке без знаков препинания. Вам просто все равно, как выглядит исходный текст в этом случае.
Во-первых, очень короткие ответы на ваши вопросы:
- Формальная стандартизация соглашений ввода / вывода: нет
- Поломка в прошлом из-за изменения выпуска: да
- Абсолютно невозможно сломать будущие фильтры: нет
- Как я могу защитить себя от изменений: быть консервативным
Когда вы говорите «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». Механизм представления возможностей практически не существует, за исключением случаев написания сценариев вручную.
Сценарии разрываются, а некоторые чаще других. Старое и известное программное обеспечение имеет тенденцию оставаться относительно одинаковым, и часто имеет флаги совместимости, когда они все равно меняются.
Сценарии, написанные на одной системе, как правило, продолжают работать, но часто ломают друг друга.