Uzupełnianie zakładki Bash: '-bash: nieoczekiwany EOF podczas wyszukiwania pasującego `)' -bash: błąd składni: nieoczekiwany koniec pliku

18

Próbuję przejść do irbsesji z określonymi zmiennymi środowiskowymi z pliku za pomocą tego polecenia:

$ env $(cat env.sh) irb

Ale kiedy próbuję nacisnąć Tabpo wpisaniu, env.aby go ukończyć, pojawia się następujący błąd:

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

Inną interesującą rzeczą jest to, że jeśli jestem zalogowany jako root, ten błąd nie występuje.

Oto wynik 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

Czy ktoś może mi wyjaśnić, dlaczego tak się dzieje, a jeśli tak, to jak to naprawić, gdy nie jestem użytkownikiem root?

Eldosoa
źródło
Jak zalogować się jako root?
muru
@muru Zalogowałem się do roota za pomocą sudo su.
eldosoa,
Edytuj swoje pytanie, aby dodać wynik find ~ -uid 0.
muru
@muru Gotowe. Dodano wynik w moim pytaniu.
eldosoa
Przepraszam za to, ale nie jako root! Chodziło mi jako zwykły użytkownik, tak że ~jest /home/something.
muru

Odpowiedzi:

33

Znalazłeś błąd w bibliotece Bash Completion używanej przez Ubuntu.

Co to znaczy?

Ubuntu wykorzystuje bibliotekę zakończenia bash, aby uczynić zakończenie bash inteligentnym. Ta biblioteka mieszka /usr/share/bash-completion/bash_completion.

Zasadniczo ta biblioteka deklaruje kilka sprytnych funkcji, które znają typowe polecenia i jak je wykonać. Po każdym naciśnięciu Tabwywoływane są funkcje w tej bibliotece i podejmowane są próby uzupełnienia bieżącego wiersza poleceń. Na przykład, jeśli wpiszesz apt-get iTab, dokończy to apt-get install. Jeśli nie podasz tej biblioteki, masz tylko standardowe, prymitywne uzupełnianie basha - więc na przykład, jeśli wpiszesz apt-get iTabbez źródła, bash po prostu wyszuka pliki w bieżącym katalogu zaczynając od ii spróbuje wykonać polecenie zgodnie z te nazwy plików.

Dlaczego to się nie dzieje jako root?

Ponieważ kiedy używasz sudo susiebie root, biblioteka ukończenia bash nie jest pozyskiwana. Byłoby inaczej, gdybyś sudo -isam się tworzył root. Założę się, że widzisz wtedy błąd, prawda? Zobacz na przykład „sudo su -” vs ”sudo -i” vs „sudo / bin / bash” - kiedy ma to znaczenie, które jest używane, czy w ogóle ma znaczenie? jeśli nie znasz różnic.

W moim przypadku, jako zwykły użytkownik, biblioteka jest pozyskiwana, gdy uruchamiam powłokę Bash, ponieważ ~/.bashrcźródła, /etc/bash_completionktóre źródła /usr/share/bash-completion/bash_completion.

Jeśli użyję sudo -ido logowania jako root, biblioteka jest pozyskiwana, ponieważ /etc/profileźródła, /etc/profile.d/bash_completion.shktóre źródła /usr/share/bash-completion/bash_completion.

Dlaczego ten błąd się dzieje?

Spróbuj wykonać to polecenie:

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

Wygląda znajomo? ;-) Rzeczywiście, dokładnie tak stało się za kulisami, kiedy trafiłeś Tabw opisany kontekst. Dokładniej, błąd występuje w funkcji _quote_readline_by_refzadeklarowanej przez /usr/share/bash-completion/bash_completion. Jeśli pozyskałeś ten plik, powinieneś mieć dostęp do tej funkcji. Następnie spróbuj tego:

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

Biorąc pod uwagę te argumenty, funkcja _quote_readline_by_refspełnia, między innymi, evalwspomniane powyżej. Możesz spojrzeć, jeśli chcesz. A kiedy piszesz env $(cat env.Tab, za kulisami funkcja jest wywoływana z dokładnie tymi argumentami. Tak się stało.

Ten evalhack miał naprawić inny problem , ale wydaje mi się, że wprowadził ten drugi błąd w tym procesie.

Jak to naprawić?

Okazuje się, że ten błąd został już zgłoszony . Po przeczytaniu tego raportu o błędach widzę trzy sposoby, aby to naprawić:

  1. Popraw to: w jednym z komentarzy w tym raporcie o błędzie ktoś sugeruje zastąpienie linii

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

    w ramach funkcji _quote_readline_by_refw pliku /usr/share/bash-completion/bash_completionprzy linii

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

    Nie polecam tego robić. Osoba, która napisała ten komentarz, nie wydaje się być twórcą bash-uzupełniania . Ta poprawka po prostu spowoduje, że lewy argument instrukcji będzie miał wartość false, a tym samym zapobiegnie temu eval. Jednak bez dobrej wiedzy o tym, co ta funkcja ma robić i w jakich kontekstach się nazywa, nie jest jasne, czy nie spowoduje to potencjalnej awarii innych zamierzonych funkcji.

  2. Pobierz najnowszą wersję: Jak wspomniano również w tym raporcie o błędach, ten błąd nie występuje w git head (gdzie między innymi zmiany _quote_readline_by_refzostały uproszczone). Możesz po prostu sklonować bieżącą wersję z Git:

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

    ... a następnie skopiuj najnowszą wersję bash_completionskryptu na /usr/share/bash-completion(nie ma potrzeby pilnego tworzenia kopii zapasowej starej wersji, chyba że czujesz się bezpieczniej - jeśli wystąpią problemy, sudo apt-get install --reinstall bash-completionpowinieneś cofnąć wszelkie zmiany, które wprowadziłeś). zalecamy, jeśli spieszysz się, aby to naprawić. :-)

Zauważ, że żadne z tych rozwiązań nie spowoduje zakończenia bashu w ramach zastępowania poleceń: jak wspomniano w tym samym raporcie o błędzie, jest to zepsute w Bash 4.3.

  1. Usiądź i poczekaj: wcześniej czy później zostanie wydana nowa wersja (która może nawet naprawić uzupełnianie basha w ramach zastępowania poleceń), a otrzymasz ją w przyszłej wersji Ubuntu. Po to idę ;-)
Malte Skoruppa
źródło
1
@ con-f-use Tak, to wszystko! Repozytorium Git jest również linkowane z głównej strony bash-complete, dlatego nie podłączyłem się do niego w mojej odpowiedzi.
Malte Skoruppa
2
@ con-f-use Twój komentarz skłonił mnie do dalszych badań tego błędu. Okazuje się, że nie jest i nigdy nie był błędem poprzedzającym. Zamiast tego jest to w rzeczywistości błąd wprowadzony przez łatkę Ubuntu zastosowaną przeciwko wcześniejszej wersji. Jak dotąd nikt nie zawęził tego błędu do tej konkretnej łatki. Tak więc zgłosiłem swoje odkrycie w odpowiednim raporcie o błędzie Ubuntu: bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1312243 .
Malte Skoruppa
2
Dobra robota, Malte.
Barry Kelly,
1
Dziękuję za wyjaśnienie. W tym momencie wersja git head usunęła błąd i autouzupełnianie zgodnie z życzeniem. EDYCJA: właściwie nieważne, nie ma.
user3391564
1
@MaxvonHippel Powiedziałem, że kiedy użyjesz sudo suroota, nie pobiera on biblioteki, ale będzie pozyskiwany, gdy go użyjesz sudo -i, co jest zamierzonym sposobem uzyskania interaktywnej sesji rootowania. Jeśli chodzi o twoje pytanie: ponieważ jakakolwiek powłoka bash czyta, ~/.bashrcco ostatecznie pobiera bibliotekę, i nie ma sposobu na „cofnięcie źródła” pliku, nie widzę całkowicie prostego sposobu. Oto możliwe Hack: Dokonać pozyskiwania warunkowego biblioteki na jakiejś zmiennej środowiskowej, powiedzmy NOCOMPL, nie jest zdefiniowana na liście ~/.bashrc...
Malte Skoruppa