133 votes

Comment invoquer bash, exécuter des commandes dans le nouveau shell, puis redonner le contrôle à l'utilisateur ?

Cela doit être très simple ou très complexe, mais je n'ai rien trouvé à ce sujet... J'essaie d'ouvrir une nouvelle instance de bash, puis d'exécuter quelques commandes à l'intérieur, et de redonner le contrôle à l'utilisateur à l'intérieur de cette même instance .

J'ai essayé :

$ bash -lic "some_command"

mais cela exécute some_command dans la nouvelle instance, puis la ferme. Je veux qu'elle reste ouverte.

Un détail supplémentaire qui pourrait affecter les réponses : si je parviens à faire fonctionner ce système, je l'utiliserai dans mon programme de formation. .bashrc en tant qu'alias, donc des points bonus pour un alias la mise en œuvre !

106voto

Ciro Santilli Points 3341

59voto

daveraja Points 685

C'est une réponse tardive, mais j'ai eu exactement le même problème et Google m'a renvoyé à cette page, donc pour être complet voici comment j'ai contourné le problème.

Pour autant que je sache, bash n'a pas d'option pour faire ce que l'auteur de l'article original voulait faire. Les -c reviendra toujours après l'exécution des commandes.

Solution de rupture : La tentative la plus simple et la plus évidente est de contourner ce problème :

bash -c 'XXXX ; bash'

Cela fonctionne en partie (bien qu'avec une couche supplémentaire de sous-coquille). Cependant, le problème est que si un sous-shell hérite des variables d'environnement exportées, les alias et les fonctions ne sont pas hérités. Cela peut donc fonctionner pour certaines choses, mais ce n'est pas une solution générale.

Mieux : La solution consiste à créer dynamiquement un fichier de démarrage et à appeler bash avec ce nouveau fichier d'initialisation, en s'assurant que votre nouveau fichier init appelle votre fichier de démarrage habituel. ~/.bashrc si nécessaire.

# 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

L'avantage est que le fichier init temporaire se supprime lui-même dès qu'il est utilisé, ce qui réduit le risque qu'il ne soit pas nettoyé correctement.

Note : Je ne suis pas sûr que /etc/bashrc soit habituellement appelé dans le cadre d'un shell normal sans login. Si c'est le cas, vous pourriez vouloir sourcer /etc/bashrc ainsi que votre fichier ~/.bashrc .

8voto

soltiz Points 56
bash -c '<some command> ; exec /bin/bash'

évitera l'ajout d'une sous-couche supplémentaire

7voto

tripleee Points 28746

Vous pouvez passer --rcfile à Bash pour qu'il lise un fichier de votre choix. Ce fichier sera lu à la place de votre .bashrc . (Si c'est un problème, source ~/.bashrc de l'autre script).

Editer : Il s'agit donc d'une fonction permettant de démarrer un nouveau shell avec les éléments provenant de ~/.more.sh ressemblerait à quelque chose comme :

more() { bash --rcfile ~/.more.sh ; }

... et en .more.sh vous aurez les commandes que vous voulez exécuter lorsque le shell démarre. (Je suppose qu'il serait élégant d'éviter un fichier de démarrage séparé -- vous ne pouvez pas utiliser l'entrée standard car le shell ne serait alors pas interactif, mais vous pourriez créer un fichier de démarrage à partir d'un document ici dans un emplacement temporaire, puis le lire).

4voto

Haimo Points 31

La réponse acceptée est très utile ! Je voudrais juste ajouter que la substitution de processus (c'est-à-dire, <(COMMAND) ) n'est pas pris en charge dans certains shells (par exemple, dash ).

Dans mon cas, j'essayais de créer une action personnalisée (essentiellement un shell d'une ligne script) dans le gestionnaire de fichiers Thunar pour démarrer un shell et activer l'environnement virtuel Python sélectionné. Ma première tentative a été la suivante :

urxvt -e bash --rcfile <(echo ". $HOME/.bashrc; . %f/bin/activate;")

donde %f est le chemin d'accès à l'environnement virtuel géré par Thunar. J'ai obtenu une erreur (en lançant Thunar à partir de la ligne de commande) :

/bin/sh: 1: Syntax error: "(" unexpected

J'ai alors réalisé que mon sh (essentiellement dash ) ne prend pas en charge la substitution de processus.

Ma solution a été d'invoquer bash au niveau supérieur pour interpréter la substitution de processus, au prix d'un niveau supplémentaire de shell :

bash -c 'urxvt -e bash --rcfile <(echo "source $HOME/.bashrc; source %f/bin/activate;")'

Par ailleurs, j'ai essayé d'utiliser here-document pour dash mais sans succès. Quelque chose comme :

echo -e " <<EOF\n. $HOME/.bashrc; . %f/bin/activate;\nEOF\n" | xargs -0 urxvt -e bash --rcfile

P.S. : Je n'ai pas assez de réputation pour poster des commentaires, les modérateurs sont libres de les déplacer dans les commentaires ou de les supprimer s'ils ne sont pas utiles pour cette question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X