¿Pasar todas las variables de un script de shell a otro?

Resuelto Toskan asked hace 12 años • 7 respuestas

Digamos que tengo un script shell/bash llamado test.shcon:

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh

Mi test2.shaspecto 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?

Toskan avatar Mar 19 '12 21:03 Toskan
Aceptado

Tienes básicamente dos opciones:

  1. Convierta la variable en una variable de entorno ( export TESTVARIABLE) antes de ejecutar el segundo script.
  2. 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 exportpara establecer una variable de entorno, puede usar una variable existente:

A=10
# ...
export A

Esto debería funcionar tanto en bashcomo en sh. bashtambién permite combinarlo así:

export A=10

Esto también funciona en mi sh (que resulta ser bash, puedes usarlo echo $SHELLpara 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.shdirectamente 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 ( sho 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.

FatalError avatar Mar 19 '2012 14:03 FatalError

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.shse 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 -ala variable está marcada para exportación. Eso es:

set -a
a=b
set +a
a=c
bash -c 'echo "$a"'

hará eco cy no una línea vacía ni b(es decir, set +ano 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 +apuede 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.

gniourf_gniourf avatar Feb 13 '2015 00:02 gniourf_gniourf