Finalización de la pestaña Bash: '-bash: EOF inesperado mientras se busca coincidencia') '-bash: error de sintaxis: final inesperado del archivo

18

Estoy tratando de entrar en una irbsesión con variables de entorno específicas de un archivo con este comando:

$ env $(cat env.sh) irb

Pero cuando intento presionar Tabdespués de escribir env.para completarlo, aparece el siguiente error:

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

Otra cosa interesante es que si estoy conectado como root, este error no ocurre.

Aquí está la salida de 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

¿Alguien puede explicarme por qué sucede esto y, si es así, cómo lo soluciono cuando no soy un usuario root?

eldosoa
fuente
¿Cómo iniciar sesión como root?
Muru
@muru me conecté a la raíz usando sudo su.
eldosoa
Edite su pregunta para agregar la salida de find ~ -uid 0.
Muru
@muru Hecho. Agregué el resultado en mi pregunta.
eldosoa
Lo siento, pero no como root! Quise decir como tu usuario normal, así que ~es /home/something.
Muru

Respuestas:

33

Encontraste un error en la biblioteca Bash Completion utilizada por Ubuntu.

¿Qué significa esto?

Ubuntu utiliza una biblioteca de finalización de bash para hacer que la finalización de bash sea inteligente. Esta biblioteca vive en /usr/share/bash-completion/bash_completion.

Esencialmente, esta biblioteca declara algunas funciones inteligentes que conocen los comandos típicos y cómo completarlos. Cada vez que presiona Tab, se llama a las funciones dentro de esta biblioteca e intenta completar su línea de comando actual. Entonces, por ejemplo, si escribe apt-get iTab, completará eso en apt-get install. Si no obtiene esa biblioteca, solo tiene la terminación de bash primitiva estándar, por lo que, por ejemplo, si escribe apt-get iTabsin haberla encontrado, bash simplemente buscará los archivos en el directorio actual comenzando ie intentará completar su comando de acuerdo con Estos nombres de archivo.

¿Por qué no está sucediendo como root?

Porque cuando lo sudo suhaces root, la biblioteca de finalización de bash no se obtiene. Esto sería diferente si solías sudo -ihacerte a ti mismo root. Apuesto a que ves el error, ¿no? Vea, por ejemplo, 'sudo su -' vs 'sudo -i' vs 'sudo / bin / bash': ¿cuándo importa cuál se usa o si importa? Si no estás familiarizado con las diferencias.

En mi caso, como usuario normal, la biblioteca se obtiene cuando inicio un shell Bash porque las ~/.bashrcfuentes de /etc/bash_completionlas fuentes /usr/share/bash-completion/bash_completion.

Si uso sudo -ipara iniciar sesión como root, la biblioteca se obtiene porque las /etc/profilefuentes de /etc/profile.d/bash_completion.shlas fuentes /usr/share/bash-completion/bash_completion.

¿Por qué está ocurriendo ese error?

Intenta ejecutar este comando:

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

¿Luce familiar? ;-) De hecho, eso es exactamente lo que sucedió detrás de escena cuando tocaste Taben el contexto que describiste. Más precisamente, el error está en la función _quote_readline_by_refdeclarada por /usr/share/bash-completion/bash_completion. Si obtuvo ese archivo, debería tener esa función disponible. Entonces, intente esto:

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

Dados estos argumentos, la función _quote_readline_by_refrealiza, entre otras cosas, lo evalmencionado anteriormente. Puedes echar un vistazo si quieres. Y cuando escribiste env $(cat env.Tab, detrás de escena esa función fue llamada exactamente con esos argumentos. Entonces eso fue lo que pasó.

Se suponía que este evaltruco solucionaría otro problema , pero supongo que introdujo este otro error en el proceso.

¿Cómo lo soluciono?

Resulta que este error ya ha sido reportado . Después de leer ese informe de error, veo tres formas de solucionarlo:

  1. Parcheo: en uno de los comentarios en ese informe de error, alguien sugiere reemplazar la línea

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

    dentro de la función _quote_readline_by_refen el archivo /usr/share/bash-completion/bash_completionpor la línea

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

    Recomiendo no hacer esto. La persona que escribió ese comentario no parece ser un desarrollador de bash-complete . Esta revisión simplemente hará que el operando izquierdo de la instrucción se evalúe como falso y, por lo tanto, evitará que eso evalsuceda. Sin embargo, sin un buen conocimiento de lo que se supone que debe hacer esa función y en qué contextos se llama, no está claro si esto no romperá potencialmente alguna otra funcionalidad prevista.

  2. Obtenga la versión más reciente: como también se mencionó en ese informe de error, este error no está presente en git head (en donde, entre otros cambios, la función _quote_readline_by_refse ha simplificado). Simplemente puede clonar la revisión actual desde Git:

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

    ... y luego copie la versión más reciente de la bash_completionsecuencia de comandos a /usr/share/bash-completion(no hay necesidad urgente de hacer una copia de seguridad de la versión anterior a menos que lo haga sentir más seguro; si experimenta algunos problemas, sudo apt-get install --reinstall bash-completiondebería revertir cualquier cambio que haya hecho). Esta es la forma en que yo recomiende si tiene prisa para arreglar esto. :-)

Tenga en cuenta que ninguna de esas soluciones hará que la finalización de bash funcione dentro de la sustitución de comandos: como se menciona en el mismo informe de error, esto se rompe en Bash 4.3.

  1. Siéntese y espere: Tarde o temprano se lanzará una nueva versión (que incluso puede solucionar la finalización de bash dentro de la sustitución de comandos) y la obtendrá con alguna futura versión de Ubuntu. Para eso voy ;-)
Malte Skoruppa
fuente
1
@ con-f-use Sí, eso es todo! El repositorio de Git también está vinculado desde el sitio principal de bash-complete, por lo que no lo había vinculado en mi respuesta.
Malte Skoruppa
2
@ con-f-use Tu comentario me hizo investigar un poco más sobre este error. Resulta que no es, y nunca fue, un error aguas arriba. En cambio, en realidad es un error introducido por un parche de Ubuntu aplicado contra la versión anterior. Nadie parece haber reducido este error a ese parche en particular hasta ahora. Así que he informado de mi hallazgo en el informe de errores de Ubuntu correspondiente: bugs.launchpad.net/ubuntu/+source/bash-completion/+bug/1312243 .
Malte Skoruppa
2
Buen trabajo Malte.
Barry Kelly
1
Gracias por la explicación. Al momento de escribir este artículo, la versión de git head ha eliminado el error y se completa automáticamente según lo deseado. EDITAR: en realidad, no importa, no lo hace.
user3391564
1
@MaxvonHippel Dije que cuando se usa sudo supara convertirse en root, no obtiene la biblioteca, pero en su lugar se obtendrá cuando se usa sudo -i, que es la forma prevista de obtener una sesión raíz interactiva. En cuanto a su pregunta: dado que cualquier shell bash lee lo ~/.bashrcque eventualmente obtiene la biblioteca, y no hay forma de "des-fuente" de un archivo, no veo una manera completamente directa. Aquí hay un posible truco: haga que el abastecimiento de la biblioteca esté condicionado a alguna variable de entorno, por ejemplo NOCOMPL, no se define en su ~/.bashrc...
Malte Skoruppa