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_command
dentro 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 .bashrc
como alias, ¡así que puntos de bonificación por una alias
implementación!
alias shortcut='bash -lic "some_command"'
en mi .bashrc y luego ejecutarshortcut
y tener un nuevo shell quesome_command
ya 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 somefile
Funciona?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,
bash
no tiene la opción de hacer lo que el cartel original quería hacer. La-c
opció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
~/.bashrc
si 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 $TMPFILE
Lo 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 $TMPFILE
cosa 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
--rcfile
a 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~/.bashrc
la fuente del otro script).Editar: Entonces, una función para iniciar un nuevo shell con las cosas de
~/.more.sh
se vería así:more() { bash --rcfile ~/.more.sh ; }
... y
.more.sh
tendrí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
~/.bashrc
una 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$subshell
a 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 subshell
que 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
%f
es 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: "(" unexpected
Luego me di cuenta de que mi
sh
(esencialmentedash
) no admite la sustitución de procesos.Mi solución fue invocar
bash
al 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
dash
pero sin éxito. Algo como:echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile
PD: 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 ./ exit
Solució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.txt
Solució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 fi
fuente
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 -la
se 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=script
parte) eliminada o modificada para evitar confundirse con una copia y pegar descarada de la respuesta superior.ENV
+sh
una, 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.