bash :экспортируемая функция не видна, но переменные видны

Если my_named_pipeсуществует в начале :, то есть ql_receiver_lock_holderне создает его, то он будет работать, иначе — нет.

В приведенных ниже примерах я удалил все ненужное. Вопрос очень общий, поэтому и ответ.

Это сработает:

a-process | another-process > "${my_named_pipe}"

Этого не будет:

a-process | another-process-that-also-creates-the-pipe > "${my_named_pipe}"

Причина

В первом ничто не мешает ему работать. Связанный вопрос в вопросе относится к стандарту перенаправления в (, а не к стандарту ). Подобно мудрому process1 > a-file | process2, process2не получит никаких входных данных.

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

2
17.09.2020, 01:34
1 ответ

Проблема

Соблюдать:

$ bash -c 'foobar () { :; }; export -f foobar; dash -c env' |grep foobar
$ bash -c 'foobar () { :; }; export -f foobar; bash -c env' |grep foobar
BASH_FUNC_foobar%%=() {  :
$ bash -c 'foobar () { :; }; export -f foobar; ksh93 -c env' |grep foobar
BASH_FUNC_foobar%%=() {  :
$ bash -c 'foobar () { :; }; export -f foobar; mksh -c env' |grep foobar
$ bash -c 'foobar () { :; }; export -f foobar; zsh -c env' |grep foobar
BASH_FUNC_foobar%%=() {  :
$ bash -c 'foobar () { :; }; export -f foobar; busybox sh -c env' |grep foobar
BASH_FUNC_foobar%%=() {  :

Переменные среды — это функция операционной системы Unix. Их поддержка идет вплоть до ядра :, когда программа вызывает другую программу (с системным вызовомexecve), одним из параметров вызова является новое окружение программы.

Встроенная -в команду exportв оболочках стиля sh -(dash, bash, ksh, … )вызывает использование переменной оболочки в качестве переменной среды, которая передается процессам, которые вызывает оболочка. И наоборот, когда вызывается оболочка, все переменные среды становятся переменными оболочки в этом экземпляре оболочки.

Экспортированные функции — это функция bash. Bash «экспортирует» функцию, создавая переменную окружения, имя которой происходит от имени функции и значением которой является тело функции (плюс заголовок и трейлер ). Вы можете видеть выше, как создается имя переменной среды :BASH_FUNC_, затем имя функции, затем %%.

Это имя не является допустимым именем для переменной оболочки. Напомним, что оболочки импортируют переменные среды как переменные оболочки при запуске. Различные оболочки по-разному ведут себя, когда имя переменной среды не является допустимой переменной оболочки. Некоторые передают переменную своим подпроцессам (выше :bash, ksh93, zsh, BusyBox ), в то время как другие передают только экспортированные переменные оболочки своим подпроцессам (выше :dash, mksh ), который эффективно удаляет переменные среды, имя которых не является допустимой переменной оболочки (не -пустой последовательностью букв ASCII, цифр и_).

Изначально bash использовал переменную окружения с тем же именем, что и функция,который в основном избежал бы этой проблемы. (Только в основном :имена функций могут содержать символы, которые не разрешены в именах переменных оболочки, например -. )Но у этого были и другие недостатки, такие как запрет на экспорт переменной оболочки и функции с тем же именем (, какая бы из них не была экспортирована последней, перезаписывала другую в среде ). Критически важно, что bash изменился, когда было обнаружено, что первоначальная реализация создала серьезную дыру в безопасности . (См. также Что означает env x=' (){ :;}; command' bash do и почему это небезопасно? , Когда появилась ошибка shellshock (CVE -2014 -6271/7169 )и какой патч полностью ее исправляет? , Как была обнаружена уязвимость Shellshock Bash?)Недостатком этого изменения является то, что экспортированные функции больше не проходят через некоторые программы, включая dash и mksh.

Ваша система, вероятно, имеет тире как /bin/sh. Это очень популярный выбор. /bin/shиспользуется очень часто, поэтому высока вероятность того, что где-то на пути вызова от исходного экземпляра bash, который запускал export -f _load_common, к экземпляру bash, который пытался использовать функцию, был вызов sh. __ENV_VARS_LOADED_MARKER_VARпрошел, потому что у него допустимое имя переменной, но BASH_FUNC__load_common%%не прошел.

Решение

Не использовать экспортированные функции. От них мало толку в первую очередь, а для вас они совершенно бесполезны. Единственным преимуществом экспорта функций является вызов bash без необходимости того, чтобы этот экземпляр bash считывал откуда-то определение функции, например, чтобы определить функцию в сценарии и передать ее экземпляру bash, вызванному из find -execили xargsили parallel. Но в вашем случае у вас уже есть код для чтения определения функции. Так что просто прочитайте определение функции безоговорочно. Удалите export -f _load_common, удалите __ENV_VARS_LOADED_MARKER_VARи просто вызовите source "$USER_ENVS".

1
18.03.2021, 23:04

Теги

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