Capturar variable de entorno específica desde sub-shell de Linux

2

Estoy tratando de encontrar una manera de ejecutar un script de shell B desde el script A, configurar o exportar una variable en el script B, y poder almacenar ese valor en el script A después de que el script B finalice y su sub-shell vuelva.

No estoy tratando de generar el script B. Sólo quiero una variable específica. Puedo agregar cosas al script A, pero no quiero que ninguna variable esté configurada en el script B para sobrescribir nada en el script A, además de lo que estoy tratando de capturar específicamente.

Estoy seguro de que hay algunas formas feas, como escribir todas las variables que me importan en A a un archivo, el script fuente B, luego leer todo desde el archivo y restaurar las variables en A, además de la variable establecida en B lo que quiero. Estoy buscando una forma relativamente limpia y directa, si existe.

NerdPirate
fuente
"No quiero que ninguna variable esté configurada en el script B para sobrescribir nada en el script A, además de lo que estoy tratando de capturar específicamente": las variables configuradas en el script B (en una subshell) no sobrescribirán ninguna variable en A. Child Los procesos no pueden escribir en sus variables de entorno del proceso padre. Tendrás que capturarlos específicamente.
Roger Lipscombe
Exactamente ... eso es lo que quiero hacer. Quiero capturarlos específicamente, como en el título de mi pregunta. Mi declaración estaba destinada a evitar las sugerencias del script de aprovisionamiento B.
NerdPirate

Respuestas:

3

Esta otra respuesta es bueno, debería ser su primera opción, especialmente si su script B hace una cosa y lo hace bien (vea Filosofía unix ) y esta "una cosa" significa "calcular este valor variable particular".

Pero, ¿y si el propósito principal de B es imprimir algo más? ¿O incluso interactuar con el usuario? Paso adicional los datos a través de la salida estándar requieren un análisis adicional del resultado recuperado. Si es así, un canal de comunicación totalmente independiente entre B y A es altamente deseado. En su caso una comunicación es suficiente.

Un archivo temporal es, de hecho, bastante bueno para ello. Pero cuando dices

maneras feas, como escribir todas las variables que me importan en A a un archivo, el script fuente B, luego leer todo de nuevo desde el archivo y restaurar las variables en A, además de la variable establecida en B que quiero

Estás poniendo la situación al revés y es realmente feo. La forma correcta es usar un archivo para pasar esta única variable deseada.

En un:

tmpf_foo=$(mktemp)

Entonces llamas a B con "$tmpf_foo" como un argumento de línea de comando y referirse al archivo por "$1" en B (o por otro número, dependiendo del diseño). Esto puede no ser conveniente si B ya analiza sus argumentos de línea de comando.

Una forma alternativa es export tmpf_foo en A y referirse al archivo como "$tmpf_foo" en B.

Si B es una herramienta de propósito general que puede usarse no solo desde A, es bueno verificar (en B) si el archivo existe, antes de escribir en él (por ejemplo, if [ -f "$tmpf_foo" ]; then … ).

De todos modos, en B escribes tu valor deseado en el archivo. P.ej. El contenido del archivo será:

12345

Después de que B finalice correctamente, en A se recupera el valor de esta manera:

specificvariable=$(<"$tmpf_foo")

(equivalente a specificvariable=$(cat "$tmpf_foo") pero sin cat; aunque no portátil).

Si necesita pasar más de una variable de B a A, puede usar varias líneas y leerlas (en A) con read. Pero si no sabe de antemano qué variables deben modificarse (o si las hay), haga que B cree líneas en el archivo para que se vea así:

specificvariable=12345
othervariable="xyz 0"
bar=baz
unset var1

Después de que B termina con éxito, en A usted obtiene el archivo:

. "$tmpf_foo"

Tenga en cuenta que puede pasar alguna ordena de esta manera (en el ejemplo anterior unset es un comando) y se ejecutará desde dentro de A. Por esta razón, debe tener mucho cuidado al escribir en el archivo desde dentro de B y debe asegurarse de que ningún otro proceso (no autorizado) pueda inyectar cadenas al archivo.

Al final (en A) eliminas el archivo temporal con rm "$tmpf_foo".

Kamil Maciorowski
fuente
Oh me gusta esto Exportar un archivo temporal se ajusta a mi caso de uso muy bien. ¡Gracias!
NerdPirate
5

Escribe esa variable específica en la salida estándar, luego en A:

specificvariable=$(/path/to/B.sh)
Ipor Sircer
fuente
3
Upvoted, pocas notas sin embargo (principalmente con usuarios sin experiencia en mente): (1) esto se ejecuta B.sh, entonces ejecutas todo el comando en lugar de la suela B.sh, no adicionalmente. (2) Esto capturará toda la salida de B.shEntonces, si el script escribe más que la variable deseada, la solución no se puede aplicar fácilmente. // Si lo deseas, puedes asimilar mis comentarios en la respuesta como si fueran tuyos (es decir, sin mencionar mi entrada); Creo que esto haría que la respuesta sea aún mejor.
Kamil Maciorowski
Esta es una buena opción, sin embargo no es para mi caso de uso, ya que B.sh emite potencialmente otra salida. Pero esta es una buena respuesta para otras personas que se encuentran con esta pregunta. Gracias
NerdPirate