Digamos que tengo un script de shell / bash llamado test.sh
:
#!/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 esto es excesivo.
¿Hay una manera diferente?
Respuestas:
Básicamente tienes dos opciones:
export TESTVARIABLE
) antes de ejecutar el segundo script.. test2.sh
y se ejecutará en el mismo shell. Esto le permitiría compartir variables más complejas como matrices fácilmente, pero también significa que el otro script podría modificar las variables en el shell de origen.ACTUALIZAR:
Usar
export
para establecer una variable de entorno, puede usar una variable existente:Esto debería funcionar en ambos
bash
ysh
.bash
También permite que se combine así:Esto también funciona en mi
sh
(que resulta serbash
, puede usarecho $SHELL
para verificar). Pero no creo que esté garantizado que funcione en todossh
, así que lo mejor es ir a lo seguro y separarlos.Cualquier variable que exporte de esta manera será visible en los scripts que ejecute, por ejemplo:
ceniza:
b.sh:
Luego:
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 usamos python en su lugar, podría verse así:
ceniza:
b.py:
Abastecimiento:
En su lugar, podríamos fuente como esta:
ceniza:
b.sh:
Luego:
Esto más o menos "importa" el contenido de
b.sh
directamente y lo ejecuta en el mismo shell . Tenga en cuenta que no tuvimos que exportar la variable para acceder a ella. Esto comparte implícitamente todas las variables que tiene, así como permite que el otro script agregue / elimine / modifique variables en el shell. Por supuesto, en este modelo, ambos scripts deben ser del mismo idioma (sh
obash
). Para dar un ejemplo de cómo podríamos pasar mensajes de un lado a otro:ceniza:
b.sh:
Luego:
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 poco de trabajo pesado de su parte), como las matrices o las matrices asociativas.fuente
Fatal Error dio una posibilidad directa: ¡busca tu segundo script! Si le preocupa que este segundo script pueda alterar algunas de sus valiosas variables, siempre puede obtenerlo en una subshell:
Los paréntesis harán que la fuente suceda en una subshell, de modo que la shell principal no vea que las modificaciones
test2.sh
podrían realizarse.Hay otra posibilidad que definitivamente debería mencionarse aquí: uso
set -a
.De la referencia POSIX
set
:Del Manual de Bash :
Entonces en tu caso:
Observe que las especificaciones solo especifican que con
set -a
la variable está marcada para exportación. Es decir:hará eco
c
y no una línea vacía nib
(es decir,set +a
no desmarca la exportación, 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 la obtención del segundo script, ya que funcionará para cualquier comando, no solo los escritos en el mismo lenguaje de shell.fuente
En realidad, hay una manera más fácil que exportar y desarmar u obtener de nuevo (al menos en bash, siempre y cuando esté de acuerdo con pasar las variables de entorno manualmente):
deja a.sh ser
y b.sh be
La salida observada es
La magia se encuentra en la última línea de
a.sh
, dondeMessage
, solo por la duración de la invocación de./b.sh
, se establece en el valor desecret
froma.sh
. Básicamente, es un poco como parámetros / argumentos con nombre. Sin embargo, más que eso, incluso funciona para variables como$DISPLAY
, que controla en qué servidor X se inicia una aplicación.Recuerde, la longitud de la lista de variables de entorno no es infinita. En mi sistema con un núcleo relativamente vainilla,
xargs --show-limits
me dice que el tamaño máximo del búfer de argumentos es 2094486 bytes. Teóricamente, estás usando scripts de shell incorrectos si tus datos son más grandes que eso (tuberías, ¿alguien?)fuente
Agregando a la respuesta de Fatal Error, hay una forma más de pasar las variables a otro script de shell.
La solución sugerida anteriormente tiene algunos inconvenientes:
using Export
: Causará que la variable esté presente fuera de su alcance, lo que no es una buena práctica de diseño.using Source
: Puede provocar colisiones de nombres o sobrescribir accidentalmente una variable predefinida en algún otro archivo de script de shell que haya originado otro archivo.Hay otra solución simple disponible para que la usemos. Teniendo en cuenta el ejemplo publicado por usted,
test.sh
test2.sh
salida
También es importante tener en cuenta que
""
son necesarios si pasamos cadenas de varias palabras. Tomando un ejemplo másmaster.sh
slave1.sh
slave2.sh
salida
Ocurre debido a las razones descritas adecuadamente en este enlace.
fuente
source
es realmente una buena cosa. Con respecto a su preocupación: la sobrescritura accidental de una variable predefinida , siempre puede obtener una subshell. Eso resuelve completamente el problema.( . ./test2.sh )
. Los paréntesis harán que Bash ejecute su contenido en una subshell.En Bash, si exporta la variable dentro de una subshell, usando paréntesis como se muestra, evitará filtrar las variables exportadas:
La ventaja aquí es que después de ejecutar el script desde la línea de comandos, no verá un $ TESTVARIABLE filtrado en su entorno:
fuente
$
comandos) nunca verá el exportado$TESTVARIABLE
. Exportar solo pasa una copia de una variable a cualquier proceso secundario posterior . No es posible pasar variables de la cadena a los procesos primarios, excepto guardando el valor en el almacenamiento y leyendo ese almacenamiento más adelante en el script del proceso primario. Es posible pasar a una segunda copia del script principal, pero ese no sería el mismo proceso . Una excelente explicación se puede encontrar aquí .Otra opción está usando
eval
. Esto solo es adecuado si las cadenas son confiables. El primer script puede hacer eco de las asignaciones variables:echo "VAR=myvalue"
Luego:
eval $(./first.sh) ./second.sh
Este enfoque es de particular interés cuando el segundo script para el que desea establecer variables de entorno no está en bash y tampoco desea que
export
las variables, tal vez porque sean sensibles y no quiera que persistan.fuente
Otra forma, que es un poco más fácil para mí es usar tuberías con nombre. Las canalizaciones con nombre proporcionan una forma de sincronizar y enviar mensajes entre diferentes procesos.
Avergonzar:
B.bash:
Uso:
B.bash esperará el mensaje y tan pronto como A.bash envíe el mensaje, B.bash continuará su trabajo.
fuente