Наскільки стабільні оболонки "stdin / stdout API" оболонки Unix?


20

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

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

Як хтось із досвідом веб-розробок, я порівнюю подібний вид збору та обробки даних технічно з веб-вискоблюванням - технікою, яка дуже нестабільна, коли є найменші зміни у поданні даних.

Зараз моє запитання стосується стабільності API команд Unix.

  1. Чи дотримуються команди в операційних системах, схожі на Unix, формальної стандартизації щодо їх введення та виведення?
  2. Чи були в історії випадки, коли оновлення якоїсь важливої ​​команди викликали порушення функціональності якогось фільтра, який був побудований за допомогою старшої версії вказаної команди?
  3. Чи дозріли команди Unix з часом, що змінити таким чином абсолютно неможливо, щоб якийсь фільтр міг зламатися?
  4. Якщо фільтри час від часу можуть ламатися через зміни API команд, як я можу як розробник захистити свої фільтри від цієї проблеми?

Відповіді:


17

Стандарт POSIX 2008 містить розділ, що описує "Оболонки та комунальні послуги" . Як правило, якщо ви дотримуєтесь цього, ваші сценарії повинні бути досить надійними, за винятком випадків депресії, але вони навряд чи трапляються протягом ночі, тому у вас має бути достатньо часу для оновлення сценаріїв.

У деяких випадках, коли формат виводу для однієї утиліти сильно різниться у різних платформах та версіях, стандарт POSIX може містити опцію, яка зазвичай називається -pабо -Pяка визначає гарантований та передбачуваний формат виводу. Прикладом цього є timeутиліта , яка має різні варіанти реалізації. Якщо вам потрібен стабільний формат API / виводу, ви використовуєте time -p.

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


12

Я спробую відповісти зі свого досвіду.

  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натомість, що би відрізало 2-е поле, розділене вкладками. awkрозбиває будь-який рядок введення на $ 1, $ 2, $ 3 ..., які за замовчуванням розділені пробілами. Залежить від понять вищого рівня, таких як "поля", а не понять нижчого рівня, таких як положення стовпця. Крім того, використовуйте регулярні вирази: sedі awkобидва можуть робити речі з регулярними виразами, які не цікавляться певною дисперсією введення. Ще одна хитрість полягає в тому, щоб обробити вхід у те, чий формат може бути вашим фільтром. Використовуйте tr -cs '[a-zA-z0-9]' '[\n]'для розбиття тексту на одне слово на рядок, без розділових знаків. Ви просто не '


9

По-перше, дуже короткі відповіді на ваші запитання:

  1. Офіційна стандартизація умов введення / виводу: немає
  2. Поломка в минулому через зміну випуску: так
  3. Зовсім неможливо зламати майбутні фільтри: ні
  4. Як я можу захистити себе від змін: будьте консервативними

Коли ви говорите "API", ви використовуєте термін, який (для хорошого чи поганого) передбачає занадто велику формальність щодо конвенцій введення / виведення фільтру. Дуже (і я маю на увазі "дуже") в цілому, основними умовами для даних, які підлягають легкій фільтрації, є:

  • кожен рядок введення - це повний запис
  • у межах кожного запису поля розділені відомим символом розмежувача

Класичним прикладом може бути формат / etc / passwd. Але ці умовні умови звичайно порушуються певною мірою частіше, ніж дотримуються цього листа.

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

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

  • Як сказав @ jw013 , подивіться, що кажуть стандарти posix. Звичайно, у posix не вказані всі команди, які ви хочете використовувати як джерела введення.
  • Якщо ви хочете, щоб ваші сценарії були портативними, намагайтеся уникати ідіосинкратій будь-якої версії якоїсь команди, яка у вас трапляється. Наприклад, багато версій GNU стандартних команд unix мають нестандартні розширення. Вони можуть бути корисними, але вам слід уникати їх, якщо ви хочете отримати максимальну портативність.
  • Спробуйте дізнатися, які підмножини аргументів команд та формати виводу, як правило, стабільні на платформах. На жаль, для цього потрібен доступ до декількох платформ разом із часом, оскільки ці відмінності не будуть записані ніде, навіть неформально.

Зрештою, ви не можете повністю захистити себе від проблем, які вас хвилюють, і немає єдиного місця, де можна було б шукати "остаточне" твердження того, що повинна робити певна команда. Для багатьох сценаріїв оболонок, особливо тих, що написані для особистого чи невеликого використання, це просто не є проблемою


5

Тільки охоплює 1) вашого питання.

Природно, API завжди можуть змінюватися за бажанням своїх творців і, таким чином, ламати залежне програмне забезпечення будь-якою мовою. Однак, чудова ідея «API» інструментів вводу / виводу інструментів Unix полягає в тому, що його практично немає (можливо, 0x0aяк кінець рядка). Хороший сценарій фільтрує дані за допомогою інструментів Unix, а не створює їх. Це означає, що ваш скрипт може зламатися через те, що змінилися параметри вводу або виводу, але не тому, що формат вводу / виводу (знову ж таки, насправді не існує) окремих інструментів, що використовуються в сценарії, змінився (тому що насправді щось не існує насправді не можна змінити).

Переглядаючи список основних інструментів, мало би я також приписував виробника , на відміну від лише фільтра:

  • wc - кількість друку байтів, слів, рядків - дуже простий формат, таким чином, абсолютно неправдоподібний для зміни, і, крім того, не дуже ймовірно, що він буде використаний у сценарії.
  • різниця - там розвивалися різні формати виведення , але я не чув про якісь - яких проблем. Також зазвичай не використовується без нагляду.
  • дата - Тепер ми справді повинні дбати про те, що ми виробляємо, особливо стосовно локальної системи. Але в іншому випадку вихідний формат є RFC'ed, якщо ви точно не вказуєте його самостійно.
  • cal - не будемо говорити про це, я знаю, що вихідний формат дуже сильно відрізняється між системами.
  • Ls , який , ж , останній - я не можу допомогти , якщо ви хочете , щоб розібрати логінсервера, просто не судилося. Крім того, хто, з останнього, більш інтерактивні листи; Якщо ви використовуєте їх у сценарії, вам потрібно подбати про те, що ви робите.
  • час було вказано на іншій посаді. Але так, це те саме, що і з ls. Більше для інтерактивного / локального використання. І вбудований bash дуже відрізняється від версії GNU, і версія GNU має нефіксовані помилки протягом багатьох років. Просто не покладайтеся на це.

Ось інструменти, які очікують, що певний формат введення буде більш конкретним, ніж байт-потік:

  • bc , dc - калькулятори. Уже в більш хакерській стороні речей (насправді я не використовую їх у сценаріях), і, мабуть, дуже стабільні формати вводу / виводу.

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

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

І навіть при використанні таких перемикачів, як правило, помилки не будуть введені тонко і отруюють ваші дані. Більшість програм просто відмовляться працювати з невідомим комутатором.

На закінчення я б сказав, що оболонка насправді має потенціал бути однією з найбільш портативних мов (вона портативна, коли ви переносите сценарій на портативному рівні). Порівняйте з улюбленими мовами сценаріїв, де трапляються тонкі помилки, або з вашою улюбленою компільованою програмою, яка перестане компілювати.

Крім того, в рідкісних місцях, де може статися поломка через несумісність, це, мабуть, не через час, а через різноманітність у різних системах (тобто, якщо це працює для вас, це було зроблено за 20 років до і буде через 20 років теж). Це є наслідком простоти інструментів.


1

Є лише фактично стандарти IO - пробіл та розділений нуль вихід.

Що стосується сумісності, ми зазвичай повертаємось до перевірки номерів версій окремих фільтрів. Мало того, що вони сильно змінюються, але коли ви хочете скористатися абсолютно новою функцією і все ще хочете, щоб сценарій запускався на старих версіях, вам доведеться якось "вимкнути" його. Практично відсутній механізм звітування про можливості, окрім написання тестових випадків вручну.


0

Сценарії роблять злам, деякі частіше, ніж інші. Старе і відоме програмне забезпечення, як правило, залишається відносно таким же, і часто має прапорці сумісності, коли воно все одно змінюється.

Сценарії, написані в одній системі, як правило, продовжують працювати, але часто порушують іншу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.