scripts script programas pasar parametros manejo español ejemplos comandos cadenas bash shell csh tcsh

bash - programas - shell script linux español



¿Puede un script de shell establecer variables de entorno del shell de llamada? (21)

Agregue la marca -l en la parte superior de su script de bash, es decir

#!/usr/bin/env bash -l ... export NAME1="VALUE1" export NAME2="VALUE2"

Los valores con NAME1 y NAME2 ahora se habrán exportado a su entorno actual, sin embargo, estos cambios no son permanentes. Si desea que sean permanentes, debe agregarlos a su archivo .bashrc u otro archivo de inicio.

De las páginas del manual:

-l Make bash act as if it had been invoked as a login shell (see INVOCATION below).

Estoy tratando de escribir un script de shell que, cuando se ejecute, establecerá algunas variables de entorno que permanecerán establecidas en el shell del llamante.

setenv FOO foo

en csh / tcsh, o

export FOO=foo

in sh / bash solo lo configuro durante la ejecución del script.

eso ya lo se

source myscript

ejecutará los comandos de la secuencia de comandos en lugar de lanzar un nuevo shell, y eso puede resultar en configurar el entorno del "llamador".

Pero aquí está el problema:

Quiero que este script sea llamable desde bash o csh. En otras palabras, quiero que los usuarios de cualquiera de los shell puedan ejecutar mi script y que se cambie el entorno de su shell. Así que ''source'' no funcionará para mí, ya que un usuario que ejecuta csh no puede generar una secuencia de comandos bash, y un usuario que ejecuta bash no puede obtener una secuencia de comandos csh.

¿Hay alguna solución razonable que no implique tener que escribir y mantener DOS versiones en el script?


Aparte de los escritos, los condicionales dependen de lo que se establece en $ SHELL / $ TERM, no. ¿Qué hay de malo en usar Perl? Es bastante ubicuo (no puedo pensar en una sola variante de UNIX que no la tenga), y le ahorrará el problema.


Bajo OS X bash puedes hacer lo siguiente:
Crea el archivo de script bash para desarmar la variable

#!/bin/bash unset http_proxy

Hacer el archivo ejecutable.

sudo chmod 744 unsetvar

Crear alias

alias unsetvar=''source /your/path/to/the/script/unsetvar''

Debería estar listo para usar siempre que tenga la carpeta que contiene su archivo de script adjunto a la ruta.


Creé una solución utilizando tuberías, eval y señal.

parent() { if [ -z "$G_EVAL_FD" ]; then die 1 "Rode primeiro parent_setup no processo pai" fi if [ $(ppid) = "$$" ]; then "$@" else kill -SIGUSR1 $$ echo "$@">&$G_EVAL_FD fi } parent_setup() { G_EVAL_FD=99 tempfile=$(mktemp -u) mkfifo "$tempfile" eval "exec $G_EVAL_FD<>''$tempfile''" rm -f "$tempfile" trap "read CMD <&$G_EVAL_FD; eval /"/$CMD/"" USR1 } parent_setup #on parent shell context ( A=1 ); echo $A # prints nothing ( parent A=1 ); echo $A # prints 1

Podría funcionar con cualquier comando.



En mi .bash_profile tengo:

# No Proxy function noproxy { /usr/local/sbin/noproxy #turn off proxy server unset http_proxy HTTP_PROXY https_proxy HTTPs_PROXY } # Proxy function setproxy { sh /usr/local/sbin/proxyon #turn on proxy server http_proxy=http://127.0.0.1:8118/ HTTP_PROXY=$http_proxy https_proxy=$http_proxy HTTPS_PROXY=$https_proxy export http_proxy https_proxy HTTP_PROXY HTTPS_PROXY }

Entonces, cuando quiero deshabilitar el proxy, las funciones se ejecutan en el shell de inicio de sesión y establecen las variables según lo esperado y deseado.


Es "posible" mediante el uso de gdb y setenv(3) , aunque me cuesta mucho recomendar hacer esto. (Además, es decir, la ubuntu más reciente no le permitirá hacer esto sin decirle al kernel que sea más permisivo con respecto a ptrace, y lo mismo puede suceder con otras distribuciones también).

$ cat setfoo #! /bin/bash gdb /proc/${PPID}/exe ${PPID} <<END >/dev/null call setenv("foo", "bar", 0) END $ echo $foo $ ./setfoo $ echo $foo bar


Esto funciona, no es lo que yo usaría, pero ''funciona''. Vamos a crear un script para establecer la variable de entorno TEREDO_WORMS :

#!/bin/ksh export TEREDO_WORMS=ukelele exec $SHELL -i

Será interpretado por el shell Korn, exporta la variable de entorno y luego se reemplaza a sí mismo con un nuevo shell interactivo.

Antes de ejecutar este script, hemos establecido SHELL en el entorno al shell C, y la variable de entorno TEREDO_WORMS no está configurada:

% env | grep SHELL SHELL=/bin/csh % env | grep TEREDO %

Cuando se ejecuta el script, se encuentra en un shell nuevo, otro shell C interactivo, pero la variable de entorno se establece:

% teredo % env | grep TEREDO TEREDO_WORMS=ukelele %

Al salir de este shell, el shell original toma el control:

% exit % env | grep TEREDO %

La variable de entorno no está configurada en el entorno del shell original. Si usa exec teredo para ejecutar el comando, entonces el shell interactivo original es reemplazado por el shell Korn que establece el entorno, y luego ese es reemplazado por un nuevo shell C interactivo:

% exec teredo % env | grep TEREDO TEREDO_WORMS=ukelele %

Si escribe exit (o Control-D ), entonces su shell se cierra, probablemente desconectándose de esa ventana, o regresando al nivel anterior de shell desde donde comenzaron los experimentos.

El mismo mecanismo funciona para Bash o Korn shell. Es posible que el aviso después de los comandos de salida aparezca en lugares divertidos.

Tenga en cuenta la discusión en los comentarios. Esta no es una solución que recomendaría, pero logra el propósito declarado de un solo script para configurar el entorno que funciona con todos los shells (que aceptan la opción -i para crear un shell interactivo). También puede agregar "$@" después de la opción de retransmitir cualquier otro argumento, lo que luego podría hacer que el shell sea utilizable como una herramienta general ''establecer entorno y ejecutar comando''. Es posible que desee omitir el -i si hay otros argumentos, lo que lleva a:

#!/bin/ksh export TEREDO_WORMS=ukelele exec $SHELL "${@-''-i''}"

El bit "${@-''-i''}" significa'' si la lista de argumentos contiene al menos un argumento, use la lista de argumentos original; de lo contrario, sustituya -i por los argumentos inexistentes ''.


Hice esto hace muchos años. Si me acuerdo correctamente, incluí un alias en cada uno de .bashrc y .cshrc, con parámetros, alias las formas respectivas de configurar el entorno en una forma común.

Luego, el script que obtendrá en cualquiera de los dos shells tiene un comando con esa última forma, que es un alias adecuado para cada shell.

Si encuentro los alias concretos, los publicaré.


La respuesta corta es no, no puede alterar el entorno del proceso principal, pero parece que lo que desea es un entorno con variables de entorno personalizadas y el shell que el usuario ha elegido.

Entonces, ¿por qué no simplemente algo como

#!/usr/bin/env bash FOO=foo $SHELL

Luego, cuando haya terminado con el medio ambiente, simplemente exit .


No es lo que yo llamaría sobresaliente, pero esto también funciona si necesita llamar al script desde el shell de todos modos. No es una buena solución, pero para una sola variable de entorno estática, funciona lo suficientemente bien.

1.) Cree un script con una condición que salga de 0 (Correcto) o 1 (No exitoso)

if [[ $foo == "True" ]]; then exit 0 else exit 1

2.) Cree un alias que dependa del código de salida.

alias=''myscript.sh && export MyVariable''

Llama al alias, que llama al script, que evalúa la condición, que se requiere para salir de cero a través de ''&&'' para establecer la variable de entorno en el shell principal.

Se trata de restos flotantes, pero puede ser útil en caso de apuro.


No podrá modificar el shell de la persona que llama porque está en un contexto de proceso diferente. Cuando los procesos secundarios heredan las variables de su shell, ellos heredan las copias.

Una cosa que puedes hacer es escribir un script que emita los comandos correctos para tcsh o sh según cómo se invoque. Si tu script es "setit" entonces haz:

ln -s setit setit-sh

y

ln -s setit setit-csh

Ahora bien, directamente o en un alias, haces esto desde sh

eval `setit-sh`

o esto de csh

eval `setit-csh`

setit usa $ 0 para determinar su estilo de salida.

Esto es reminiscente de cómo se usa la gente para obtener el conjunto de variables de entorno TERM.

La ventaja aquí es que setit está escrito en cualquier shell que te guste como en:

#!/bin/bash arg0=$0 arg0=${arg0##*/} for nv in / NAME1=VALUE1 / NAME2=VALUE2 do if [ x$arg0 = xsetit-sh ]; then echo ''export ''$nv'' ;'' elif [ x$arg0 = xsetit-csh ]; then echo ''setenv ''${nv%%=*}'' ''${nv##*=}'' ;'' fi done

con los enlaces simbólicos dados anteriormente, y la evaluación de la expresión backquoted, esto tiene el resultado deseado.

Para simplificar la invocación de csh, tcsh o shells similares:

alias dosetit ''eval `setit-csh`''

o para sh, bash, y similares:

alias dosetit=''eval `setit-sh`''

Una cosa buena sobre esto es que solo tienes que mantener la lista en un solo lugar. En teoría, incluso podría pegar la lista en un archivo y colocar cat nvpairfilename entre "in" y "do".

Esto es más o menos lo que solía hacer la configuración del terminal de shell de inicio de sesión: una secuencia de comandos generaría las instrucciones que se ejecutarán en el shell de inicio de sesión. Generalmente se usaría un alias para simplificar la invocación, como en "tset vt100". Como se mencionó en otra respuesta, también hay una funcionalidad similar en el servidor de noticias INN UseNet.


No veo ninguna respuesta que documente cómo solucionar este problema con procesos de cooperación. Un patrón común con cosas como ssh-agent es hacer que el proceso hijo imprima una expresión que el padre puede eval .

bash$ eval $(shh-agent)

Por ejemplo, ssh-agent tiene opciones para seleccionar sintaxis de salida compatible con Csh o Bourne.

bash$ ssh-agent SSH2_AUTH_SOCK=/tmp/ssh-era/ssh2-10690-agent; export SSH2_AUTH_SOCK; SSH2_AGENT_PID=10691; export SSH2_AGENT_PID; echo Agent pid 10691;

(Esto hace que el agente comience a ejecutarse, pero no le permite usarlo realmente, a menos que ahora copie y pegue esta salida en el indicador de comandos de su shell). Compare:

bash$ ssh-agent -c setenv SSH2_AUTH_SOCK /tmp/ssh-era/ssh2-10751-agent; setenv SSH2_AGENT_PID 10752; echo Agent pid 10752;

(Como puede ver, csh y tcsh usan setenv para establecer las variables).

Tu propio programa también puede hacer esto.

bash$ foo=$(makefoo)

Su script makefoo simplemente calcularía e imprimiría el valor, y permitiría a la persona que llama hacer lo que quiera con él. Asignarlo a una variable es un caso de uso común, pero probablemente no sea algo que desee incluir en la herramienta que produce el código. valor.


Otra opción es usar "Módulos de entorno" ( http://modules.sourceforge.net/ ). Lamentablemente, esto introduce un tercer idioma en la mezcla. Usted define el entorno con el lenguaje de Tcl, pero hay algunos comandos prácticos para las modificaciones típicas (anteponer frente a añadir frente a conjunto). También necesitarás tener instalados módulos de entorno. Luego puede usar el module load *XXX* para nombrar el entorno que desea. El comando del módulo es básicamente un alias elegante para el mecanismo de eval descrito anteriormente por Thomas Kammeyer. La principal ventaja aquí es que puede mantener el entorno en un idioma y confiar en "Módulos de entorno" para traducirlo a sh, ksh, bash, csh, tcsh, zsh, python (?!? !!), etc.


Otra solución que no veo mencionada es escribir el valor de la variable en un archivo.

Me encontré con un problema muy similar en el que quería poder ejecutar la última prueba de configuración (en lugar de todas mis pruebas). Mi primer plan fue escribir un comando para configurar la variable env TESTCASE, y luego tener otro comando que usaría esto para ejecutar la prueba. No hace falta decir que tuve el mismo problema exacto que tú.

Pero luego se me ocurrió este simple truco:

Primer comando ( testset ):

#!/bin/bash if [ $# -eq 1 ] then echo $1 > ~/.TESTCASE echo "TESTCASE has been set to: $1" else echo "Come again?" fi

Segundo comando ( testrun ):

#!/bin/bash TESTCASE=$(cat ~/.TESTCASE) drush test-run $TESTCASE


Puede indicar al proceso hijo que imprima sus variables de entorno (llamando a "env"), luego haga un bucle sobre las variables de entorno impresas en el proceso principal y llame a "exportar" sobre esas variables.

El siguiente código se basa en la captura de salida de encontrar. -print0 en una matriz de bash

Si el shell primario es el bash, puedes usar

while IFS= read -r -d $''/0'' line; do export "$line" done < <(bash -s <<< ''export VARNAME=something; env -0'') echo $VARNAME

Si el shell primario es el guión, la read no proporciona la marca -d y el código se complica

TMPDIR=$(mktemp -d) mkfifo $TMPDIR/fifo (bash -s << "EOF" export VARNAME=something while IFS= read -r -d $''/0'' line; do echo $(printf ''%q'' "$line") done < <(env -0) EOF ) > $TMPDIR/fifo & while read -r line; do export "$(eval echo $line)"; done < $TMPDIR/fifo rm -r $TMPDIR echo $VARNAME


Puedes invocar otro Bash con los diferentes bash_profile. Además, puede crear bash_profile especial para usar en un entorno multi-bashprofile.

Recuerde que puede usar funciones dentro de bashprofile, y que las funciones estarán disponibles de forma global. por ejemplo, "function user {export USER_NAME $ 1}" puede establecer una variable en tiempo de ejecución, por ejemplo: usuario olegchir && env | grep olegchir


Siempre se podrían usar alias.

alias your_env=''source ~/scripts/your_env.sh''


Su proceso de shell tiene una copia del entorno principal y no tiene acceso al entorno del proceso principal en absoluto. Cuando su proceso de shell termina, cualquier cambio que haya hecho en su entorno se perderá. La obtención de un archivo de script es el método más comúnmente utilizado para configurar un entorno de shell, es posible que solo desee morder la bala y mantener una para cada uno de los dos tipos de shell.


Técnicamente, eso es correcto, solo ''eval'' no bifurca otro shell. Sin embargo, desde el punto de vista de la aplicación que está intentando ejecutar en el entorno modificado, la diferencia es nula: el elemento secundario hereda el entorno de su principal, por lo que el entorno (modificado) se transmite a todos los procesos descendentes.

Ipso facto, la variable de entorno modificada se "pega", siempre y cuando se esté ejecutando bajo el programa / shell padre.

Si es absolutamente necesario que la variable de entorno permanezca después de que el padre (Perl o shell) haya salido, es necesario que el shell primario haga el trabajo pesado. Uno de los métodos que he visto en la documentación es que la secuencia de comandos actual genere un archivo ejecutable con el lenguaje de ''exportación'' necesario, y luego engañe a la shell primaria para que lo ejecute, siempre consciente del hecho de que necesita prefacio Comando con ''source'' si está intentando dejar atrás una versión no volátil del entorno modificado. Un Kluge en el mejor de los casos.

El segundo método es modificar la secuencia de comandos que inicia el entorno de shell (.bashrc o lo que sea) para que contenga el parámetro modificado. Esto puede ser peligroso: si aplica la secuencia de comandos de inicialización, es posible que su shell no esté disponible la próxima vez que intente iniciarse. Hay muchas herramientas para modificar el shell actual; al colocar los ajustes necesarios en el ''lanzador'', también puede impulsar esos cambios. Generalmente no es una buena idea; Si solo necesita los cambios de entorno para un conjunto de aplicaciones en particular, tendrá que regresar y devolver el script de inicio de shell a su estado original (usando vi o lo que sea) después.

En resumen, no hay métodos buenos (y fáciles). Presumiblemente, esto se hizo difícil para garantizar que la seguridad del sistema no se viera comprometida de manera irrevocable.


Utilice la "sintaxis de llamada" del espacio de puntos. Por ejemplo, aquí está cómo hacerlo usando la ruta completa a un script:

. /path/to/set_env_vars.sh

Y aquí está cómo hacerlo si está en el mismo directorio que el script:

. set_env_vars.sh

Estos ejecutan el script bajo el shell actual en lugar de cargar otro (que es lo que sucedería si lo ./set_env_vars.sh ). Debido a que se ejecuta en el mismo shell, las variables de entorno que establezca estarán disponibles cuando salga.

Esto es lo mismo que llamar a la source set_env_vars.sh , pero es más corto de escribir y puede funcionar en algunos lugares donde la source no lo hace.