Почему' [' встроенная оболочка и' [[' ключевое слово оболочки?

Измените оболочку пользователя по умолчанию в/etc/passwd к команде (или сценарий обертки для той команды), который регистрирует того пользователя в chroot.

66
09.02.2015, 09:00
4 ответа

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

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

Это соглашение позволяет написать сценарий оболочки, содержащий следующую строку:

rm foobar ${more_things_to_remove}

... и гарантировать, что вы не можете случайно добавить параметры в команду rm , даже если переменная оболочки более _ вещей, _ для _ удаления , имеет неприятное значение, как « -rf ».

Это соглашение предшествует более позднему соглашению об использовании специального варианта -- для прекращения обработки варианта. -- является гораздо лучшим способом явного обозначения конца вариантов:

rm -- foobar ${more_things_to_remove}

# and it works even if you don't need to delete something called "foobar":
rm -- ${more_things_to_remove}

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

Лично я никогда не знаю, какие коммунальные службы все еще придерживаются конвенции, а какие нет, поэтому я всегда ставлю варианты перед аргументами, как раньше, и я слегка удивлен, когда вижу чужой рабочий код, который делает это в противоположном порядке!

-121--75013-

Если вы думаете о запуске двоичных файлов Linux непосредственно на AIX, то нет такой функции (даже если вы можете найти двоичные файлы для архитектуры Power для программного обеспечения Linux, которое вы пытаетесь использовать).

IBM действительно предоставляет набор инструментов AIX Toolbox для приложений Linux , который должен помочь в портировании программного обеспечения, разработанного для Linux, на AIX. Это коллекция инструментов и библиотек, обычно встречающихся в Linux, включая GCC, Gnome и KDE, и множество библиотек и инструментов (gawk, bash, ncurses, rsync, lsof,...). Но вам придется перекомпилировать:

Потому что Linux и AIX используют разные двоичные интерфейсы приложений (ABI) (например, Linux на разных аппаратных платформах использует разные ABI), в общем нет бинарная совместимость при изменении операционных систем или аппаратных архитектур. Например:

  • приложения Linux, скомпилированные под Linux на аппаратном обеспечении кроме IBM pSeries или IBM iSeries, как правило, не могут работать под Linux для pSeries без повторной компиляции.

  • Приложения Linux, скомпилированные в Linux для pSeries, не могут запуск под AIX,включая AIX Toolbox для приложений Linux.

  • Приложения Linux, скомпилированные в AIX с помощью AIX Toolbox для приложений Linux не может работать под Linux для pSeries.

Это из Linux Приложений on pSeries IBM Redbook ( ссылка в формате PDF, 4 .7M ), который описывает набор инструментов и содержит некоторые примечания по портированию и главу, посвященную запуску собственного Linux в аппаратном обеспечении pSeries.

-121--89283-

Разница между [ и [[ является достаточно фундаментальной.

  • [ является командой. Его аргументы обрабатываются, как только обрабатываются пути любые другие аргументы команд. Например, рассмотрим:

      [-z $ name]
    

    Оболочка расширит $ name и выполнит разделение слов и создание имени файла для результата, как и для любой другой команды.

    Например, произойдет сбой:

     $ name = «here and there»
    $ [-n $ name] & & эхо не пусто
    bash: [: слишком много аргументов
    

    Для правильной работы необходимы кавычки:

     $ [-n «$ name»] & & эхо не пусто
    не пусто
    
  • [ является ключевым словом оболочки и его аргументы обрабатываются по специальным правилам. Например, рассмотрим:

      [[-z $ name]]
    

    Оболочка расширит $ name , но, в отличие от любой другой команды, не будет выполнять ни разбиения слов, ни создания имени файла для результата. Например, следующее будет успешным, несмотря на места, внедренный в name :

     $ name = «here and there»
    $ [[-n $ name]] & & эхо
    не пусто
    

Сводка

[ является командой и подчиняется тем же правилам, что и все другие команды, выполняемые оболочкой.

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

83
27.01.2020, 19:31

Новеред [[ в bash представляет собой оптимизацию [.

Классика [ [ имеет один большой недостаток, когда он часто используется, чтобы сделать тривиальную работу: он будет нерезать новым процессом каждый раз:
(Это создает новое адресное пространство только для сравнения 0 и 1 ! Каждый раз!)

Я думаю, что главная точка добавления [[[ делал оценку выражения внутри [ не порождает дополнительный процесс. Но как работает [ [[. Итак, оптимизация была реализована с новым именем более эффективным способом, а именно команда Shell встроенной.
Стало ключевое слово в синтаксисе оболочки в качестве побочного эффекта.

В то время [ использовалось первое, было правильным образом , чтобы сделать это с внешним процессом.

0
27.01.2020, 19:31

[ изначально была просто внешней командой, другое название для /bin/test. Но некоторые команды, такие как [ и echo, так часто используются в скриптах оболочки, что реализаторы оболочки решили копировать код непосредственно в саму оболочку, вместо того, чтобы каждый раз при их использовании запускать другой процесс. Это превратило эти команды в "builtins", хотя вы все еще можете вызывать внешнюю программу по ее полному пути.

[[] пришли гораздо позже. Хотя сборка реализована внутри оболочки, она разбирается так же, как и внешние команды. Как объяснялось в ответе Джона1024, это означает, что нецитируемые переменные будут разбиты на слова, а такие лексемы как > и < обрабатываются как перенаправление ввода/вывода. Это сделало написание сложных сравнительных выражений неудобным. [[ было создано как синтаксис оболочки для идеосинкратического разбора. В пределах [[ переменные не получают расщепления слов, < и > могут быть использованы в качестве операторов сравнения, = могут вести себя по-разному в зависимости от того, цитируется следующий параметр или нет и т.д. и т.п. Все эти удобства делают [[ проще в использовании, чем традиционная команда/сборка [.

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

Это похоже на эволюцию, которая привела к синтаксису $((...)) для арифметических выражений, который в основном заменил традиционную команду expr.

3
27.01.2020, 19:31

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

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

Это соглашение позволяет написать сценарий оболочки, содержащий следующую строку:

rm foobar ${more_things_to_remove}

... и гарантировать, что вы не можете случайно добавить параметры в команду rm , даже если переменная оболочки более _ вещей, _ для _ удаления , имеет неприятное значение, как « -rf ».

Это соглашение предшествует более позднему соглашению об использовании специального варианта -- для прекращения обработки варианта. -- является гораздо лучшим способом явного обозначения конца вариантов:

rm -- foobar ${more_things_to_remove}

# and it works even if you don't need to delete something called "foobar":
rm -- ${more_things_to_remove}

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

Лично я никогда не знаю, какие коммунальные службы все еще придерживаются конвенции, а какие нет, поэтому я всегда ставлю варианты перед аргументами, как раньше, и я слегка удивлен, когда вижу чужой рабочий код, который делает это в противоположном порядке!

-121--75013-

Если вы думаете о запуске двоичных файлов Linux непосредственно на AIX, то нет такой функции (даже если вы можете найти двоичные файлы для архитектуры Power для программного обеспечения Linux, которое вы пытаетесь использовать).

IBM действительно предоставляет набор инструментов AIX Toolbox для приложений Linux , который должен помочь в портировании программного обеспечения, разработанного для Linux, на AIX. Это коллекция инструментов и библиотек, обычно встречающихся в Linux, включая GCC, Gnome и KDE, и множество библиотек и инструментов (gawk, bash, ncurses, rsync, lsof,...). Но вам придется перекомпилировать:

Потому что Linux и AIX используют разные двоичные интерфейсы приложений (ABI) (например, Linux на разных аппаратных платформах использует разные ABI), в общем нет бинарная совместимость при изменении операционных систем или аппаратных архитектур. Например:

  • приложения Linux, скомпилированные под Linux на аппаратном обеспечении кроме IBM pSeries или IBM iSeries, как правило, не могут работать под Linux для pSeries без повторной компиляции.

  • Приложения Linux, скомпилированные в Linux для pSeries, не могут запуск под AIX,включая AIX Toolbox для приложений Linux.

  • Приложения Linux, скомпилированные в AIX с помощью AIX Toolbox для приложений Linux не может работать под Linux для pSeries.

Это из Linux Приложений on pSeries IBM Redbook ( ссылка в формате PDF, 4 .7M ), который описывает набор инструментов и содержит некоторые примечания по портированию и главу, посвященную запуску собственного Linux в аппаратном обеспечении pSeries.

-121--89283-

В V7 Unix - где дебютировала оболочка Борна - [ называлась test , и она существовала только как /bin/test . Итак, код вы бы написать сегодня как:

if [ "$foo" = "bar" ] ; then ...

вы бы написали вместо этого как

if test "$foo" = "bar" ; then ...

Эта вторая нотация все еще существует, и я нахожу, что более ясно о том, что происходит: вы вызываете команду под названием test , которая оценивает свои аргументы и возвращает exit status code , что , если использует, чтобы решить, что делать дальше. Та команда может быть встроена в раковину, или это может быть внешняя программа. ¹

[ в качестве альтернативы тесту пришел позже. ² Это может быть синоним builtin для теста , но он также предоставляется как /bin/[ на современных системах для оболочек, которые не имеют его в качестве builtin.

[ и тест могут быть реализованы с использованием одного и того же кода. Это относится к /bin/[ и /bin/test в OS X, где это жесткие ссылки на один и тот же исполняемый файл. ³ В результате реализация полностью игнорирует завершающий ] : он не требует, если вы называете его /bin/[ , и он не жалуется, если вы сделать предоставить его /bin/test . ⁴

None этой истории влияет на [[, потому что никогда не было изначальной программы под названием [. Он существует исключительно внутри тех оболочек, которые реализуют его как расширение к оболочке POSIX .

Часть различия между «builtin» и «keyword» обусловлена этой историей. Он также отражает тот факт, что синтаксические правила разбора [ выражений отличаются, как указано в ответе John1024 . ⁵


Footnotes:

  1. Когда вы смотрите на него таким образом, это дает понять, почему вы должны ставить места вокруг [ в сценарии оболочки, в отличие от того, как скобки и скобки работают в большинстве других языков программирования. Если синтаксический анализатор команды оболочки разрешен , если [«$ x»... , он также должен был бы разрешить ifest «$ x»...

  2. Это произошло примерно в 1980 году. /bin/[ не существует в моей копии Ancient Unix V7 из 1979, и man test не документирует его как псевдоним. В соответствующей записи на главной странице имеется предварительная копия руководства System III от 1980,он указан в списке .

  3. ls -i/bin/[/bin/test

  4. Но не рассчитывайте на такое поведение. Встроенная версия Bash [ действительно требует закрытия ] , и ее встроенная реализация test пожалуется, если вы предоставите ее .

  5. Различие между командой builtin и внешней командой также может иметь значение по другой причине: две реализации могут вести себя по-разному. Это относится к эхо во многих системах. Поскольку существует только одна реализация, такое различие не требуется для ключевого слова.

62
27.01.2020, 19:31

Теги

Похожие вопросы