По-видимому, в nix существует проблема. Существует проблема на github с предлагаемым обходным решением путем установки переменной LOCALE_ARCHIVE
.
Если у вас уже установлен nix, просто сделайте:
nix-env -i glibc-locales
И в профиле bash:
export LOCALE_ARCHIVE="$(nix-env --installed --no-name --out-path --query glibc-locales)/lib/locale/locale-archive"
Вы упускаете из виду, что команда {
запускается с нулевым stderr
, она запускает содержащиеся фоновые команды с восстановленным fd, но это та команда, которая запускает команды и выдает команду -, запускает сообщения обратной связи, и он работает с нулевым.
Вы упустили самый важный момент, перенаправление оболочки применяется по порядку слева направо.
В:
{ 2>&3 "$@"& } 3>&2 2>/dev/null
Вся групповая команда запускается с:
Таким образом, при выполнении команды внутри группировки:
Таким образом, если "$@"&
выводит что-либо со стандартной ошибкой, вывод выводится на терминал.
Для ваших конкретных случаев:
{ grep warning system.log& } 2>/dev/null
{ grep warning system.log& }
работает со стандартной ошибкой, указывает на /dev/null
. grep
не отменяет никакого перенаправления, поэтому его стандартная ошибка аналогична {...}
и перенаправляется на /dev/null
, вы не получаете вывода на терминал.
В:
{ 2>&3 grep warning system.log& } 3>&2 2>/dev/null
Стандартная ошибкаgrep
перенаправляется на дескриптор файла 3, который указывает на терминал, как описано выше, поэтому вы получаете вывод на терминал.
В интерактивном Bash foo &
запускает foo
в фоновом режиме и выводит идентификатор задания и идентификатор процесса в стандартную ошибку оболочки.
foo 2>/dev/null &
запускает foo
в фоновом режиме, stderr перенаправляется на /dev/null
, но по-прежнему выводит идентификатор задания и идентификатор процесса в стандартную ошибку оболочки (, а не на перенаправленный stderr из foo
).
{ foo & } 2>/dev/null
сначала перенаправляет stderr на /dev/null
, затем внутренняя часть {}
обрабатывается с применением этого перенаправления. Затем foo
запускается в фоновом режиме, и идентификатор задания и идентификатор процесса печатаются в , теперь перенаправленный stderr оболочки (, то есть в/dev/null
).
When commands are grouped, redirections may be applied to the entire command list.
Мы можем проверить примененное перенаправление, группа также перенаправляет вывод идентификатора задания:
$ { sleep 9 & } 2> temp [ no output here ] $ cat temp [1] 8490
Когда команда в конце концов завершается, уведомление об этом появляется на терминале, однако:(Или, скорее, в текущем стандартном потоке командной строки, чем бы он ни был.)
$ kill %1
[1]+ Terminated sleep 99
В {... } 3>&2 2>/dev/null
fd 3 перенаправляется туда, куда всегда указывает stderr, а затем stderr перенаправляется на /dev/null
. Предполагая, что stderr изначально указывал на терминал, результатом будет 3 -> terminal, 2 -> /dev/null
. Эти перенаправления применяются к группе.
Если у нас есть { foo 2>&3 & }
внутри группы, foo
запускается в фоновом режиме, его stderr указывает на fd 3 группы, а идентификатор задания и идентификатор процесса печатаются в stderr группы.
Сложив эти два вместе, foo
stderr указывает на то место, куда указывает fd 3 группы, т. е. исходный stderr, а идентификатор задания печатается в fd 2 группы, т. е. /dev/null
.
Таким образом, по сути, { 2>&3 foo & } 3>&2 2>/dev/null
перенаправляет идентификатор задания и идентификатор процесса, напечатанный оболочкой, на /dev/null
и направляет foo
stderr в обход этого перенаправления:
foo's stdout -> group's fd 1 -> original stdout (never redirected)
foo's stderr -> group's fd 3 -> original stderr
job id from group -> group's fd 2 -> /dev/null