Esto debe ser realmente simple o realmente complejo, pero no pude encontrar nada al respecto ... Estoy tratando de abrir una nueva instancia de bash, luego ejecutar algunos comandos dentro de ella y devolver el control al usuario dentro de eso misma instancia .
Lo intenté:
$ bash -lic "some_command"
pero esto se ejecuta some_commanddentro de la nueva instancia y luego la cierra. Quiero que permanezca abierto.
Un detalle más que podría afectar las respuestas: si puedo hacer que esto funcione, lo usaré en mi .bashrccomo alias, ¡así que puntos de bonificación por una aliasimplementación!

alias shortcut='bash -lic "some_command"'en mi .bashrc y luego ejecutarshortcuty tener un nuevo shell quesome_commandya se ejecutó en él.Respuestas:
bash --rcfile <(echo '. ~/.bashrc; some_command')dispensa la creación de archivos temporales. Pregunta en otros sitios:
fuente
The system cannot find the file specified.cat ~/.bashrc? 2) ¿cat <(echo a)Funciona? 3) ¿bash --rcfile somefileFunciona?bash.exe --rcfile ^<^(echo 'source $HOME/.bashrc; ls; pwd'^)debería ejecutarse desde el símbolo del sistema de Windows.sudo bash --init-file <(echo "ls; pwd")osudo -iu username bash --init-file <(echo "ls; pwd")?Esta es una respuesta tardía, pero tuve exactamente el mismo problema y Google me envió a esta página, así que para completar, aquí es cómo solucioné el problema.
Por lo que puedo decir,
bashno tiene la opción de hacer lo que el cartel original quería hacer. La-copción siempre regresará después de que se hayan ejecutado los comandos.Solución rota : el intento más simple y obvio en torno a esto es:
bash -c 'XXXX ; bash'Esto funciona en parte (aunque con una capa de subcapa adicional). Sin embargo, el problema es que si bien un sub-shell heredará las variables de entorno exportadas, los alias y las funciones no se heredan. Entonces, esto podría funcionar para algunas cosas, pero no es una solución general.
Mejor : la forma de evitar esto es crear dinámicamente un archivo de inicio y llamar a bash con este nuevo archivo de inicialización, asegurándose de que su nuevo archivo init llame a su archivo habitual
~/.bashrcsi es necesario.# Create a temporary file TMPFILE=$(mktemp) # Add stuff to the temporary file echo "source ~/.bashrc" > $TMPFILE echo "<other commands>" >> $TMPFILE echo "rm -f $TMPFILE" >> $TMPFILE # Start the new bash shell bash --rcfile $TMPFILELo bueno es que el archivo de inicio temporal se borrará a sí mismo tan pronto como se use, lo que reduce el riesgo de que no se limpie correctamente.
Nota: no estoy seguro de si / etc / bashrc se suele llamar como parte de un shell normal sin inicio de sesión. Si es así, es posible que desee obtener / etc / bashrc además de su
~/.bashrc.fuente
rm -f $TMPFILEcosa lo hace. En realidad, no recuerdo el caso de uso que tuve para esto, y ahora uso técnicas de automatización más avanzadas, ¡pero este es el camino a seguir!bash --rcfile <(echo ". ~/.bashrc; a=b")trap.Puede pasar
--rcfilea Bash para que lea un archivo de su elección. Este archivo se leerá en lugar de su.bashrc. (Si eso es un problema, obtenga~/.bashrcla fuente del otro script).Editar: Entonces, una función para iniciar un nuevo shell con las cosas de
~/.more.shse vería así:more() { bash --rcfile ~/.more.sh ; }... y
.more.shtendría los comandos que desea ejecutar cuando se inicie el shell. (Supongo que sería elegante evitar un archivo de inicio separado; no puede usar la entrada estándar porque entonces el shell no será interactivo, pero puede crear un archivo de inicio desde un documento aquí en una ubicación temporal y luego leerlo).fuente
Puede obtener la funcionalidad que desee obteniendo el script en lugar de ejecutarlo. p.ej:
fuente
alias=''?Agregue a
~/.bashrcuna sección como esta:if [ "$subshell" = 'true' ] then # commands to execute only on a subshell date fi alias sub='subshell=true bash'Entonces puede iniciar la subcapa con
sub.fuente
env subshell=true bash(como que no se escape$subshella los comandos posteriores): El uso de env vs utilizando la exportación .env. Para verificar si está definido o no, utilizoecho $subshell(en lugar de loenv | grep subshellque usas).¡La respuesta aceptada es realmente útil! Solo para agregar que la sustitución de procesos (es decir,
<(COMMAND)) no es compatible con algunos shells (pdash.En mi caso, estaba intentando crear una acción personalizada (básicamente un script de shell de una línea) en el administrador de archivos de Thunar para iniciar un shell y activar el entorno virtual de Python seleccionado. Mi primer intento fue:
urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")donde
%fes la ruta al entorno virtual manejado por Thunar. Recibí un error (al ejecutar Thunar desde la línea de comando):/bin/sh: 1: Syntax error: "(" unexpectedLuego me di cuenta de que mi
sh(esencialmentedash) no admite la sustitución de procesos.Mi solución fue invocar
bashal nivel superior para interpretar la sustitución del proceso, a expensas de un nivel extra de shell:bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'Alternativamente, intenté usar here-document para
dashpero sin éxito. Algo como:echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfilePD: No tengo la reputación suficiente para publicar comentarios, los moderadores pueden moverlo a comentarios o eliminarlo si no es útil con esta pregunta.
fuente
De acuerdo con la respuesta de daveraja , aquí hay un script bash que resolverá el propósito.
Considere una situación si está utilizando C-shell y desea ejecutar un comando sin salir del contexto / ventana de C-shell de la siguiente manera,
Comando que se ejecutará : busque la palabra exacta 'Prueba' en el directorio actual de forma recursiva solo en archivos * .h, * .c
grep -nrs --color -w --include="*.{h,c}" Testing ./Solución 1 : ingrese a bash desde C-shell y ejecute el comando
bash grep -nrs --color -w --include="*.{h,c}" Testing ./ exitSolución 2 : escriba el comando deseado en un archivo de texto y ejecútelo usando bash
echo 'grep -nrs --color -w --include="*.{h,c}" Testing ./' > tmp_file.txt bash tmp_file.txtSolución 3 : ejecute el comando en la misma línea usando bash
bash -c 'grep -nrs --color -w --include="*.{h,c}" Testing ./'Solución 4 : cree un sciprt (una vez) y utilícelo para todos los comandos futuros
alias ebash './execute_command_on_bash.sh' ebash grep -nrs --color -w --include="*.{h,c}" Testing ./El guión es el siguiente,
#!/bin/bash # ========================================================================= # References: # https://stackoverflow.com/a/13343457/5409274 # https://stackoverflow.com/a/26733366/5409274 # https://stackoverflow.com/a/2853811/5409274 # https://stackoverflow.com/a/2853811/5409274 # https://www.linuxquestions.org/questions/other-%2Anix-55/how-can-i-run-a-command-on-another-shell-without-changing-the-current-shell-794580/ # https://www.tldp.org/LDP/abs/html/internalvariables.html # https://stackoverflow.com/a/4277753/5409274 # ========================================================================= # Enable following line to see the script commands # getting printing along with their execution. This will help for debugging. #set -o verbose E_BADARGS=85 if [ ! -n "$1" ] then echo "Usage: `basename $0` grep -nrs --color -w --include=\"*.{h,c}\" Testing ." echo "Usage: `basename $0` find . -name \"*.txt\"" exit $E_BADARGS fi # Create a temporary file TMPFILE=$(mktemp) # Add stuff to the temporary file #echo "echo Hello World...." >> $TMPFILE #initialize the variable that will contain the whole argument string argList="" #iterate on each argument for arg in "$@" do #if an argument contains a white space, enclose it in double quotes and append to the list #otherwise simply append the argument to the list if echo $arg | grep -q " "; then argList="$argList \"$arg\"" else argList="$argList $arg" fi done #remove a possible trailing space at the beginning of the list argList=$(echo $argList | sed 's/^ *//') # Echoing the command to be executed to tmp file echo "$argList" >> $TMPFILE # Note: This should be your last command # Important last command which deletes the tmp file last_command="rm -f $TMPFILE" echo "$last_command" >> $TMPFILE #echo "---------------------------------------------" #echo "TMPFILE is $TMPFILE as follows" #cat $TMPFILE #echo "---------------------------------------------" check_for_last_line=$(tail -n 1 $TMPFILE | grep -o "$last_command") #echo $check_for_last_line #if tail -n 1 $TMPFILE | grep -o "$last_command" if [ "$check_for_last_line" == "$last_command" ] then #echo "Okay..." bash $TMPFILE exit 0 else echo "Something is wrong" echo "Last command in your tmp file should be removing itself" echo "Aborting the process" exit 1 fifuente
Aquí hay otra variante (funcional):
Esto abre una nueva terminal gnome, luego en la nueva terminal ejecuta bash. Primero se lee el archivo rc del usuario, luego
ls -lase envía un comando para su ejecución en el nuevo shell antes de que se vuelva interactivo. El último eco agrega una nueva línea adicional que se necesita para finalizar la ejecución.gnome-terminal -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'También me resulta útil a veces decorar el terminal, por ejemplo, con colores para una mejor orientación.
gnome-terminal --profile green -- bash -c 'bash --rcfile <( cat ~/.bashrc; echo ls -la ; echo)'fuente
Ejecutar comandos en un shell en segundo plano
Simplemente agregue
&al final del comando, por ejemplo:fuente
$ bash --init-file <(echo 'some_command') $ bash --rcfile <(echo 'some_command')En caso de que no pueda o no quiera utilizar la sustitución de procesos:
De otra manera:
$ bash -c 'some_command; exec bash' $ sh -c 'some_command; exec sh'sh-sólo forma (dash,busybox):fuente
ENV=scriptparte) eliminada o modificada para evitar confundirse con una copia y pegar descarada de la respuesta superior.ENV+shuna, están presentes en las otras respuestas, pero en su mayoría están enterradas en toneladas de texto o rodeadas de código innecesario / no esencial. Creo que tener un resumen breve y claro beneficiaría a todos.