zsh и POSIX эквивалент bash `{var}> & 1`

Если вы можете исходный код скрипта, вы можете его прочитать. cat / path / to / script отобразит содержимое script .

4
02.10.2018, 12:21
1 ответ

Поддержка {var}>...была добавлена ​​в ksh93, bashи zshодновременно по предложению разработчика zsh. Оператор {var}>...работает в zsh, но не для составных команд.

Также обратите внимание, что в:

cmd 3>&1

fd 3 открыт только для cmd, в

cmd {var}>&1

Динамически выделенный fd (, сохраненный в $var), остается открытым после того, как cmdвозвращается как в zsh, так и в bash. Этот оператор в основном предназначен для использования с exec(. См. также sysopenв zshдля более простого интерфейса к системному вызову open()).

Таким образом, в приведенном выше коде отсутствует exec {tmp}>&-для последующего освобождения этого fd в bash.

Так что здесь можно сделать:

if exec {tmp}>&1; then
   errors=$(exec 2>&1 >&"$tmp" {tmp}>&- && ls -ld /x /bin | tr o Z)
   exec {tmp}>&-
fi

Что будет работать в bash, zshи ksh93и не приведет к утечке fd. (кавычки вокруг $tmpнеобходимы только в bashи когда параметр posixне включен ). Обратите внимание, что в ksh93или когда zshили bashнаходятся в режиме POSIX,сбой execприводит к выходу оболочки(dup()сбой здесь может быть вызван закрытием stdout или некоторым ограничением на количество открытых файлов или другими патологическими случаями, для которых вы все равно можете выйти ).

Но здесь вам не нужен динамически выделяемый fd, просто используйте, например, fd 3, который не используется в этом коде:

{ errors=$(exec 2>&1 >&3 3>&-; ls -ld /x /bin | tr o Z); } 3>&1

Что будет работать в любой -Bourne-подобной оболочке.

Как и в описанном выше подходе с динамическим fd, даже если это не так очевидно, в случае сбояdup2()3>&1)назначение не будет выполнено, поэтому вы можете убедиться, что errorsинициализирован до (. ] с unset -v errors, например ).

Обратите внимание, что не имеет значения, открыт ли fd 3 иным образом или используется в остальной части скрипта (, исходный fd, если он открыт, останется нетронутым и будет восстановлен в конце ). ожидает ли код, встроенный в $(...), открытость fd 3.

Ожидается, что только fds 0, 1 и 2 будут открыты приложениями, другие fds — нет. lsи trничего не ожидают от fd 3. Случаи, когда вам может понадобиться использовать другой fd, — это когда ваш код явно использует этот fd и ожидает, что он был открыт заранее например, если бы вместо lsу вас было cat /dev/fd/3, где ожидается, что fd 3 был открыт для какого-то ресурса где-то ранее в вашем скрипте.

Чтобы ответить на вопрос о том, как назначить первый свободный fd в оболочках POSIX, я не думаю, что есть способ с помощью оболочки POSIX и API утилит. Это также может не иметь смысла. Оболочка может делать то, что она хочет внутри, с любым fd при условии, что это не мешает ее собственному API. Например, вы можете обнаружить, что fd 11 сейчас свободен, но позже может использоваться оболочкой для чего-то внутреннего, и ваши записи в него могут повлиять на его поведение. Также обратите внимание, что в POSIX sh вы можете манипулировать только fds от 0 до 9.

12
27.01.2020, 20:47

Теги

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