world script run hello example español ejemplos linux bash shell unix sh

linux - script - ¿Cuál es el significado de a! antes de un comando en el shell?



shell script hello world (3)

La pregunta está en el título. ¿Cuál es el propósito de un comando de shell (parte de un script de shell) que comienza con un signo de exclamación? Ejemplo concreto:

En foo.sh:

#!/usr/bin/env bash set -e ! docker stop foo ! docker rm -f foo # ... other stuff

Sé que sin el espacio, el signo de exclamación se usa para reemplazar la historia y ! <expression> ! <expression> acuerdo con la página del manual se puede utilizar para evaluar " Verdadero si expr es falso ". Pero en el contexto de ejemplo eso no tiene sentido para mí.


"!" Significa "no", así que cuando lo coloca antes de un comando y ejecuta "$?" Se hará eco de un 1. Lo que significa que falló en lugar de un 0, lo que significa éxito.


Si no desea que el script falle en ambos casos, error o éxito del comando, también puede usar esta alternativa:

set -e docker stop foo || true

El valor booleano o verdadero hace que la canalización siempre tenga 0 como valor de retorno.


TL; DR: Esto es simplemente pasar por set -e indicador set -e en la línea específica donde lo está utilizando.

Agregar agregar a la respuesta correcta y útil de hek2mgl .

Tienes:

set -e ! command

Manual de referencia de Bash → Tuberías describe:

Cada comando en una tubería se ejecuta en su propia subshell. El estado de salida de una tubería es el estado de salida del último comando en la tubería (...). Si la palabra reservada ''!'' precede a la tubería, el estado de salida es la negación lógica del estado de salida como se describe anteriormente. El shell espera a que finalicen todos los comandos de la canalización antes de devolver un valor.

Esto significa que ! preceder a un comando está negando el estado de salida del mismo:

$ echo 23 23 $ echo $? 0 # But $ ! echo 23 23 $ echo $? 1

O:

$ echo 23 && echo "true" || echo "fail" 23 true $ ! echo 23 && echo "true" || echo "fail" 23 fail

El estado de salida es útil de muchas maneras. En su script, usado junto con set -e hace que el script salga cada vez que un comando devuelve un estado distinto de cero.

Por lo tanto, cuando tienes:

set -e command1 command2

Si command1 devuelve un estado distinto de cero, el script finalizará y no continuará con el command2 .

Sin embargo, también hay un punto interesante para mencionar, descrito en 4.3.1 The Set Builtin :

-mi

Salga de inmediato si una tubería (vea Tuberías), que puede consistir en un solo comando simple (vea Comandos simples), una lista (vea Listas) o un comando compuesto (vea Comandos compuestos) devuelve un estado distinto de cero. El shell no sale si el comando que falla es parte de la lista de comandos inmediatamente después de un tiempo o hasta la palabra clave, parte de la prueba en una declaración if, parte de cualquier comando ejecutado en un && o || lista excepto el comando que sigue al && o || final, cualquier comando en una tubería pero el último, o si se invierte el estado de retorno del comando. . Si un comando compuesto que no sea un subshell devuelve un estado distinto de cero porque un comando falló mientras se ignoraba -e, el shell no se cierra. Una trampa en ERR, si se establece, se ejecuta antes de que salga el shell.

Tomando todo esto en consideración, cuando tiene:

set -e ! command1 command2

Lo que está haciendo es set -e indicador set -e en el command1 . ¿Por qué?

  • si command1 ejecuta correctamente, devolverá un estado cero. ! lo negará, pero set -e no activará una salida por el porque proviene de un estado de retorno invertido con!, como se describió anteriormente.
  • si command1 falla, devolverá un estado distinto de cero. ! lo negará, por lo que la línea terminará devolviendo un estado cero y el script continuará normalmente.