variable una sirve script resultado que pasar parametros para hat guardar funciones entorno editar cómo comando bash unix shell

bash - sirve - ¿Cuál es una forma concisa de verificar que las variables de entorno estén configuradas en un script de shell de Unix?



variables de entorno linux bash (14)

Expansión de parámetros

La respuesta obvia es usar una de las formas especiales de expansión de parámetros:

: ${STATE?"Need to set STATE"} : ${DEST:?"Need to set DEST non-empty"}

O, mejor (vea la sección en ''Posición de comillas dobles'' más abajo):

: "${STATE?Need to set STATE}" : "${DEST:?Need to set DEST non-empty}"

La primera variante (¿usar solo ? ) Requiere que se establezca STATE, pero STATE = "" (una cadena vacía) está bien; no es exactamente lo que desea, sino la notación alternativa y anterior.

La segunda variante (usando :? ) Requiere que DEST esté configurado y no vacío.

Si no proporciona ningún mensaje, el shell proporciona un mensaje predeterminado.

El constructo ${var?} Es portable a la versión 7 UNIX y al shell Bourne (1978 o más). El constructo ${var:?} es un poco más reciente: creo que estaba en System III UNIX alrededor de 1981, pero puede haber estado en PWB UNIX antes de eso. Por lo tanto, se encuentra en Korn Shell y en POSIX, incluyendo específicamente Bash.

Por lo general, se documenta en la página man del shell en una sección llamada Expansión de parámetros . Por ejemplo, el manual de bash dice:

${parameter:?word}

Mostrar error si es nulo o no está configurado. Si el parámetro es nulo o no está configurado, la expansión de la palabra (o un mensaje a ese efecto si la palabra no está presente) se escribe en el error estándar y la shell, si no es interactiva, se cierra. De lo contrario, se sustituye el valor del parámetro.

El comando de colon

Probablemente debería agregar que el comando de dos puntos simplemente tiene sus argumentos evaluados y luego tiene éxito. Es la notación de comentario de shell original (antes de '' # '' hasta el final de la línea). Durante mucho tiempo, los scripts de shell Bourne tenían dos puntos como primer carácter. El Shell C leería un script y usaría el primer carácter para determinar si era para el Shell C (un hash '' # '') o el shell Bourne (dos puntos '' : ''). Luego el kernel se puso en acción y agregó soporte para '' #!/path/to/program '' y el shell Bourne obtuvo '' # '' comentarios, y la convención de los dos puntos se fue por el camino. Pero si te encuentras con un script que comienza con dos puntos, ahora sabrás por qué.

Posición de comillas dobles

blong preguntó en un comment :

¿Alguna idea sobre esta discusión? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749

La esencia de la discusión es:

... Sin embargo, cuando lo shellcheck (con la versión 0.4.1), recibo este mensaje:

In script.sh line 13: : ${FOO:?"The environment variable ''FOO'' must be set and non-empty"} ^-- SC2086: Double quote to prevent globbing and word splitting.

¿Algún consejo sobre qué debo hacer en este caso?

La respuesta corta es "haz lo que sugiere shellcheck ":

: "${STATE?Need to set STATE}" : "${DEST:?Need to set DEST non-empty}"

Para ilustrar por qué, estudia lo siguiente. Tenga en cuenta que el comando : no hace eco de sus argumentos (pero el shell evalúa los argumentos). Queremos ver los argumentos, por lo que el siguiente código usa printf "%s/n" en lugar de :

$ mkdir junk $ cd junk $ > abc $ > def $ > ghi $ $ x="*" $ printf "%s/n" ${x:?You must set x} # Careless; not recommended abc def ghi $ unset x $ printf "%s/n" ${x:?You must set x} # Careless; not recommended bash: x: You must set x $ printf "%s/n" "${x:?You must set x}" # Careful: should be used bash: x: You must set x $ x="*" $ printf "%s/n" "${x:?You must set x}" # Careful: should be used * $ printf "%s/n" ${x:?"You must set x"} # Not quite careful enough abc def ghi $ x= $ printf "%s/n" ${x:?"You must set x"} # Not quite careful enough bash: x: You must set x $ unset x $ printf "%s/n" ${x:?"You must set x"} # Not quite careful enough bash: x: You must set x $

Observe cómo el valor en $x se expande a la primera * y luego a una lista de nombres de archivos cuando la expresión general no está entre comillas dobles. Esto es lo que shellcheck recomienda se debe arreglar. No he verificado que no se oponga al formulario donde la expresión está entre comillas dobles, pero es razonable suponer que estaría bien.

Tengo algunos scripts shell de Unix en los que necesito comprobar que ciertas variables de entorno están configuradas antes de comenzar a hacer cosas, así que hago este tipo de cosas:

if [ -z "$STATE" ]; then echo "Need to set STATE" exit 1 fi if [ -z "$DEST" ]; then echo "Need to set DEST" exit 1 fi

que es mucho escribir ¿Existe un lenguaje más elegante para verificar que se establece un conjunto de variables de entorno?

EDITAR: Debo mencionar que estas variables no tienen un valor predeterminado significativo; la secuencia de comandos debe emitir un error en caso de que no esté definido.


El $? la sintaxis es bastante clara

if [ $?BLAH == 1 ]; then echo "Exists"; else echo "Does not exist"; fi


En lugar de usar scripts de shell externos, tiendo a cargar funciones en mi shell de inicio de sesión. Uso algo como esto como una función auxiliar para verificar las variables de entorno en lugar de cualquier variable establecida:

is_this_an_env_variable () local var="$1" if env |grep -q "^$var"; then return 0 else return 1 fi }


En mi opinión, la comprobación más simple y compatible para #! / Bin / sh es:

if [ "$MYVAR" = "" ] then echo "Does not exist" else echo "Exists" fi

Nuevamente, esto es para / bin / sh y es compatible también en sistemas Solaris antiguos.



Ninguna de las soluciones anteriores funcionó para mis propósitos, en parte porque busco en el entorno una lista abierta de variables que deben establecerse antes de comenzar un largo proceso. Terminé con esto:

mapfile -t arr < variables.txt EXITCODE=0 for i in "${arr[@]}" do ISSET=$(env | grep ^${i}= | wc -l) if [ "${ISSET}" = "0" ]; then EXITCODE=-1 echo "ENV variable $i is required." fi done exit ${EXITCODE}


Para las personas futuras como yo, quería dar un paso adelante y parametrizar el nombre var, por lo que puedo recorrer una lista de nombres variables de tamaño variable:

#!/bin/bash declare -a vars=(NAME GITLAB_URL GITLAB_TOKEN) for var_name in "${vars[@]}" do if [ -z "$(eval "echo /$$var_name")" ]; then echo "Missing environment variable $var_name" exit 1 fi done


Podemos escribir una buena afirmación para verificar un conjunto de variables a la vez:

# # assert if variables are set (to a non-empty string) # if any variable is not set, exit 1 (when -f option is set) or return 1 otherwise # # Usage: assert_var_not_null [-f] variable ... # function assert_var_not_null() { local fatal var num_null=0 [[ "$1" = "-f" ]] && { shift; fatal=1; } for var in "$@"; do [[ -z "${!var}" ]] && printf ''%s/n'' "Variable ''$var'' not set" >&2 && ((num_null++)) done if ((num_null > 0)); then [[ "$fatal" ]] && exit 1 return 1 fi return 0 }

Ejemplo de invocación:

one=1 two=2 assert_var_not_null one two echo test 1: return_code=$? assert_var_not_null one two three echo test 2: return_code=$? assert_var_not_null -f one two three echo test 3: return_code=$? # this code shouldn''t execute

Salida:

test 1: return_code=0 Variable ''three'' not set test 2: return_code=1 Variable ''three'' not set


Prueba esto:

[ -z "$STATE" ] && echo "Need to set STATE" && exit 1;


Seguramente el enfoque más simple es agregar el -u al shebang (la línea en la parte superior de tu script), asumiendo que estás usando bash :

#!/bin/sh -u

Esto hará que la secuencia de comandos se cierre si alguna de las variables no vinculadas está al acecho.


Siempre he usado

if [ "x$STATE" == "x" ]; then echo "Need to set State"; exit 1; fi

No es mucho más conciso, me temo.

Bajo CSH tienes $? ESTADO.


Su pregunta depende del shell que está utilizando.

Bourne shell deja muy poco en el camino de lo que buscas.

PERO...

Funciona, casi en todas partes.

Sólo intenta y mantente alejado de csh. Fue bueno para las campanas y los silbidos que agregó, comparó el caparazón de Bourne, pero ahora está realmente chirriante. Si no me crees, solo trata de separar a STDERR en csh! (-:

Hay dos posibilidades aquí. El ejemplo anterior, a saber, utilizando:

${MyVariable:=SomeDefault}

por primera vez necesita referirse a $ MyVariable. Esto lleva el env. var MyVariable y, si no está configurado actualmente, asigna el valor de SomeDefault a la variable para su uso posterior.

También tienes la posibilidad de:

${MyVariable:-SomeDefault}

que simplemente sustituye a SomeDefault por la variable en la que está utilizando esta construcción. No asigna el valor SomeDefault a la variable, y el valor de MyVariable seguirá siendo nulo después de encontrar esta declaración.


bash 4.2 introdujo el operador -v que prueba si un nombre está configurado con algún valor, incluso la cadena vacía.

$ unset a $ b= $ c= $ [[ -v a ]] && echo "a is set" $ [[ -v b ]] && echo "b is set" b is set $ [[ -v c ]] && echo "c is set" c is set


${MyVariable:=SomeDefault}

Si MyVariable está configurado y no es nulo, restablecerá el valor de la variable (= no pasa nada).
Si no, MyVariable se establece en SomeDefault .

Lo anterior intentará ejecutar ${MyVariable} , así que si solo desea establecer la variable, haga lo siguiente:

MyVariable=${MyVariable:=SomeDefault}