Почему у меня ошибка "join: extra operand '/dev/fd/62'"?

Это проблема с идентификацией пользователя в протоколе NFS. Как это работает, зависит от того, какую версию NFS вы используете.

В NFSv3 имена пользователей и пароли не являются частью протокола; вместо этого используются номера UID и GID. Если пользователя с UID = 1000 на машине a называют bart , а пользователя с таким же uid на машине b называют homer , то bart может читать файлы, созданные пользователем homer на машине b.Это одна из причин, по которой синхронизация UID обычно является хорошей идеей при использовании NFS.

Однако NFSv4 многое из этого изменил. В NFSv4 имя пользователя и группы передаются не только по номерам UID, но и по сети. Чтобы это работало правильно, протокол NFSv4 существенно изменил несколько вещей:

  • Протокол требует, чтобы все имена пользователей существовали на всех машинах. То есть, если у клиента есть пользователь bart , сервер должен также иметь пользователя bart (их UID могут отличаться). Если в каком-либо из них отсутствует указанный пользователь, то все вернется к пользователю и группе никто и / или nogroup .
  • Протокол имеет понятие «домен». По умолчанию это имя домена (т. Е. Полное доменное имя компьютера, на котором вы работаете, за вычетом имени хоста), но может быть произвольной строкой. Домены используются для разделения машин с разными наборами пользователей. Если домен на клиенте не совпадает с доменом на сервере, тогда система предполагает, что пользователь bart на машине a полностью отличается bart от пользователя на машине. б.

Для получения более подробной информации прочтите справочную страницу rpc.idmapd (8) (которая документирует реализацию протокола сопоставления идентификаторов в Linux).

До недавнего времени большинство дистрибутивов Linux использовали по умолчанию NFSv3, если вы явно не запрашивали иное. Однако через несколько лет настройки по умолчанию меняются на NFSv4.

Чтобы все заработало, у вас есть два варианта:

  1. Вернуться к NFSv3.Это можно сделать с помощью параметра монтирования nfsvers = 3 .
  2. Выясните, почему rpc.idmapd не делает то, что вы ожидаете, и возитесь с ним, пока он не сделает.

Очевидно, что путь наименьшего сопротивления равен 1. Однако NFSv4 имеет ряд полезных функций по сравнению с набором функций NFSv3, и вы потеряете их, отказавшись от него.

1
24.07.2018, 08:40
1 ответ

"$outer" — скалярная переменная в кавычках, поэтому она всегда расширяется до одного аргумента. Если он пуст или не установлен, он все равно расширяется до одного пустого аргумента до join(, и когда вы вызываете свой скрипт с -o2, это один аргумент -a 2вместо двух аргументов -aи2).

Ваш join, вероятно, является GNU joinв том смысле, что он принимает параметры после не -аргументов параметров. Этот "$outer"не является аргументом опции -, когда он пуст, поскольку он не начинается с -, поэтому он обрабатывается как имя файла, а joinжалуется на предоставленное третье имя файла, которого он не ожидает.

Если вам нужна переменная с переменным количеством аргументов, используйте массив:

outer=()
...
(o)
   outer=(-a "$OPTARG");;

...
join "${outer[@]}"

Хотя и тут можно:

outer=
...
(o)
   outer="-a$OPTARG";;
...
join ${outer:+"$outer"}... <(sort < "$f1") <(sort < "$f2")

Или:

unset -v outer
...
(o)
   outer="$OPTARG";;
...
join ${outer+-a "$outer"}...

(что он не работает в zsh, за исключением эмуляции sh/ksh ).

Некоторые другие примечания:

  • join -t '\t'не работает. Вам понадобится delim=$'\t'для хранения литерала TAB в$delim
  • Не забывайте использовать --при передаче произвольных аргументов командам (или используйте перенаправления там, где это возможно ). Итак, sort -- "$f1"или лучше sort < "$f1"вместо sort "$f1".
  • арифметические расширения также могут быть разделены + glob, поэтому их также следует заключать в кавычки.(shift "$((OPTIND - 1))")(здесь не проблема, поскольку вы используете bash, который не наследует $IFSот среды, и вы не модифицируете IFSранее в скрипте, но все же хорошая практика ).
4
27.01.2020, 23:18

Теги

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