Je voudrais lancer quelque chose comme ceci:
bash -c "some_program with its arguments"
mais pour avoir un bash interactif continuez à courir après la some_program
fin.
Je suis sûr que ce -c
n'est pas un bon moyen de man bash
seys:
Un shell interactif est un shell démarré sans arguments sans option et sans l'option -c
Alors comment le faites vous ?
L'objectif principal est décrit ici
REMARQUE
- Je dois résilier
some_program
de temps en temps - Je ne veux pas le mettre en arrière-plan
- Je veux rester sur le
bash
moment pour faire autre chose - Je veux pouvoir réexécuter le programme
pty.
fg
Réponses:
Il est préférable de le faire à partir d'un script avec
exec $0.
Or ou si l'un de ces descripteurs de fichiers dirige vers un périphérique terminal qui n'est pas actuellement utilisé, cela vous aidera - vous devez vous rappeler que d'autres processus veulent également vérifier ce terminal.Et au fait, si votre objectif est, comme je le suppose, de préserver l'environnement du script après l'avoir exécuté, vous seriez probablement beaucoup mieux servi avec:
Le shell
.dot
etbash's source
ne sont pas une seule et même chose - le shell.dot
est POSIX spécifié comme un shell spécial intégré et est donc aussi proche que possible de la garantie, bien que ce ne soit en aucun cas une garantie qu'il sera là ...Bien que ce qui précède devrait faire ce que vous attendez avec peu de problèmes. Par exemple, vous pouvez:
Le shell exécutera votre script et vous renverra à l'invite interactive - tant que vous évitez d'
exit
utiliser le shell de votre script, c'est-à-dire, ou d'arrière-plan de votre processus - qui liera vos E / S à/dev/null.
DÉMO:
BEAUCOUP
JOBS
Je pense que vous devriez vous familiariser un peu avec les options de gestion des tâches intégrées du shell. @Kiwy et @jillagre ont tous deux déjà abordé ce sujet dans leurs réponses, mais cela pourrait justifier des détails supplémentaires. Et j'ai déjà mentionné un shell spécial spécifié par POSIX intégré, mais
set, jobs, fg,
et ilbg
y en a quelques autres, et, comme une autre réponse le démontre,trap
etkill
deux autres encore.Si vous ne recevez pas déjà des notifications instantanées sur l'état des processus en arrière-plan exécutés simultanément, c'est parce que vos options de shell actuelles sont définies sur la valeur par défaut spécifiée par POSIX
-m
, mais vous pouvez les obtenir de manière asynchrone avecset -b
:Une caractéristique très fondamentale des systèmes basés sur Unix est leur méthode de gestion des processus
signals
. J'ai lu une fois un article éclairant sur le sujet qui compare ce processus à la description de la planète par Douglas Adams NowWhat:Il s'agit de
kill signals
.Au moins pour moi, la citation ci-dessus a répondu à beaucoup de questions. Par exemple, j'avais toujours considéré comme très étrange et pas du tout intuitif que si je voulais surveiller un
dd
processus, je devais le fairekill
. Après avoir lu cela, cela avait du sens.Je dirais que la plupart d'entre eux n'essaient pas de s'adapter pour une bonne raison - cela peut être bien plus ennuyeux que ce serait une aubaine d'avoir un tas de processus spammant votre terminal avec les informations que leurs développeurs pensaient avoir été importantes pour vous .
En fonction de la configuration de votre terminal (avec laquelle vous pouvez vérifier
stty -a
) ,CTRL+Z
est probablement défini pour transmettre unSIGTSTP
au leader du groupe de processus de premier plan actuel, qui est probablement votre shell, et qui devrait également être configuré par défaut pourtrap
ce signal et suspendre votre dernière commande. Encore une fois, comme le montrent les réponses de @jillagre et @Kiwy, rien ne vous empêche d'adapter cette fonctionnalité à votre objectif comme vous le souhaitez.SCREEN JOBS
Donc, pour tirer parti de ces fonctionnalités, vous devez d'abord les comprendre et personnaliser leur gestion en fonction de vos propres besoins. Par exemple, je viens de trouver ce screenrc sur Github qui inclut des
screen
raccourcis clavier pourSIGTSTP
:Cela simplifierait la suspension d'un processus exécuté en tant qu'enfant
screen
processus ou duscreen
processus enfant lui-même comme vous le souhaitiez.Et immédiatement après:
OU:
Mettre en avant ou en arrière-plan le processus selon vos préférences. La fonction
jobs
intégrée peut vous fournir une liste de ces éléments à tout moment. L'ajout de l'-l
opérande inclura les détails du pid.la source
Voici une solution plus courte qui accomplit ce que vous voulez, mais qui n'a de sens que si vous comprenez le problème et comment fonctionne bash:
Cela lancera un shell bash, démarrera
some_program
et aprèssome_program
sortie, vous serez déposé sur un shell bash.Fondamentalement, ce que nous faisons est d'alimenter bash une chaîne sur son STDIN. Cette chaîne est
some_program with its arguments; exec </dev/tty
. Cela indique à bash de se lancer ensome_program
premier, puis de s'exécuter ensuiteexec </dev/tty
. Ainsi, au lieu de continuer à lire les commandes de la chaîne que nous lui transmettons, bash commencera à lire/dev/tty
.C'est
-i
parce que quand bash démarre, il vérifie si STDIN est un tty, et quand il démarre ce n'est pas le cas. Mais plus tard, ce sera le cas, nous le forçons donc en mode interactif.Une autre solution
Une autre idée à laquelle je pensais que ce serait très portable serait d'ajouter ce qui suit à la toute fin de votre
~/.bashrc
fichier.Ensuite, lorsque vous voulez d'abord lancer un shell avec une commande, faites simplement:
Explication:
La plupart de cela devrait être évident, mais le résultat de la modification du nom de variable est de sorte que nous puissions localiser la variable. Puisqu'il
$START_COMMAND
s'agit d'une variable exportée, elle sera héritée par tous les enfants du shell, et si un autre shell bash est l'un de ces enfants, il exécutera à nouveau la commande. Nous attribuons donc la valeur à une nouvelle variable non exportée ($start_command
) et supprimons l'ancienne.la source
<<<
n'est pas POSIX, mais vous pouvez le faire à laecho "string here" | bash -i
place. Ensuite, il y a/dev/tty
ce qui est une chose Linux. Mais vous pouvez dupliquer le FD avant de lancer bash, puis rouvrir STDIN, qui ressemble à ce que vous faites, mais j'ai choisi de garder les choses simples./dev/tty
n'est pas une chose Linux mais certainement POSIX.Cela devrait faire l'affaire:
Modifier:
Voici une nouvelle tentative suite à votre mise à jour:
Utilisez ControlC, vous serez présenté ce petit menu:
C'est le cas.
Sélectionnez le choix "bash"
Sélectionnez le choix "redémarrer"
la source
CTRL+C
n'est qu'un effet secondaire de la configuration par défaut de votre terminal pour l'interpréter comme unSIGINT
. Vous pouvez modifier cela à votre guisestty
.SIGINT
esttrapped
ci - dessus avec2
.Vous pouvez le faire en passant votre script en tant que fichier d'initialisation:
Ou vous pouvez le transmettre sur la ligne de commande:
Notez que cela
--init-file
était destiné à la lecture de fichiers d'initialisation à l'échelle du système, de/etc/bash.bashrc
sorte que vous souhaitiez peut-être les 'source
' dans votre script.la source
Je ne vois pas vraiment l'intérêt de faire cela, car vous revenez déjà à un shell après avoir exécuté ce programme. Cependant, vous pouvez:
Cela lancera une bash interactive après l'exécution du programme.
la source
Vous pouvez mettre la commande en arrière-plan pour garder votre bash actuel ouvert:
Pour revenir à la course, vous pouvez alors utiliser la
fg
commande et la^+z
remettre en arrière-planla source
bash
ou non, vous utilisez pour moi un shell très étranger s'il ne peut pas gérer l'arrière-plan du processus. Et je suis d'accord avec Kiwi - cette information vous servirait mieux si elle était dans votre question.Vous souhaiterez peut-être utiliser l'écran pour exécuter la commande. Vous pouvez ensuite vous reconnecter à la session une fois la commande terminée.
Sinon, exécutez simplement la commande en arrière-plan
some_program with its arguments&
. Cela vous laissera la possibilité de réexécuter la commande et d'obtenir le statut de la commande une fois celle-ci terminée.la source
screen
mais le mettre en arrière-plan ne me sert pas - j'ai parfois besoin de terminer le programme, de faire autre chose et de le relancer. Et l'objectif principal est de le faire rapidement.kill %
oukill %1
.