Bash Tab Hoàn thành: '-bash: EOF bất ngờ trong khi tìm kiếm khớp `)' -bash: lỗi cú pháp: kết thúc tệp không mong muốn


18

Tôi đang cố gắng đi vào một irbphiên với các biến môi trường cụ thể từ một tệp bằng lệnh này:

$ env $(cat env.sh) irb

Nhưng khi tôi thử nhấn Tabsau khi tôi gõ env.để hoàn thành nó, tôi gặp lỗi sau:

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

Một điều thú vị nữa là nếu tôi đăng nhập bằng root, lỗi này không xảy ra.

Đây là đầu ra của 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

Bất cứ ai có thể giải thích cho tôi tại sao điều này xảy ra và nếu vậy, làm cách nào để khắc phục nó khi tôi không phải là người dùng root?


Làm thế nào để bạn đăng nhập như root?
muru

@muru Tôi đăng nhập vào root bằng sudo su.
eldosoa

Vui lòng chỉnh sửa câu hỏi của bạn để thêm đầu ra của find ~ -uid 0.
muru

@muru Xong. Đã thêm đầu ra trong câu hỏi của tôi.
eldosoa

Xin lỗi về điều đó, nhưng không phải là root! Tôi có nghĩa là người dùng bình thường của bạn, vì vậy đó ~/home/something.
muru

Câu trả lời:


33

Bạn đã tìm thấy một lỗi trong thư viện Bash Completeion được sử dụng bởi Ubuntu.

Điều đó có nghĩa là gì?

Ubuntu sử dụng thư viện hoàn thành bash để làm cho bash hoàn thành thông minh. Thư viện này sống trong /usr/share/bash-completion/bash_completion.

Về cơ bản, thư viện này tuyên bố một vài chức năng thông minh biết về các lệnh điển hình và cách hoàn thành chúng. Bất cứ khi nào bạn nhấn Tab, các chức năng trong thư viện này sẽ được gọi và cố gắng hoàn thành dòng lệnh hiện tại của bạn. Vì vậy, ví dụ nếu bạn gõ apt-get iTabnó sẽ hoàn thành nó apt-get install. Nếu bạn không tìm nguồn thư viện đó, bạn chỉ có hoàn thành bash tiêu chuẩn, nguyên thủy - vì vậy, ví dụ nếu bạn nhập apt-get iTabmà không có nguồn gốc, bash sẽ chỉ tìm các tệp trong thư mục hiện tại bắt đầu ivà cố gắng hoàn thành lệnh của bạn theo những tên tập tin

Tại sao nó không xảy ra như root?

Bởi vì khi bạn sử dụng sudo suđể tự tạo root, thư viện hoàn thành bash không có nguồn gốc. Điều này sẽ khác nếu bạn sử dụng sudo -iđể làm cho chính mình root. Tôi cá là bạn đã thấy lỗi rồi phải không? Xem ví dụ 'sudo su -' vs 'sudo -i' vs 'sudo / bin / bash' - khi nào nó quan trọng được sử dụng, hoặc nó có vấn đề gì không? nếu bạn không quen với sự khác biệt.

Trong trường hợp của tôi, là một người dùng bình thường, thư viện có nguồn gốc khi tôi khởi động shell Bash vì ~/.bashrcnguồn /etc/bash_completionnào là nguồn /usr/share/bash-completion/bash_completion.

Nếu tôi sử dụng sudo -iđể đăng nhập như root, thư viện sẽ có nguồn gốc vì /etc/profilenguồn /etc/profile.d/bash_completion.shnào là nguồn /usr/share/bash-completion/bash_completion.

Tại sao lỗi đó xảy ra?

Hãy thử thực hiện lệnh này:

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

Trông quen quen? ;-) Thật vậy, đó chính xác là những gì đã xảy ra đằng sau hậu trường khi bạn nhấn Tabvào bối cảnh bạn mô tả. Chính xác hơn, lỗi nằm trong hàm được _quote_readline_by_refkhai báo bởi /usr/share/bash-completion/bash_completion. Nếu bạn có nguồn đó, bạn nên có sẵn chức năng đó. Vì vậy, hãy thử tiếp theo:

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

Với các đối số này, hàm _quote_readline_by_refthực hiện, trong số những thứ khác, evalđược đề cập ở trên. Bạn có thể có một cái nhìn nếu bạn thích. Và khi bạn gõ env $(cat env.Tab, đằng sau hậu trường mà hàm đó được gọi với chính xác những đối số đó. Vì vậy, đó là những gì đã xảy ra.

Bản evalhack này được cho là để khắc phục một vấn đề khác , nhưng tôi đoán nó đã giới thiệu lỗi khác trong quá trình này.

Làm thế nào để tôi sửa nó?

Hóa ra lỗi này đã được báo cáo . Sau khi đọc báo cáo lỗi đó, tôi thấy ba cách để sửa nó:

  1. Vá nó: Trong một trong những bình luận trong báo cáo lỗi đó, ai đó đề nghị thay thế dòng

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

    trong chức năng _quote_readline_by_reftrong tập tin /usr/share/bash-completion/bash_completiontheo dòng

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

    Tôi khuyên bạn không nên làm điều này. Người viết bình luận đó dường như không phải là nhà phát triển hoàn thành bash . Hotfix này chỉ đơn giản sẽ làm cho toán hạng bên trái của câu lệnh đánh giá thành sai và do đó ngăn điều đó evalxảy ra. Tuy nhiên, nếu không có kiến ​​thức tốt về chức năng đó được cho là sẽ làm gì và trong bối cảnh nào nó được gọi, thì không rõ liệu điều này sẽ không có khả năng phá vỡ một số chức năng dự định khác.

  2. Nhận phiên bản mới nhất: Như đã đề cập trong báo cáo lỗi đó, lỗi này không có trong đầu git (trong đó các thay đổi khác, chức năng _quote_readline_by_refđã được đơn giản hóa). Bạn chỉ có thể sao chép bản sửa đổi hiện tại từ Git:

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

    ... Và sau đó sao chép phiên bản mới nhất của bash_completiontập lệnh sang /usr/share/bash-completion(không cần khẩn cấp sao lưu phiên bản cũ trừ khi nó giúp bạn cảm thấy an toàn hơn - nếu bạn gặp một số vấn đề, sudo apt-get install --reinstall bash-completionnên hoàn nguyên mọi thay đổi bạn đã thực hiện tốt.) Đây là cách tôi đề nghị nếu bạn đang vội để sửa lỗi này. :-)

Lưu ý rằng không có giải pháp nào trong số đó sẽ làm cho việc hoàn thành bash bên trong công việc thay thế lệnh: như đã đề cập trong cùng một báo cáo lỗi, điều này bị hỏng trong Bash 4.3.

  1. Ngồi lại và chờ đợi: Sớm hay muộn một phiên bản mới sẽ được phát hành (thậm chí có thể sửa lỗi hoàn thành bash bên trong thay thế lệnh) và bạn sẽ nhận được nó với một số phiên bản Ubuntu trong tương lai. Đó là những gì tôi sẽ làm ;-)

1
@ con-f-use Yep, vậy thôi! Repo Git cũng được liên kết từ trang web chính của bash-hoàn thành, đó là lý do tại sao tôi đã không liên kết với nó trong câu trả lời của tôi.
Malte Skoruppa

2
@ con-f-use Nhận xét của bạn khiến tôi phải nghiên cứu thêm về lỗi này. Hóa ra nó không phải, và chưa bao giờ, là một lỗi ngược dòng. Thay vào đó, nó thực sự là một lỗi được giới thiệu bởi một bản vá Ubuntu được áp dụng so với phiên bản ngược dòng. Cho đến nay, không ai đã thu hẹp lỗi này vào bản vá cụ thể đó. Vì vậy, tôi đã báo cáo phát hiện của mình trong báo cáo lỗi Ubuntu tương ứng: bug.launchpad.net/ubfox/+source/bash-completion/+orms/1312243 .
Malte Skoruppa

2
Malte làm việc tốt.
Barry Kelly

1
Cảm ơn đã giải thích. Khi viết bài này, phiên bản đầu git đã loại bỏ lỗi tự động hoàn thành như mong muốn. EDIT: thực sự, không có gì, nó không.
dùng3391564

1
@MaxvonHippel Tôi đã nói rằng khi bạn sử dụng sudo suđể trở thành root, nó không lấy nguồn thư viện, nhưng nó sẽ có nguồn gốc khi bạn sử dụng sudo -ithay vào đó, đó là cách dự định để có được một phiên root gốc tương tác. Đối với câu hỏi của bạn: Vì bất kỳ shell bash nào đọc ~/.bashrcthư viện cuối cùng và không có cách nào để "hủy nguồn" một tệp, tôi thấy không có cách nào hoàn toàn đơn giản. Đây là một hack có thể: Làm cho việc tìm nguồn cung ứng của thư viện có điều kiện trên một số biến môi trường, giả sử NOCOMPL, không được xác định trong ~/.bashrc, ...
Malte Skoruppa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.