Замена двойного процесса Bash дает неверный файловый дескриптор

Когда я пытаюсь сослаться на два канала замены процесса в функции bash, работает только первый из них. Второй выдает ошибку «плохой дескриптор файла», например:

$ foo(){
> cat "$1"
> cat "$2"
> }
$ foo <(echo hi) <(echo bye)
hi
cat: /dev/fd/62: Bad file descriptor
$ 

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

Любые идеи о том, что я делаю неправильно? FWIW Я делаю это, чтобы сделать оболочку для использования графического инструмента Mac OS X FileMerge diff вместо инструмента командной строки, который уже с удовольствием работает с несколькими каналами из командной строки.

-Роб


person rharder    schedule 01.10.2012    source источник


Ответы (4)


Во-первых, я думаю, что @Michael Krelin прав в том, что это связано с версией bash, поставляемой с OS X (v3.2.48). Из моего тестирования видно, что файловые дескрипторы отбрасываются после первой внешней команды, которую выполняет функция:

$ bar() { echo "Args: $*"; echo "First ext command:"; ls /dev/fd; echo "Second ext command:"; ls /dev/fd; }
$ bar <(echo hi) <(echo bye)
Args: /dev/fd/63 /dev/fd/62
First ext command:
0   1   2   3   4   5   6   62  63
Second ext command:
0   1   2   3   4   5   6

Обратите внимание, что /dev/fd/62 и 63 исчезают между двумя листингами ls. Я думаю, что нашел обходной путь: скопируйте хрупкие fd в нехрупкие fd, прежде чем они исчезнут:

$ baz() { exec 3<"$1" 4<"$2"; ls /dev/fd; ls /dev/fd; cat /dev/fd/3; cat /dev/fd/4; }
$ baz <(echo hi) <(echo bye)
0   1   2   3   4   5   6   62  63
0   1   2   3   4   5   6
hi
bye
person Gordon Davisson    schedule 01.10.2012
comment
отличный обходной путь. Да, извините, что не указал, но странное поведение было в OS X 10.8. Я заметил, что это странное поведение также не происходило в cygwin. Я, вероятно, переключусь на macports bash, если он работает правильно. - person rharder; 01.10.2012

/bin/bash, поставляемый с OSX (3.2.48), не работает. Один из macports (4.2.37 — обычно /opt/local/bin/bash, если он у вас установлен) работает нормально. Является ли это версией или сборкой, я не знаю. Возможно, вы захотите использовать macports bash для этого скрипта. На каждом Mac обязательно должен быть macport, так что я предполагаю, что у вас есть ;-)

person Michael Krelin - hacker    schedule 01.10.2012
comment
Да, macports bash исправил это для меня. Я обновлю свой логин терминала. Спасибо! - person rharder; 02.10.2012

Вы уверены, что запускаете его с помощью bash, а не какой-либо другой оболочки? Вы проверили вывод echo $SHELL?

У меня отлично работает с помощью bash:

[16:03:51][tim@tim(1)]:~
(0)$function foo() { cat "$1"; cat "$2"; };
[16:03:59][tim@tim(1)]:~
(0)$foo <(echo "lva") <(echo hi)
lva
hi

Например, когда я меняю shebang на #!/bin/dash, я получаю ошибки.

Пожалуйста, попробуйте поставить #!/bin/bash как шебанг в первой строке вашего скрипта.

person Tim Lamballais    schedule 01.10.2012
comment
Это не ответ ... Я только что проверил - он работает на Linux и не работает на OSX, которая, похоже, является платформой OP. - person Michael Krelin - hacker; 01.10.2012

Похоже, проблема здесь: http://bugs.alpinelinux.org/issues/1465

person estani    schedule 27.11.2012