Comment envoyer des commandes à des fenêtres de terminal spécifiques?

13


Je voudrais écrire un script pour ouvrir plusieurs programmes (serveurs) simultanément dans des terminaux séparés - peu importe lequel - et assigner différentes commandes à différents terminaux avec des commandes «atterrissant» dans le bon terminal. Est-ce possible?
Peut-être quelque chose comme ça:

  1. terminal ouvert1
  2. ouvrir terminal2 // simultanément avec 1.
  3. command1 // s'exécute dans le terminal1 sans ouvrir une nouvelle fenêtre de terminal
  4. command2 // s'exécute dans le terminal2 sans ouvrir une nouvelle fenêtre de terminal
  5. ...

Puis-je en quelque sorte étiqueter les fenêtres du terminal pour que les commandes soient exécutées dans le bon terminal?

J'aimerais également regarder tous les terminaux pendant que leurs programmes sont en cours d'exécution - mes programmes ont un argument pour imprimer la trace / débogage sur le terminal. J'aimerais donc voir quels messages sont échangés entre eux.

REMARQUE: je suis moins préoccupé par la sécurité des données échangées car ce script devrait servir de "simulation". J'ai configuré chaque serveur pour qu'il s'exécute à partir d'un port alloué sur localhost.

Aliakbar Ahmadi
la source
Vérifiez pssh ....
heemayl
Quelle doit être la précision du timing; une marge de disons 2 secondes (par terminal) est-elle appropriée?
Jacob Vlijm
@JacobVlijm: il est plus important pour moi d'attribuer correctement les commandes selon la "fenêtre" du terminal
Aliakbar Ahmadi
1
Peut être fait, surtout lorsqu'il s'agit de simulation, sera de retour :)
Jacob Vlijm
1
@JacomVlijm: ma question est en fait résolue par hasard: pour envoyer une commande à son instance correcte, chaque commande doit être préfixée avec le datadir sur lequel l'instance démarre! Mais pour ma chance, cela est implémenté en bitcoin mais je vais juste laisser la question sans réponse .. peut-être que quelqu'un propose une idée plus générale pour n'importe quel programme!? :) Mais merci quand même!
Aliakbar Ahmadi

Réponses:

14

Puisque vous mentionnez que vous avez résolu le problème pour votre situation spécifique, ci-dessous une solution à usage général. Grâce à xdotooll' --syncoption de, cela fonctionne assez fiable dans les tests que j'ai effectués; Je pouvais «envoyer» des commandes à des fenêtres de terminal spécifiques et cela fonctionnait parfaitement sans exception.

Comment ça marche dans la pratique

La solution existe à partir d'un script, qui peut être exécuté avec deux options -setet -run:

  1. Pour configurer (ouvrir) un nombre arbitraire de fenêtres de terminal, dans cet exemple 3:

    target_term -set 3

    Trois nouveaux terminaux s'ouvriront, leur identifiant de fenêtre est mémorisé dans un fichier caché:

    entrez la description de l'image ici

    Pour des raisons de clarté, j'ai minimisé la fenêtre du terminal à partir de laquelle j'ai exécuté la commande :)

  2. Maintenant que j'ai créé trois fenêtres, je peux envoyer des commandes à l'une d'entre elles avec la commande run (par exemple):

    target_term -run 2 echo "Monkey eats banana since it ran out of peanuts"

    Comme indiqué ci-dessous, la commande a été exécutée dans le deuxième terminal:

    entrez la description de l'image ici

    Par la suite, je peux envoyer une commande au premier terminal:

     target_term -run 1 sudo apt-get update

    faire sudo apt-get updatecourir dans le terminal 1:

    entrez la description de l'image ici

    etc...

Comment installer

  1. Le script a besoin des deux wmctrlet xdotool:

    sudo apt-get install wmctrl xdotool
  2. Copiez le script ci-dessous dans un fichier vide, sauvegardez-le sous target_term(sans extension!) Dans ~/bin(créez le répertoire ~/binsi nécessaire.

  3. Rendez le script exécutable (n'oubliez pas) et déconnectez-vous ou exécutez:

    source ~/.profile
  4. Maintenant, configurez vos fenêtres de terminal, avec le nombre de fenêtres requises comme argument:

    target_term -set <number_of_windows>
  5. Vous pouvez maintenant "envoyer" des commandes à l'un de vos terminaux avec la commande:

    target_term -run <terminal_number> <command_to_run>

Le script

#!/usr/bin/env python3
import subprocess
import os
import sys
import time
#--- set your terminal below
application = "gnome-terminal"
#---

option = sys.argv[1]
data = os.environ["HOME"]+"/.term_list"

def current_windows():
    w_list = subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8")
    w_lines = [l for l in w_list.splitlines()]
    try:
        pid = subprocess.check_output(["pgrep", application]).decode("utf-8").strip()
        return [l for l in w_lines if str(pid) in l]
    except subprocess.CalledProcessError:
        return []

def arr_windows(n):
    w_count1 = current_windows()
    for requested in range(n):
        subprocess.Popen([application])
    called = []
    while len(called) < n:
        time.sleep(1)
        w_count2 = current_windows()
        add = [w for w in w_count2 if not w in w_count1]
        [called.append(w.split()[0]) for w in add if not w in called]
        w_count1 = w_count2

    return called

def run_intterm(w, command):
    subprocess.call(["xdotool", "windowfocus", "--sync", w])
    subprocess.call(["xdotool", "type", command+"\n"]) 

if option == "-set":
    open(data, "w").write("")
    n = int(sys.argv[2])
    new = arr_windows(n)
    for w in new:
        open(data, "a").write(w+"\n")
elif option == "-run":
    t_term = open(data).read().splitlines()[int(sys.argv[2])-1]
    command = (" ").join(sys.argv[3:])
    run_intterm(t_term, command)

Remarques

  • Le script est défini pour gnome-terminal, mais peut être utilisé pour n'importe quel terminal (ou tout autre programme également) en changeant le applicationdans la section head du script:

    #--- set your terminal below
    application = "gnome-terminal"
    #---
  • Les commandes ci-dessus peuvent (bien sûr) également être exécutées à partir d'un script au cas où vous souhaiteriez l'utiliser pour une sorte de simulation.
  • Le script attend jusqu'à ce que la fenêtre cible ait le focus et que la commande soit terminée en tapant, donc la commande atterrira toujours dans la fenêtre de terminal de droite.
  • Pas besoin de dire que le script ne fonctionne qu'avec la configuration du terminal (windows) qui a été appelée par la commande:

    target_term -set

    Les fenêtres du terminal seront alors "étiquetées" par le script, comme vous le mentionnez dans votre question.

  • Si vous démarrez une nouvelle target_termsession, le fichier caché, créé par le script sera simplement écrasé, il n'est donc pas nécessaire de le supprimer autrement.
Jacob Vlijm
la source
Bien joué, merci! Il convient également de noter que python 3.x est également requis pour que ce script fonctionne.
pompalini