Bash Tab Completion: '-bash: неожиданный EOF при поиске соответствия `)' -bash: синтаксическая ошибка: неожиданный конец файла

18

Я пытаюсь войти в irbсеанс с определенными переменными среды из файла с помощью этой команды:

$ env $(cat env.sh) irb

Но когда я пытаюсь нажать Tabпосле ввода, env.чтобы завершить его, я получаю следующую ошибку:

$ env $(cat env.-bash: unexpected EOF while looking for matching `)'
-bash: syntax error: unexpected end of file

Еще одна интересная вещь: если я вошел в систему как root, эта ошибка не возникает.

Вот вывод find ~ -uid 0:

$ find ~ -uid 0
/home/(redacted)/.rpmdb
/home/(redacted)/.rpmdb/Group
/home/(redacted)/.rpmdb/Conflictname
/home/(redacted)/.rpmdb/Installtid
/home/(redacted)/.rpmdb/Sha1header
/home/(redacted)/.rpmdb/Providename
/home/(redacted)/.rpmdb/__db.002
/home/(redacted)/.rpmdb/Requirename
/home/(redacted)/.rpmdb/Sigmd5
/home/(redacted)/.rpmdb/__db.001
/home/(redacted)/.rpmdb/Obsoletename
/home/(redacted)/.rpmdb/.dbenv.lock
/home/(redacted)/.rpmdb/Name
/home/(redacted)/.rpmdb/Basenames
/home/(redacted)/.rpmdb/Triggername
/home/(redacted)/.rpmdb/Packages
/home/(redacted)/.rpmdb/Dirnames
/home/(redacted)/.rpmdb/__db.003

Может кто-нибудь объяснить мне, почему это происходит, и если да, то как мне это исправить, когда я не являюсь пользователем root?

eldosoa
источник
Как войти в систему как root?
Муру
@muru Я вошел в систему как root sudo su.
Элдосоа
Пожалуйста, отредактируйте свой вопрос, чтобы добавить вывод find ~ -uid 0.
Муру
@muru Готово. Добавил вывод в мой вопрос.
Eldosoa
Извините за это, но не как root! Я имел в виду как ваш обычный пользователь, так что ~это /home/something.
Муру

Ответы:

33

Вы нашли ошибку в библиотеке Bash Completion, используемой Ubuntu.

Что это значит?

Ubuntu использует библиотеку завершения bash, чтобы сделать завершение bash разумным. Эта библиотека живет в /usr/share/bash-completion/bash_completion.

По сути, эта библиотека объявляет несколько умных функций, которые знают о типичных командах и о том, как их выполнять. Всякий раз, когда вы нажимаете Tab, функции в этой библиотеке вызывают и пытаются завершить текущую командную строку. Так, например, если вы напечатаете, apt-get iTabэто завершит это до apt-get install. Если вы не используете эту библиотеку, у вас есть только стандартное примитивное завершение bash - так, например, если вы печатаете apt-get iTabбез использования источника, bash просто ищет файлы в текущем каталоге, начиная с, iи пытается выполнить команду в соответствии с эти имена файлов.

Почему это не происходит как root?

Потому что когда вы используете sudo suдля создания себя root, библиотека завершения bash не поставляется. Это было бы иначе, если бы ты sudo -iделал сам root. Бьюсь об заклад, вы видите ошибку, не так ли? Посмотрите, например, «sudo su -» против «sudo -i» против «sudo / bin / bash» - когда имеет значение, какой используется, или имеет значение вообще? если вы не знакомы с различиями.

В моем случае, как обычный пользователь, библиотека получает исходный код, когда я запускаю оболочку Bash из-за ~/.bashrcисточников, /etc/bash_completionкоторые являются источниками /usr/share/bash-completion/bash_completion.

Если я использую sudo -iдля входа в систему root, библиотека получает из-за /etc/profileисточников, /etc/profile.d/bash_completion.shкоторые источники /usr/share/bash-completion/bash_completion.

Почему эта ошибка происходит?

Попробуйте выполнить эту команду:

$ eval 'quoted=$(cat' env.
bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file

Выглядит знакомо? ;-) Действительно, именно это и произошло, когда вы попали Tabв контекст, который вы описали. Точнее, ошибка в _quote_readline_by_refобъявленной функции /usr/share/bash-completion/bash_completion. Если вы получили этот файл, у вас должна быть доступна эта функция. Итак, попробуйте следующее:

$ _quote_readline_by_ref '$(cat env.' quoted
bash: unexpected EOF while looking for matching `)'
bash: syntax error: unexpected end of file

Учитывая эти аргументы, функция _quote_readline_by_refвыполняет, помимо прочего, что evalупомянуто выше. Вы можете посмотреть, если хотите. И когда вы печатаете env $(cat env.Tab, за кулисами эта функция вызывается именно с этими аргументами. Так вот что случилось.

Этот evalхак должен был исправить другую проблему , но я предполагаю, что в процессе появилась другая ошибка.

Как мне это исправить?

Оказывается, об этой ошибке уже сообщалось . После прочтения этого сообщения об ошибке я вижу три способа исправить это:

  1. Исправьте это: в одном из комментариев в этом отчете об ошибках кто-то предлагает заменить строку

    [[ ${!2} == \$* ]] && eval $2=${!2}

    внутри функции _quote_readline_by_refв файле /usr/share/bash-completion/bash_completionпо строке

    [[ ${!2} == \$\'* ]] && eval $2=${!2}

    Я рекомендую не делать этого. Человек, написавший этот комментарий, не является разработчиком bash-complete . Это исправление просто приведет к тому, что левый операнд оператора оценивается как ложное, и, таким образом, предотвратит это eval. Однако без хорошего знания того, что эта функция должна делать и в каких контекстах она вызывается, неясно, не нарушит ли она какую-либо другую предполагаемую функциональность.

  2. Получите самую последнюю версию: Как также упоминалось в этом отчете об ошибке, эта ошибка отсутствует в git head (где, помимо других изменений, функция _quote_readline_by_refбыла упрощена). Вы можете просто клонировать текущую ревизию из Git:

    git clone https://salsa.debian.org/debian/bash-completion.git

    ... и затем скопируйте самую новую версию bash_completionскрипта в /usr/share/bash-completion(нет необходимости в срочном резервном копировании старой версии, если это не заставит вас чувствовать себя в безопасности - если у вас возникнут какие-то проблемы, sudo apt-get install --reinstall bash-completionследует отменить любые внесенные вами изменения.) Так я рекомендую, если вы спешите исправить это. :-)

Обратите внимание, что ни одно из этих решений не выполнит завершение bash внутри подстановки команд: как упоминалось в том же отчете об ошибках, это не работает в Bash 4.3.

  1. Расслабьтесь и подождите: рано или поздно выйдет новая версия (которая может даже исправить завершение bash в подстановке команд), и вы получите ее с какой-то будущей версией Ubuntu. Вот для чего я иду ;-)
Malte Skoruppa
источник
1
@ con-f-use Да, вот и все! Репозиторий Git также связан с основным сайтом bash-complete, поэтому я не ссылался на него в своем ответе.
Malte Skoruppa
2
@ con-f-use Ваш комментарий заставил меня еще немного изучить эту ошибку. Оказывается, это не было и никогда не было ошибкой вверх по течению. Вместо этого, это на самом деле ошибка, представленная патчем Ubuntu, примененным к предыдущей версии. Пока что никто не сузил эту ошибку до этого конкретного патча. Поэтому я сообщил о своем обнаружении в соответствующем отчете об ошибке в Ubuntu: bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1312243 .
Malte Skoruppa
2
Хорошая работа, Мальте.
Барри Келли
1
Спасибо за объяснение. На момент написания этой статьи версия git head устраняла ошибку и выполняла автозаполнение по желанию. РЕДАКТИРОВАТЬ: на самом деле, не важно, это не так.
user3391564
1
@MaxvonHippel Я сказал , что , когда вы используете , sudo suчтобы стать корнем, не подключит библиотеку, но он будет получать источники , когда вы используете sudo -iвместо этого, что предполагаемый способ получить интерактивный корневой сеанс. Что касается вашего вопроса: поскольку любая оболочка bash читает, ~/.bashrcчто в конечном итоге является источником библиотеки, и нет никакого способа «удалить исходный код» файла, я не вижу абсолютно простого способа. Вот возможный хак: сделайте источник библиотеки условным для некоторой переменной среды, скажем NOCOMPL, не определяемой в вашем ~/.bashrc,
Малте Скорупа,