ZSH в Linux не распознает допустимые параметры в сценарии оболочки - PullRequest
0 голосов
/ 02 декабря 2018

zsh не распознает параметры, заданные с помощью -o, но только , когда он в шебанге, и на Linux.

Следующий скрипт не работает на zsh 5.0.2, zsh 5.6 и последний git:

#!/bin/zsh -o pipefail
thiswillfail | echo 'hello, world'
echo $?
exit

Ожидаемый вывод

hello, world
/home/prajjwal/script:2: command not found: thiswillfail
127

Фактический вывод

/bin/zsh: no such option:  pipefail

Что работает

  • Скрипт на zsh 5.3 на MacOS Mojave.Похоже, что это происходит с ошибкой на всех Linux версиях, которые я до сих пор пробовал.
  • Ручной вызов /bin/zsh -o pipefail на терминале
  • Установка параметра с помощью set -o pipefail после шебанга в сценарии.

То, что я пробовал

  • Очистка моих .zshrc для обеспечения одного измои настройки не вызывают этого.

В стороне

Пока я только пытаюсь заставить работать pipefail, это отказывается работать с любымдругие параметры, которые я пытаюсь установить, хотя все они упоминаются в zshoptions.

1 Ответ

0 голосов
/ 02 декабря 2018

Это ловушка попыток установить параметры в строке #!.Ядро разбивает строку shebang только на первый пробел.

Когда вы говорите

#!/bin/zsh -o pipefail

, команда, которая заканчивается выполнением, является "/bin/zsh" "-o pipefail" "/home/prajjwal/script".

Ошибкасообщение говорит, что " pipefail" (обратите внимание на начальный пробел) не является допустимой опцией, которая является правильной: допустим только "pipefail".

В этом случае возможный обходной путь - собрать все в одну командную строкуаргумент:

#!/bin/zsh -opipefail

Но в целом это невозможно, и интерфейс #! не позволяет передавать более одного дополнительного аргумента, поэтому вы можете найти другие обходные пути (например, используя set вручную) или написать скрипт-обертку:

#!/bin/zsh
exec /bin/zsh -o pipefail /path/to/the/real/script

В некоторых системах доступна другая альтернатива: env -S.Эта опция не указана в POSIX и доступна не во всех системах.Он работает на системах с использованием инструментов GNU (включая все стандартные дистрибутивы Linux) и FreeBSD , но не OpenBSD или NetBSD .Я не смог найти никакой информации о MacOS.

(Примечание: GNU env также поддерживает --split-string в качестве альтернативного (длинного) имени опции, но FreeBSD env нет.)

Использование:

#!/usr/bin/env -S /bin/zsh -o pipefail

Это вызывает env с одним длинным аргументом ('-S /bin/zsh -o pipefail').Обработка стандартного параметра обрабатывает его как параметр -S, за которым следует аргумент (' /bin/zsh -o pipefail').

В таком простом случае, как этот, env -S разбивает аргумент на пробелы / табуляции и обрабатывает полученный список какесли она изначально была частью исходной командной строки:

env -S ' /bin/zsh -o pipefail'
# works the same as:
env /bin/zsh -o pipefail

В менее простых случаях вам придется заключать в кавычки некоторые символы (env -S обрабатывает пробелы, ", ', \, $ специально, среди прочих).В частности, он не работает как цитирование оболочки.Подробнее см. На страницах руководства, ссылки на которые приведены выше.

...