Je veux exécuter un sous-shell bash, (1) exécuter quelques commandes, (2), puis rester dans ce sous-shell pour faire ce que je veux. Je peux faire chacune de ces choses individuellement:
Exécutez la commande en utilisant
-c
flag:$> bash -c "ls; pwd; <other commands...>"
Cependant, il retourne immédiatement au "super" shell après l'exécution des commandes. Je peux aussi simplement lancer un sous-shell interactif:
Démarrer un nouveau
bash
processus:$> bash
et il ne quittera pas le sous-shell tant que je ne le dirai pas explicitement ... mais je ne pourrai exécuter aucune commande initiale. La solution la plus proche que j'ai trouvée est:
$> bash -c "ls; pwd; <other commands>; exec bash"
qui fonctionne, mais pas comme je le voulais, car il exécute les commandes données dans un sous-shell, puis en ouvre un autre pour l’interaction.
Je veux le faire sur une seule ligne. Une fois que je quitte le sous-shell, je devrais revenir au shell "super" habituel sans incident. Il doit y avoir un moyen ~~
NB: Ce que je ne demande pas ...
- ne pas demander où trouver la page de manuel bash
- ne demande pas comment lire les commandes d'initialisation à partir d'un fichier ... Je sais comment faire cela, ce n'est pas la solution que je cherche
- pas intéressé à utiliser tmux ou gnu screen
- pas intéressé à donner un contexte à cela. C'est-à-dire que la question est censée être générale et non à des fins spécifiques
- Si possible, je veux éviter d'utiliser des solutions de contournement qui accomplissent ce que je veux, mais d'une manière "sale". Je veux juste faire ceci sur une seule ligne. En particulier, je ne veux pas faire quelque chose comme
xterm -e 'ls'
exec bash
solution ne vous convient-elle pas?exec bash
solution implique deux sous-réservoirs distincts. Je veux un sous-shell continu.exec
est qu'il remplace le premier sous-shell par le second, de sorte qu'il ne vous reste qu'un shell en dessous du parent. Si vos commandes d'initialisation définissent des variables d'environnement, elles existeront dans le shell exécuté.exec
c'est que vous perdez tout ce qui n'est pas transmis aux sous-shell via l'environnement, tels que les variables non exportées, les fonctions, les alias, ...Réponses:
Cela peut être facilement fait avec des pipes nommées temporaires :
Le mérite de cette réponse revient au commentaire de Lie Ryan . J'ai trouvé cela vraiment utile, et c'est moins visible dans les commentaires, alors j'ai pensé que cela devrait être sa propre réponse.
la source
$HOME/.bashrc
n'est pas exécuté si. Il devrait être inclus à partir du canal nommé temporaire.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
est un synonyme de lasource
commande: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
ousudo -iu username bash --init-file <(echo "ls; pwd")
?Vous pouvez le faire de manière détournée avec un fichier temporaire, bien que cela prenne deux lignes:
la source
rm $BASH_SOURCE
.mktemp
résout le problème des fichiers temporaires, comme @cjc l’a souligné. Bash pourrait prendre en charge la lecture des commandes init à partir de stdin, mais pour autant que je sache, ce n'est pas le cas. Spécifier-
comme un fichier init et les canaliser à moitié fonctionne, mais Bash se ferme alors (probablement parce qu'il a détecté le pipeline). La solution élégante, à mon humble avis, consiste à utiliser exec.Essayez ceci à la place:
$SHELL
Cela rend le shell ouvert en mode interactif, en attente d'une fermeture avecexit
.la source
La "solution Expect" à laquelle je faisais référence est la programmation d'un shell bash avec le langage de programmation Expect :
Vous courriez ça comme:
./subshell.exp "ls; pwd"
la source
Pourquoi ne pas utiliser les sous-shell natifs?
Lorsque les commandes sont entourées de parenthèses, bash génère un sous-processus pour exécuter ces commandes. Vous pouvez ainsi modifier l'environnement sans affecter le shell parent. Ceci est fondamentalement plus lisible équivalent à la
bash -c "ls; pwd; exec $BASH"
.Si cela semble toujours verbeux, il y a deux options. L'une consiste à avoir cet extrait de code en tant que fonction:
Une autre est de faire
exec $BASH
plus court:Personnellement, j'aime
R
mieux aborder, car il n'est pas nécessaire de jouer avec des ficelles qui s'échappent.la source
Si
sudo -E bash
cela ne fonctionne pas, j'utilise ce qui suit, ce qui a répondu à mes attentes jusqu'à présent:J'ai défini HOME = $ HOME parce que je souhaite que ma nouvelle session ait HOME défini sur HOME de l'utilisateur, plutôt que sur HOME, ce qui se produit par défaut sur certains systèmes.
la source
moins élégant que
--init-file
, mais peut-être plus instrumentable:la source