Cómo averiguar las variables de entorno establecidas después de iniciar sesión en una sesión de shell

1

¿Cómo puedo averiguar las variables de entorno establecidas después de iniciar sesión en una sesión de shell?

Mis dos soluciones ficticias han sido las siguientes:

_VariableName1="VarValue1";export _VariableName1;
_VariableName2="VarValue2";export _VariableName2;

...

set | grep '_' 

... que casi muestra las variables establecidas después del inicio de sesión (aquellas diferentes a las vars establecidas .bash_profile y .bashrc ). Este enfoque me hace olvidarme constantemente del guión bajo en las vars, y los viejos gurús del trabajo se ríen de mí cuando lo ven;)

El segundo enfoque es utilizar "variables legibles por humanos", pero ejecutar después de iniciar sesión o sudo:

 su - username the 
 set > /tmp/vars.before 

establecer los vars

 VariableName1="VarValue1";export VariableName1;
 VariableName2="VarValue2";export VariableName2;

set > /tmp/vars.after

... y luego ejecute el siguiente comando:

 comm -13 /tmp/vars.before /tmp/vars.after

o

 comm --nocheck-order -3 /tmp/vars.before /tmp/vars.after

dependiendo de comm binario etc.

Entonces, ¿cuál es la forma más limpia o inteligente de descubrirlo?

Yordan Georgiev
fuente

Respuestas:

3

Un enfoque es anular export y unset Con funciones que hacen un seguimiento de sus variables.

Tenga en cuenta que para que esto funcione usted debe exportar variables como esta: export <variable>=<value>.

Las dos funciones deben ser llamadas export y unset y mantenga una lista de sus variables en un archivo, que nombraré ~/.track$$ ( $$ es el PID de tu shell actual):

export ()
{
    if echo $@ | egrep -q '[^=]+=[^=]+' && builtin export "$@" && echo $- | grep -q i; then          # [1]
        touch ~/.track$$                                                                             # [2]
        cp -fa ~/{.track$$,.track$$.bak} 2> /dev/null;                                               # [3]  
        grep -v "^$(echo $@ | sed 's/\([^=]=\).\+/\1/')" < ~/.track$$.bak > ~/.track$$ 2> /dev/null; # [4]
        echo $@ >> ~/.track$$;                                                                       # [5]
    fi
}

unset ()
{
    if builtin unset $@ && echo $- | grep -q i; then                # [1]
        touch ~/.track$$                                            # [2]
        cp -fa ~/{.track$$,.track$$.bak} 2> /dev/null;              # [3]
        egrep -v "^$@=" < ~/.track$$.bak > ~/.track$$ 2> /dev/null; # [4]
    fi
}

Además, debe averiguar qué variables de entorno ha establecido. Un alias como este lo hará:

alias iset="cat ~/.track$$ 2>/dev/null"

Un alias como este:

alias ireset="rm ~/.track$$ >/dev/null 2>&1"

se puede utilizar para restablecer la lista.

Para mantener el número de ~/.track$$ archivos al mínimo podemos usar este comando de limpieza:

rm $(ls -d ~/.* | egrep 'track[0-9]+$|track[0-9]+\.bak$' | egrep -v $(ps -ef | grep bash | grep -v grep | awk '{print $2}' | tr '\n' '|' | sed 's/|$//')) > /dev/null 2>&1

¿Dónde deberíamos poner estas funciones, alias, etc?

Le recomendaría que agregue las funciones, los alias y el comando de limpieza al final de ~/.bashrc, para que las subshells obtengan las funciones también. Dependiendo de tu distro y como /etc/profile, /etc/bash.bashrc y los amigos se ejecutan, puede definirlos demasiado pronto (en algunas distribuciones ~/.profile fuentes ~/.bashrc o al revés) por lo que puede que tenga que ajustarlo.

Luego cierre la sesión y vuelva a iniciar sesión.

Ahora si corres export <variable>=<value> en tu sesión de bash la función export:

  • [1] verifica si el parámetro está bien formado (esto es para evitar entradas falsas al escribir export MYVAR, porque su valor de retorno es 0 y crearía una entrada en ~/.track$$ )

  • [1] entonces ejecuta builtin export <variable>=<value> (esto establece la variable, independientemente de lo que suceda después)

  • [1] entonces se agita $- para ver si se trata de una shell interactiva (ver esta respuesta Cuando ssh en una máquina de Ubuntu, qué tipo de shell estoy usando [enchufe desvergonzado]). De forma predeterminada, las subshells no heredan funciones, por lo que los scripts no se crean ~/.track$$ archivos. Si un script usa #!/bin/bash -i, aunque, lo hará. Esto lo evitará.

  • [2] entonces toca ~/.track$$ para asegurarse de que existe y

  • [3] hace una copia de respaldo

  • [4] luego verifica si la variable ya existe, si ese es el caso, se elimina de ~/.track$$

  • [5] finalmente, agrega una línea a ~/.track$$

Del mismo modo, si escribe unset <variable> y golpear Entrar la función unset:

  • [1] ejecuta builtin unset <variable> (esto elimina la variable, independientemente de lo que ocurra después)

  • [1] si unset Fue exitoso lo comprueba, como en el export función de arriba Si esto es un shell interactivo (ver esta respuesta Cuando ssh en una máquina de Ubuntu, qué tipo de shell estoy usando [enchufe desvergonzado]). Por defecto, las subshells no heredan funciones, por lo que los scripts no crean ~/.track$$ archivos. Si un script usa #!/bin/bash -i, aunque, lo hará. Esto lo evitará.

  • [2] entonces toca ~/.track$$ para asegurarse de que existe y

  • [3] luego hace una copia de respaldo de ~/.track$$

  • [4] elimina la entrada variable de ~/.track$$

Cuál es el builtin ¿Qué palabra clave utilicé en ambas funciones? Ya que export o unset son shell builtins (es decir, comandos que vienen con el shell) que necesito usar builtin, que es en sí mismo un comando incorporado (desde man bash ):

shell-builtin builtin [argumentos]

Ejecute el shell especificado, pasándole argumentos y devuelva su estado de salida. Esto es útil cuando se define una función cuyo nombre es el mismo que el de una shell incorporada, manteniendo la funcionalidad de la incorporada dentro de la función. El CD incorporado se redefine de esta manera. El estado de retorno es falso si shell-builtin no es un comando incorporado de shell.

El comando de limpieza enumera y filtra los activos ~/.track$$ archivos y elimina el resto.

Lo que obtienes con esta configuración:

  • Ya no es necesario usar guiones bajos. Simplemente usa el familiar export comando (que ha sido anulado con una función) y funcionará.

  • Cada bash sesión tiene su propio ~/.track$$ expediente. No colisiones entre conchas.

  • Como efecto secundario de lo anterior, las subshells no heredan las de los padres. ~/.track$$ Archivo, aunque heredan todas las variables de entorno.

  • Variables de entorno establecidas en archivos de origen ( . file o source file ) se agregan a ~/.track$$.

  • Las variables de entorno establecidas en una () subshell también se rastrean (incorrectamente), porque $$ se expande a la ID de proceso del shell actual, no a la subshell (ver man bash ).

  • Las variables se enumeran desde el primero hasta el último exportado.

  • Variables establecidas por .profile y otros guiones que usted reasignar (incluso con el mismo valor) será listado por iset. Por ejemplo, HOME es usualmente establecido por .profile. Si lo haces export HOME=/usr/local/bin:$HOME y correr iset ya verás HOME listado

Y ahora algunos ejemplos:

  • Las variables exportadas se muestran con iset:

    $ export MYVAR1=0987654321; iset
    MYVAR1=0987654321
    
  • Las variables redefinidas se tratan adecuadamente:

    $ export MYVAR2="this is a string"; iset
    MYVAR1=0987654321
    MYVAR2=this is a string
    $ export MYVAR2="this is a different string for the same variable"; iset
    MYVAR1=0987654321
    MYVAR2=this is a different string for the same variable
    
  • Entorno según env partidos iset salida:

    $ env|grep MYVAR
    MYVAR2=this is a different string for the same variable
    MYVAR1=0987654321
    
  • Las variables de solo lectura no se agregan a ~/.track$$:

    $ export EUID=0; iset
    -bash: EUID: readonly variable
    MYVAR1=0987654321
    
  • Antiguos, los archivos de pista que ya no se utilizan se eliminan cuando ~/.bashrc se ejecuta (por ejemplo, al crear una subshell):

    $ ls -1 ~/.track*
    .track11002
    .track11002.bak
    .track21774
    .track21774.bak
    .track2923
    .track2923.bak
    .track7382
    .track7382.bak
    .track8374
    .track8374.bak
    $ echo $$
    2923
    $ bash
    <subshell>$ ls -1 ~/.track*
    .track2923
    .track2923.bak
    
jaume
fuente
De nada, me alegro de poder ayudar.
jaume
Su enfoque puede ser derrotado de 3 formas: 1. Desactive una var que fue exportada por .profile. (el cambio no se mostrará) 2. Descomprima y vuelva a exportar (al valor original) una var que fue exportada por .profile. (será listado incorrectamente por iset ) 3. export myvar; myvar=value ( iset mostrará el valor incorrecto).
Hugh Allen
@Hugh Allen: Estoy de acuerdo con 3., export var=value debe usarse, edité mi respuesta para que sea más clara, gracias por leerla y señalarlo. A partir de 2., si entiendo correctamente, el OP desea descubrir las variables de entorno que están establecidas (es decir, a las que se les asigna un valor) después de iniciar sesión, por lo que alguna Var conjunto después debe ser seguido. En consecuencia, vars exportados por .profile, si se configura más tarde, se agregan a iset. Con respecto a 1., no veo cómo se puede eliminar una var de iset de salida si nunca se le agregó. 1. es el comportamiento deseado: vars establecido por .profile y no reasignados no son monitoreados.
jaume
Puede que tengas razón. Supuse que Yordan quería saber sobre cualquier cambio, incluidas las variables que no estaban definidas, según su segundo enfoque utilizando un comando de comparación.
Hugh Allen
1

Si te interesa ambiente solo variables, debes usar env en lugar de set. No estoy muy seguro de si entiendo correctamente lo que estás tratando de lograr, pero parece que

env | sort > /tmp/vars.before

después de iniciar sesión, seguido de

env | sort > /tmp/vars.after
comm -13 /tmp/vars.before /tmp/vars.after

en algún momento posterior hace lo correcto, al menos si ninguna de sus variables de entorno contiene una cadena que incluya una nueva línea. (Si lo hace, me gustaría usar env -0 | sort -z para obtener las variables de entorno separadas por valores nulos y luego usar perl para comparación, o programar todo en perl.)

Uwe
fuente
0

Si desea saber qué variables de entorno se han establecido, simplemente ingrese el siguiente comando:

printenv
Bruno
fuente