¿Pasar todas las variables de un script de shell a otro?
Digamos que tengo un script shell/bash llamado test.sh
con:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
Mi test2.sh
aspecto es este:
#!/bin/bash
echo ${TESTVARIABLE}
Esto no funciona. No quiero pasar todas las variables como parámetros ya que, en mi humilde opinión, esto es excesivo.
¿Existe una manera diferente?
Tienes básicamente dos opciones:
- Convierta la variable en una variable de entorno (
export TESTVARIABLE
) antes de ejecutar el segundo script. - Obtenga el segundo script, es decir
. test2.sh
, se ejecutará en el mismo shell. Esto le permitiría compartir fácilmente variables más complejas, como matrices, pero también significa que el otro script podría modificar variables en el shell fuente.
ACTUALIZAR:
Para usar export
para establecer una variable de entorno, puede usar una variable existente:
A=10
# ...
export A
Esto debería funcionar tanto en bash
como en sh
. bash
también permite combinarlo así:
export A=10
Esto también funciona en mi sh
(que resulta ser bash
, puedes usarlo echo $SHELL
para verificar). Pero no creo que esté garantizado que eso funcione en todos sh
, así que es mejor ir a lo seguro y separarlos.
Cualquier variable que exportes de esta manera será visible en los scripts que ejecutes, por ejemplo:
ceniza:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.sh
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
Entonces:
$ ./a.sh
The message is: hello
El hecho de que ambos sean scripts de shell también es incidental. Las variables de entorno se pueden pasar a cualquier proceso que ejecute; por ejemplo, si usáramos Python, podría verse así:
ceniza:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.py
b.py:
#!/usr/bin/python
import os
print 'The message is:', os.environ['MESSAGE']
Abastecimiento:
En su lugar, podríamos obtener fuentes como esta:
ceniza:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
b.sh:
#!/bin/sh
echo "The message is: $MESSAGE"
Entonces:
$ ./a.sh
The message is: hello
Esto más o menos "importa" el contenido de b.sh
directamente y lo ejecuta en el mismo shell . Observe que no tuvimos que exportar la variable para acceder a ella. Esto comparte implícitamente todas las variables que tiene, además de permitir que el otro script agregue/elimine/modifique variables en el shell. Por supuesto, en este modelo ambos scripts deben estar en el mismo idioma ( sh
o bash
). Para dar un ejemplo de cómo podríamos pasar mensajes de un lado a otro:
ceniza:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
echo "[A] The message is: $MESSAGE"
b.sh:
#!/bin/sh
echo "[B] The message is: $MESSAGE"
MESSAGE="goodbye"
Entonces:
$ ./a.sh
[B] The message is: hello
[A] The message is: goodbye
Esto funciona igualmente bien en bash
. También facilita compartir datos más complejos que no podría expresar como una variable de entorno (al menos sin un trabajo pesado de su parte), como matrices o matrices asociativas.
Fatal Error brindó una posibilidad sencilla: ¡obtenga su segundo script! Si le preocupa que este segundo script pueda alterar algunas de sus valiosas variables, siempre puede obtenerlo en una subcapa:
( . ./test2.sh )
Los paréntesis harán que la fuente suceda en un subshell, de modo que el shell principal no verá las modificaciones que test2.sh
se podrían realizar.
Hay otra posibilidad a la que definitivamente deberíamos hacer referencia aquí: usar set -a
.
De la referencia POSIXset
:
-a
: Cuando esta opción está activada, el atributo de exportación se establecerá para cada variable a la que se realiza una asignación; consulte el volumen Definiciones básicas de IEEE Std 1003.1-2001, Sección 4.21, Asignación de variables . Si la asignación precede al nombre de una utilidad en un comando, el atributo de exportación no persistirá en el entorno de ejecución actual después de que se complete la utilidad, con la excepción de que preceder a una de las utilidades integradas especiales hace que el atributo de exportación persista después de la ejecución integrada. en ha completado. Si la asignación no precede al nombre de una utilidad en el comando, o si la asignación es el resultado de la operación de las utilidades getopts o read , el atributo de exportación persistirá hasta que se desactive la variable.
Del manual de Bash :
-a
: marca las variables y funciones que se modifican o crean para exportar al entorno de comandos posteriores.
Entonces en tu caso:
set -a
TESTVARIABLE=hellohelloheloo
# ...
# Here put all the variables that will be marked for export
# and that will be available from within test2 (and all other commands).
# If test2 modifies the variables, the modifications will never be
# seen in the present script!
set +a
./test2.sh
# Here, even if test2 modifies TESTVARIABLE, you'll still have
# TESTVARIABLE=hellohelloheloo
Observe que las especificaciones solo especifican que set -a
la variable está marcada para exportación. Eso es:
set -a
a=b
set +a
a=c
bash -c 'echo "$a"'
hará eco c
y no una línea vacía ni b
(es decir, set +a
no desmarca para exportar, ni “guarda” el valor de la asignación solo para el entorno exportado). Este es, por supuesto, el comportamiento más natural.
Conclusión: usar set -a
/ set +a
puede ser menos tedioso que exportar manualmente todas las variables. Es superior a obtener el segundo script, ya que funcionará para cualquier comando, no solo los escritos en el mismo lenguaje Shell.