Penyelesaian Tab Bash: '-bash: EOF yang tak terduga sambil mencari yang sesuai `)' -bash: kesalahan sintaksis: akhir file yang tidak terduga

18

Saya mencoba masuk ke irbsesi dengan variabel lingkungan spesifik dari file dengan perintah ini:

$ env $(cat env.sh) irb

Tetapi ketika saya mencoba tekan Tabsetelah saya mengetik env.untuk menyelesaikannya, saya mendapatkan kesalahan berikut:

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

Hal lain yang menarik adalah bahwa jika saya login sebagai root, kesalahan ini tidak terjadi.

Inilah output dari 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

Adakah yang bisa menjelaskan kepada saya mengapa ini terjadi dan jika demikian, bagaimana cara memperbaikinya saat saya bukan pengguna root?

Eldosoa
sumber
Bagaimana Anda masuk sebagai root?
muru
@muru saya login ke root menggunakan sudo su.
eldosoa
Harap edit pertanyaan Anda untuk menambahkan output find ~ -uid 0.
muru
@muru Selesai. Menambahkan output dalam pertanyaan saya.
eldosoa
Maaf tentang itu, tetapi tidak sebagai root! Saya dimaksudkan sebagai user biasa Anda, sehingga ~adalah /home/something.
muru

Jawaban:

33

Anda menemukan bug di perpustakaan Bash Completion yang digunakan oleh Ubuntu.

Apa artinya ini?

Ubuntu menggunakan pustaka penyelesaian bash untuk membuat penyelesaian bash pintar. Perpustakaan ini tinggal di /usr/share/bash-completion/bash_completion.

Pada dasarnya, pustaka ini mendeklarasikan beberapa fungsi pintar yang tahu tentang perintah-perintah tipikal dan bagaimana menyelesaikannya. Setiap kali Anda menekan Tab, fungsi-fungsi dalam perpustakaan ini dipanggil dan berusaha untuk menyelesaikan baris perintah Anda saat ini. Jadi misalnya jika Anda mengetiknya apt-get iTabakan menyelesaikan itu untuk apt-get install. Jika Anda tidak sumber perpustakaan itu, Anda hanya memiliki standar, penyelesaian bash primitif - jadi misalnya jika Anda mengetik apt-get iTabtanpa membuatnya, bash hanya akan mencari file di direktori saat ini dimulai dengan idan mencoba untuk menyelesaikan perintah Anda sesuai dengan nama file ini.

Mengapa itu tidak terjadi sebagai root?

Karena ketika Anda menggunakan sudo suuntuk membuat sendiri root, pustaka penyelesaian bash tidak bersumber. Ini akan berbeda jika Anda sudo -imembuat sendiri root. Saya yakin Anda melihat bug itu, bukan? Lihat misalnya 'sudo su -' vs 'sudo -i' vs 'sudo / bin / bash' - kapan itu penting yang digunakan, atau apakah itu penting sama sekali? jika Anda tidak terbiasa dengan perbedaan.

Dalam kasus saya, sebagai pengguna normal, pustaka akan bersumber ketika saya memulai Bash shell karena ~/.bashrcsumber /etc/bash_completionyang sumbernya /usr/share/bash-completion/bash_completion.

Jika saya gunakan sudo -iuntuk masuk sebagai root, perpustakaan akan bersumber karena /etc/profilesumber /etc/profile.d/bash_completion.shyang sumbernya /usr/share/bash-completion/bash_completion.

Mengapa bug itu terjadi?

Cobalah untuk menjalankan perintah ini:

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

Terlihat tidak asing? ;-) Memang, itulah yang terjadi di balik layar ketika Anda menekan Tabdalam konteks yang Anda gambarkan. Lebih tepatnya, bug ada dalam fungsi yang _quote_readline_by_refdideklarasikan oleh /usr/share/bash-completion/bash_completion. Jika Anda membuat sumber file itu, Anda harus memiliki fungsi itu tersedia. Jadi selanjutnya coba ini:

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

Dengan argumen-argumen ini, fungsi _quote_readline_by_refmelakukan, antara lain, yang evaldisebutkan di atas. Anda dapat melihatnya jika mau. Dan ketika Anda mengetik env $(cat env.Tab, di balik layar yang berfungsi dipanggil dengan tepat argumen itu. Jadi itulah yang terjadi.

Ini evalhack seharusnya untuk memperbaiki masalah lain , tapi saya kira itu diperkenalkan bug lain ini dalam proses.

Bagaimana saya memperbaikinya?

Ternyata bug ini sudah dilaporkan . Setelah membaca laporan bug itu, saya melihat tiga cara untuk memperbaikinya:

  1. Menambalnya: Di salah satu komentar dalam laporan bug itu, seseorang menyarankan untuk mengganti baris

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

    dalam fungsi _quote_readline_by_refdalam file /usr/share/bash-completion/bash_completiondengan garis

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

    Saya merekomendasikan untuk tidak melakukan ini. Orang yang menulis komentar itu tampaknya bukan pengembang penyelesaian-bash . Perbaikan terbaru ini hanya akan menyebabkan operan kiri pernyataan untuk mengevaluasi ke salah dan dengan demikian mencegah hal itu evalterjadi. Namun tanpa pengetahuan yang baik tentang apa fungsi yang seharusnya dilakukan dan dalam konteks apa namanya, tidak jelas apakah ini tidak akan berpotensi merusak beberapa fungsi yang dimaksudkan lainnya.

  2. Dapatkan versi terbaru: Seperti yang juga disebutkan dalam laporan kutu itu, kutu ini tidak ada di git head (di mana di antara perubahan lainnya fungsi _quote_readline_by_reftersebut telah disederhanakan). Anda dapat mengkloning revisi saat ini dari Git:

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

    ... lalu salin versi terbaru bash_completionskrip ke /usr/share/bash-completion(tidak perlu segera mencadangkan versi lama kecuali jika itu membuat Anda merasa lebih aman - jika Anda mengalami beberapa masalah, sudo apt-get install --reinstall bash-completionkembalikan perubahan yang Anda buat dengan baik.) Ini adalah cara saya merekomendasikan jika Anda sedang terburu-buru untuk memperbaikinya. :-)

Perhatikan bahwa tidak ada solusi yang akan membuat penyelesaian bash di dalam pekerjaan substitusi perintah: seperti yang disebutkan dalam laporan bug yang sama, ini rusak di Bash 4.3.

  1. Duduk dan tunggu: Cepat atau lambat versi baru akan dirilis (yang bahkan dapat memperbaiki penyelesaian bash di dalam substitusi perintah) dan Anda akan mendapatkannya dengan beberapa versi Ubuntu di masa depan. Itulah tujuan saya ;-)
Malte Skoruppa
sumber
1
@ con-f-use Yap, itu dia! Repo Git juga ditautkan dari situs utama penyelesaian bash, itulah sebabnya saya tidak menautkannya dalam jawaban saya.
Malte Skoruppa
2
@ con-f-use Komentar Anda membuat saya melakukan penelitian lebih lanjut tentang bug ini. Ternyata itu bukan, dan tidak pernah, bug hulu. Sebaliknya, itu sebenarnya bug yang diperkenalkan oleh tambalan Ubuntu yang diterapkan terhadap versi upstream. Sejauh ini tidak ada yang mempersempit bug ini ke patch tertentu. Jadi saya telah melaporkan temuan saya dalam laporan bug Ubuntu yang sesuai: bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1312243 .
Malte Skoruppa
2
Kerja bagus, Malte.
Barry Kelly
1
Terima kasih untuk penjelasannya. Pada tulisan ini, versi git head telah menghapus bug dan autocomplet yang diinginkan. EDIT: sebenarnya, tidak apa-apa, tidak.
user3391564
1
@MaxvonHippel Saya mengatakan bahwa ketika Anda menggunakan sudo suuntuk menjadi root, itu tidak sumber perpustakaan, tapi itu akan bersumber ketika Anda menggunakannya sudo -i, yang merupakan cara yang dimaksudkan untuk mendapatkan sesi root interaktif. Adapun pertanyaan Anda: Karena bash shell membaca ~/.bashrcyang akhirnya sumber perpustakaan, dan tidak ada cara untuk "un-source" file, saya tidak melihat cara yang sepenuhnya mudah. Inilah kemungkinan hack: Buat sumber perpustakaan tergantung pada beberapa variabel lingkungan, katakanlah NOCOMPL, tidak didefinisikan dalam ~/.bashrc, ...
Malte Skoruppa