Використовуйте #! / Bin / sh або #! / Bin / bash для сумісності Ubuntu-OSX та простоти використання та POSIX


18

Я знаю, що я можу використовувати як перший рядок сценаріїв, щоб викликати потрібну оболонку.

Буде #!/bin/shрекомендовано, якщо сумісність з усіма системами Unix є абсолютною вимогою?

У моєму випадку єдині ОС, які мене хвилюють, - це Ubuntu (Debian) та OSX. Враховуючи це, чи можу я використовувати #!/bin/bashі бути впевненим, що він працюватиме в обох системах?
Чи також це полегшило б використання скриптів з більш сучасним і чіткішим синтаксисом для команд? Чи #!/bin/shстосується також використання використання POSIX?


1
Напевно, варто відзначити, що багато дистрибуції почали зливатися /binі /usr/bin. У результаті цього, напевно, краще використовувати їх #!/usr/bin/env <shname>для перенесення в наші дні.
HalosGhost

Відповіді:


15

Для початку, якщо ви можете зробити припущення, що Bash попередньо встановлений (що, наскільки мені відомо, у всіх системах, які ви перераховуєте), використовуйте наступний хешбанг для сумісності:

#!/usr/bin/env bash

це викликає те, що bashстанеться налаштованим, незалежно від того, знаходиться він /binчи /usr/local/bin.

Хоча для більшості систем у широкому діапазоні (включаючи AIX, Solaris, кілька BSD-ароматів), які bashопинялися в різних місцях, envзавжди опинялися в/usr/bin/env . Хитрість, однак, не моя, а авторка кухарської книги Bash.

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

Наприклад, подвійні дужки:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

тоді як у традиційних діалектах оболонок вам доведеться вдатися до:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

але найкраще в подвійних дужках - це те, що вони дозволяють регулярні вирази для відповідності. Bash Hackers Wiki дасть вам багато трюків в цьому напрямку.

Ви також можете використовувати досить зручні вирази, як $((2**10))або інші арифметичні вирази, вбудовані в$((expression)) синтаксис.

Використання зворотних посилань для передплатників добре, хоч і трохи застаріле. Але можливості гніздування$(command ...) викликів набагато зручніші, оскільки вам не доведеться уникати багатьох речей на різних рівнях нижньої оболонки.

Це лише кілька речей, які Bash дає вам над традиційним загальним shсинтаксисом POSIX .

Але якщо ви хочете більше енергії на оболонці (не тільки в сценаріях), також погляньте zsh.


Bash є дуже корисним інструментом, але будьте обережні, щоб не використовувати його для запуску служб, які можуть бути вразливими для помилки сценарію Bash, наприклад, access.redhat.com/security/cve/CVE-2014-6271 . Дотримуйтесь shтаких завдань.
Rick-777

1
Rick-777, що ця вразливість була сильно перекрита, і, на мою думку, ваш коментар є FUD. Якщо системна служба працює під bash, вона жодним чином не вразлива для цієї помилки. Ця помилка є вразливою до цієї помилки лише тоді, коли вона відганяє процес bash, дозволяючи віддаленим користувачам прямий доступ до однієї або декількох змінних оточуючих середовищ, як у FastCGI, і навіть тоді лише до непатческіх версій bash. У системах, з якими shпов'язано bash, вразливість не буде зменшена за допомогою використання sh.
Score_Under

11

У Debian і Ubuntu /bin/shє dash, що є оболонкою, сумісною з POSIX. Якщо ви вкажете #!/bin/sh, ви повинні обмежитися операторами POSIX у вашому сценарії. (Перевага полягає в тому, що воно dashпочинається швидше, ніж те bash, що ваш сценарій може виконати свою роботу за менший час.)

У багатьох (більшості?) Інших системах Linux /bin/shє bash, саме тому багато сценаріїв написані #!/bin/shяк їхній рядок shebang, хоча вони використовують bashрозширення.

Якщо ви хочете використовувати bashрозширення, найбезпечніший підхід у всіх системах - вказати #!/bin/bash; таким чином ви чітко заявляєте про свою залежність bash. Вам потрібно зробити це на Debian і Ubuntu. Як додатковий бонус, коли його запускають як /bin/sh bashдеактивація деяких розширень (детальніше див . Опис bashрежиму POSIX ); тому уточнення #!/bin/bashнеобхідне, щоб отримати повну користь bash.

В OS X /bin/bashтакож є і /bin/shє bash. Вказівка ​​також #!/bin/bashбуде добре працювати там.


5

Так, і OSX, і Linux будуть поставлятися разом /bin/bash. Ви повинні бути абсолютно безпечними. Однак це не POSIX. Оболонка POSIX є в /bin/shбільшості (усіх?) Систем, і це самий портативний підхід і єдиний спосіб бути сумісним з POSIX.

Зауважте, що хоча на багатьох системах /bin/shвказується bash, на інших це може вказувати на різні оболонки. dashНаприклад , це посилання на Debian і Ubuntu. Крім того, навіть якщо /bin/shце посилання на bash, поведінка оболонки змінюється, коли вона називається як shman bash, моє наголос):

Якщо bash викликається іменем sh, він намагається максимально наблизити поведінку до запуску історичних версій sh, дотримуючись стандарт POSIX. Коли викликається як інтерактивна оболонка входу, або неінтерактивна оболонка з опцією --login, вона спочатку намагається прочитати та виконати команди з / etc / profile та ~ / .profile у такому порядку. Параметр --noprofile може використовуватися для гальмування такої поведінки. Коли викликається інтерактивна оболонка з назвою sh, bash шукає змінну ENV, розширює її значення, якщо вона
визначено та використовує розширене значення як ім'я файлу для читання та виконання. Оскільки оболонка, на яку посилається sh, не намагається читати та виконувати команди з будь-яких інших файлів запуску, параметр --rcfile не впливає. Неінтерактивна оболонка з ім'ям sh не намагається прочитати інші файли запуску. Після виклику як sh, bash переходить у режим posix після зчитування файлів запуску.


2

Якщо сумісність із "усіма системами Unix" є абсолютною вимогою - а якщо ні, то чому ви пишете сценарій оболонки? - тоді, так, вам слід скористатися #! /bin/sh, тому що Bash не гарантується встановлення ніде , не кажучи вже про вхід /bin.

Насправді це набагато, набагато гірше. Якщо вам потрібна сумісність з усіма системами Unix, що включає такі речі, як Solaris і AIX, які заморозили їхнє середовище оболонки приблизно в 1995 році. Це означає, що вам доведеться використовувати такі речі, як старомодний sort +Nсинтаксис - нові системи втратили! А це також означає, що немає функцій оболонки, немає масивів, ні [[ ... ]], ні ${foo#glob}, немає $(( ... ))для арифметики, можливо, немає $( ... )підстановки команд -style, малих і недокументованих верхніх меж того, як можна отримати великий вхід, ...

Ви, ймовірно, можете піти, не турбуючись про таку велику сумісність, але якщо це навіть проблема в першу чергу, я настійно рекомендую вам розглянути мову, яка менш жахлива, ніж оболонка. Основний інтерпретатор Perl є більш ймовірно, будуть доступні , ніж Bash.


Спасибі. Як було сказано спочатку "У моєму випадку єдиною ОС", яку я хвилюю, є Ubuntu (Debian) та OSX. ". Це єдині 2 системи, які я використовував (і я їх дуже багато використовую) за останні 5 років, тому саме тому я пишу сценарій оболонки, який би працював лише на них. У мене взагалі немає потреби в універсальному сценарії та обмеженнях, які він би представляв.
Майкл Дюррант

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