Quiero ejecutar una subshell bash, (1) ejecutar algunos comandos, (2) y luego permanecer en esa subshell para hacer lo que me plazca. Puedo hacer cada uno de estos individualmente:
Ejecute el comando usando la
-c
bandera:$> bash -c "ls; pwd; <other commands...>"
sin embargo, inmediatamente vuelve al shell "super" después de que se ejecutan los comandos. También puedo ejecutar una subshell interactiva:
Iniciar nuevo
bash
proceso:$> bash
y no saldrá de la subshell hasta que lo diga explícitamente ... pero no puedo ejecutar ningún comando inicial. La solución más cercana que he encontrado es:
$> bash -c "ls; pwd; <other commands>; exec bash"
que funciona, pero no de la manera que quería, ya que ejecuta los comandos dados en un subshell y luego abre uno separado para la interacción.
Quiero hacer esto en una sola línea. Una vez que salga del subshell, debería volver al shell "super" normal sin incidentes. Debe haber una manera ~~
NB: lo que no estoy preguntando ...
- sin preguntar dónde conseguir la página de manual de bash
- sin preguntar cómo leer los comandos de inicialización de un archivo ... Sé cómo hacer esto, no es la solución que estoy buscando
- no estoy interesado en usar la pantalla tmux o gnu
- No estoy interesado en dar contexto a esto. Es decir, la pregunta pretende ser general, y no para ningún propósito específico.
- si es posible, quiero evitar el uso de soluciones alternativas que logren lo que quiero, pero de una manera "sucia". Solo quiero hacer esto en una sola línea. En particular, no quiero hacer algo como
xterm -e 'ls'
exec bash
solución no es adecuada para usted?exec bash
solución involucra dos subcapas separadas. Quiero una subshell continua.exec
es que reemplaza el primer subshell con el segundo, por lo que solo te queda 1 shell debajo del padre. Si sus comandos de inicialización establecen variables de entorno, existirán en el shell ejecutado.exec
es que pierde todo lo que no se transmite a subcapas a través del entorno, como variables no exportadas, funciones, alias, ...Respuestas:
Esto se puede hacer fácilmente con tuberías temporales con nombre :
El crédito por esta respuesta va al comentario de Lie Ryan . Encontré esto realmente útil, y es menos notable en los comentarios, así que pensé que debería ser su propia respuesta.
fuente
$HOME/.bashrc
embargo, esto probablemente significa que no se ejecuta. Tendría que incluirse desde la tubería con nombre temporal.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
es un sinónimo delsource
comando: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
osudo -iu username bash --init-file <(echo "ls; pwd")
?Puede hacerlo de forma indirecta con un archivo temporal, aunque tomará dos líneas:
fuente
rm $BASH_SOURCE
.mktemp
resuelve el problema del archivo temporal como señaló @cjc. Bash podría soportar leer los comandos init desde stdin, pero por lo que puedo decir, no lo hace. Especificar-
como archivo init y canalizarlos a medias funciona, pero Bash luego sale (probablemente porque detectó la tubería). La solución elegante, en mi humilde opinión, es utilizar exec.Intenta esto en su lugar:
$SHELL
Hace que el shell se abra en modo interactivo, esperando un cierre conexit
.fuente
La "solución esperada" a la que me refería es programar un shell bash con el lenguaje de programación Expect :
Lo ejecutarías como:
./subshell.exp "ls; pwd"
fuente
¿Por qué no usar subshell nativos?
El encerrar comandos con paréntesis hace que bash spawn sea un subproceso para ejecutar estos comandos, por lo que puede, por ejemplo, alterar el entorno sin afectar el shell principal. Esto es básicamente más legible equivalente a
bash -c "ls; pwd; exec $BASH"
.Si eso todavía se ve detallado, hay dos opciones. Una es tener este fragmento como una función:
Otro es hacer
exec $BASH
más corto:Personalmente, me gusta
R
acercarme más, ya que no hay necesidad de jugar con cuerdas de escape.fuente
Si
sudo -E bash
no funciona, utilizo lo siguiente, que hasta ahora ha cumplido mis expectativas:Configuré HOME = $ HOME porque quiero que mi nueva sesión tenga HOME configurado en HOME de mi usuario, en lugar de HOME de root, lo que ocurre de manera predeterminada en algunos sistemas.
fuente
menos elegante que
--init-file
, pero quizás más instrumentable:fuente