¿Cómo compruebo la sintaxis de un script Bash sin ejecutarlo?


Respuestas:


381
bash -n scriptname

Tal vez una advertencia obvia: esto valida la sintaxis pero no verificará si su script bash intenta ejecutar un comando que no está en su camino, como en ech hellolugar de echo hello.


9
En la página de manual de bash, en "SHELL BUILTIN COMMANDS / set", -n está documentado y, como dice el comienzo de la página de manual, bash interpreta todas las opciones de un solo carácter set.
Ephemient

24
para agregar a la (para mí) advertencia no obvia, tampoco detectará un error causado por un espacio faltante en if ["$var" == "string" ]lugar deif [ "$var" == "string" ]
Brynjar

11
@Brynjar Eso se debe a que solo se trata de verificar la sintaxis. El corchete abierto no es sintaxis, ese es el nombre de la función a ejecutar. type [dice "[es un shell incorporado". Finalmente, delega en el testprograma, pero también espera un paréntesis de cierre. Entonces es como if test"$var", que no es lo que el autor quiso decir, pero es sintácticamente válido (digamos que $ var tiene un valor de "a", luego veremos "bash: testa: comando no encontrado"). El punto es que sintácticamente, no falta espacio.
Joshua Cheek

2
@JoshuaCheek: Builtin [solo se invoca en este caso si se $varexpande a una cadena vacía . Si se $varexpande a una cadena no vacía , [se concatena con esa cadena y Bash lo interpreta como un nombre de comando (no un nombre de función ) y, sí, eso es sintácticamente válido, pero, como usted dice, obviamente no es la intención. Si usa en [[lugar de [, aunque [[sea ​​una palabra clave de shell (en lugar de una incorporada), obtendrá el mismo resultado, porque la concatenación de cadena no intencionada todavía anula el reconocimiento de la palabra clave.
mklement0

2
@JoshuaCheek: Bash todavía está sintaxis: verificando aquí: está comprobando la sintaxis de invocación de comando simple : ["$var"es sintácticamente una expresión válida de nombre de comando ; de manera similar, los tokens ==y "$string"son argumentos de comando válidos . (Generalmente, incorporado [se analiza con comando sintaxis, mientras que [[- como una concha palabra clave - se analiza de manera diferente). El orden interna del shell [no no delegar al " testprograma" (utilidad externa): bash, dash, ksh, zshtodos tienen incorporado versiones de ambos [ytest, y no llaman a sus contrapartes de servicios externos.
mklement0

127

El tiempo lo cambia todo. Aquí hay un sitio web que proporciona verificación de sintaxis en línea para script de shell.

Descubrí que es muy poderoso detectar errores comunes.

ingrese la descripción de la imagen aquí

Sobre ShellCheck

ShellCheck es una herramienta de análisis estático y de enlace para scripts sh / bash. Se centra principalmente en el manejo de errores y dificultades típicas de sintaxis de nivel principiante e intermedio donde el shell solo da un mensaje de error críptico o un comportamiento extraño, pero también informa sobre algunos problemas más avanzados donde los casos de esquina pueden causar fallas tardías.

¡El código fuente de Haskell está disponible en GitHub!


55
Gran consejo; en OSX ahora también puede instalar el CLI shellcheck.net, shellchecka través Homebrew : brew install shellcheck.
mklement0

3
También en debian y amigos:apt-get install shellcheck
ese otro tipo

Para Ubuntu Trusty, este paquete debe instalarse desde trusty-backports.
Peterino

Como se mencionó anteriormente, se necesita una dependencia confiable, y puede instalarla como se muestra a continuación en ubuntu 14.04: sudo apt-get -f install, luego: sudo sudo apt-get install shellcheck
zhihong

Esto es realmente útil, pero no utiliza el analizador de Bash sino el suyo. En la mayoría de los casos, esto es lo suficientemente bueno y puede identificar tanto el análisis como otros problemas, pero hay al menos un caso límite (y probablemente otros que no he visto) en el que no se analiza de la misma manera.
Daniel H

38

También habilito la opción 'u' en cada script de bash que escribo para hacer alguna comprobación adicional:

set -u 

Esto informará el uso de variables no inicializadas, como en el siguiente script 'check_init.sh'

#!/bin/sh
set -u
message=hello
echo $mesage

Ejecutando el script:

$ check_init.sh

Informará lo siguiente:

./check_init.sh[4]: mensaje: parámetro no establecido.

Muy útil para detectar errores tipográficos.


44
Siempre establezco estas banderas en mis scripts de bash, si pasa estas, es bueno ir "set -o errexit" "set -o nounset" "set -o pipefail"
μολὼν.λαβέ

+1 para set -uaunque esto realmente no responde la pregunta, porque debe ejecutar el script para obtener el mensaje de error. Ni siquiera bash -n check_init.shmuestra esa advertencia
rubo77

23
sh  -n   script-name 

Ejecuta esto. Si hay errores de sintaxis en el script, entonces devuelve el mismo mensaje de error. Si no hay errores, sale sin dar ningún mensaje. Puede verificar de inmediato mediante el uso echo $?, que devolverá la 0confirmación exitosa sin ningún error.

A mí me funcionó bien. Corrí en el sistema operativo Linux, Bash Shell.


1
Aunque no exactamente en relación con la comprobación de sintaxis fiesta - usando -x set y set + x para depurar el guión completo o secciones de la secuencia de comandos es bastante útil
gurum

Gracias por esto, no sabía, no sabía sobre -n, pero lo que quería era @GuruM> sh -x test.sh, ya que eso muestra la salida generada del script
zzapper

1
Si. Olvidé mencionar que puede hacer lo siguiente en la línea de comando: 1) bash -x test.sh #this ejecuta todo el script en 'modo de depuración' 2) set + x; bash test.sh; set -x #set modo de depuración activado / desactivado antes / después de ejecutar el script En el script: a) #! / bin / bash -x #add 'modo de depuración' en la parte superior del script b) set + x; código; set -x #add 'modo de depuración' para cualquier sección del script
GuruM

sh -nprobablemente no verificará que el script sea válido Bash script. Podría dar falsos negativos. shes una variante de shell Bourne que generalmente no es Bash. Por ejemplo, en Ubuntu Linux realpath -e $(command -v sh)da / bin / dash
jarno

4

De hecho, verifico todos los scripts de bash en el directorio actual en busca de errores de sintaxis SIN ejecutarlos con la findherramienta

Ejemplo:

find . -name '*.sh' -exec bash -n {} \;

Si desea usarlo para un solo archivo, simplemente edite el comodín con el nombre del archivo.


3

El comando nulo [dos puntos] también es útil al depurar para ver el valor de la variable

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

utiliza expansiones de parámetros
mug896

esto funciona, porque set -xmuestra cada línea antes de ser ejecutado
rubo77


1

Si necesita en una variable la validez de todos los archivos en un directorio (git pre-commit hook, build lint script), puede capturar la salida stderr de los comandos "sh -n" o "bash -n" (vea otro respuestas) en una variable y tener un "if / else" basado en eso

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

Cambia "sh" por "bash" según tus necesidades

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.