Come posso inviare comandi a specifiche finestre del terminale?


13


Vorrei scrivere uno script per l'apertura di più programmi (server) simultaneamente in terminali separati - non importa quale - e assegnare comandi diversi a terminali diversi con comandi "atterranti" all'interno del terminale corretto. È possibile?
Forse qualcosa del genere:

  1. aprire il terminale 1
  2. aprire terminal2 // contemporaneamente con 1.
  3. command1 // esegue nel terminal1 senza aprire una nuova finestra del terminale
  4. command2 // esegue in terminal2 senza aprire una nuova finestra di terminale
  5. ...

Posso in qualche modo etichettare le finestre dei terminali in modo che i comandi vengano eseguiti all'interno del terminale corretto?

Mi piacerebbe anche vedere tutti i terminali mentre i loro programmi sono in esecuzione - i miei programmi hanno un argomento per stampare traccia / debug sul terminale. Quindi mi piacerebbe vedere quali messaggi vengono scambiati tra di loro.

NOTA: sono meno preoccupato per la sicurezza dei dati scambiati poiché questo script dovrebbe servire da "simulazione". Ho configurato ciascun server per l'esecuzione da una porta allocata su localhost.


Controlla pssh ....
heemayl,

Quanto devono essere precisi i tempi; una marge di diciamo 2 secondi (per terminale) è appropriata?
Jacob Vlijm,

@JacobVlijm: per me è più importante assegnare correttamente i comandi alla "finestra" del terminale corrispondente
Aliakbar Ahmadi

1
Può essere fatto, specialmente quando si tratta di simulazione, pubblicherà di nuovo :)
Jacob Vlijm,

1
@JacomVlijm: in realtà la mia domanda è stata risolta per errore: per inviare un comando alla sua istanza corretta, ogni comando deve essere preceduto dal datadir su cui inizia l'istanza! Ma per mia fortuna questo è implementato in bitcoin ma lascerò la domanda senza risposta .. forse qualcuno ha un'idea più generale per qualsiasi programma !? :) Ma grazie comunque!
Aliakbar Ahmadi,

Risposte:


14

Da quando hai detto che hai risolto il problema per la tua situazione specifica, sotto una soluzione per scopi generali. Grazie axdotool 's --syncopzione, funziona abbastanza affidabile nei test mi sono imbattuto; Ho potuto "inviare" comandi a finestre specifiche del terminale e ha funzionato perfettamente senza eccezioni.

Come funziona in pratica

La soluzione esiste da uno script, che può essere eseguito con due opzioni -sete -run:

  1. Per impostare (aprire) un numero arbitrario di finestre del terminale, in questo esempio 3:

    target_term -set 3

    Si apriranno tre nuovi terminali, il loro ID finestra viene ricordato in un file nascosto:

    inserisci qui la descrizione dell'immagine

    Per motivi di chiarezza ho minimizzato la finestra del terminale da cui ho eseguito il comando :)

  2. Ora che ho creato tre finestre, posso inviare comandi a una di esse con il comando run (es.):

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

    Come mostrato di seguito, il comando è stato eseguito nel secondo terminale:

    inserisci qui la descrizione dell'immagine

    Successivamente, posso inviare un comando al primo terminale:

     target_term -run 1 sudo apt-get update

    facendo sudo apt-get updatefunzionare nel terminal 1:

    inserisci qui la descrizione dell'immagine

    e così via...

Come impostare

  1. Lo script ha bisogno di entrambi wmctrle xdotool:

    sudo apt-get install wmctrl xdotool
  2. Copia lo script qui sotto in un file vuoto, salvalo come target_term(nessuna estensione!) In ~/bin(crea la directory ~/binse necessario.

  3. Rendi eseguibile lo script (non dimenticare) ed esegui il logout / in o esegui:

    source ~/.profile
  4. Ora imposta le finestre del tuo terminale, con il numero di finestre richieste come argomento:

    target_term -set <number_of_windows>
  5. Ora puoi "inviare" i comandi a uno dei tuoi terminali con il comando:

    target_term -run <terminal_number> <command_to_run>

Il copione

#!/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)

Appunti

  • Lo script è impostato per gnome-terminal, ma può essere utilizzato per qualsiasi terminale (o altro programma) modificando la applicationsezione head dello script:

    #--- set your terminal below
    application = "gnome-terminal"
    #---
  • I comandi sopra possono (ovviamente) essere eseguiti anche da uno script nel caso in cui ti piacerebbe utilizzarlo per una sorta di simulazione.
  • Lo script attende che sia la finestra di destinazione sia attiva e il comando abbia terminato di digitare, quindi il comando atterrerà sempre nella finestra terminale destra.
  • Non c'è bisogno di dire che lo script funziona solo con l'installazione del terminale (windows) che è stata chiamata dal comando:

    target_term -set

    Le finestre del terminale verranno quindi "etichettate" dallo script, come menzionato nella domanda.

  • Nel caso in cui avvii una nuova target_termsessione, il file nascosto, creato dallo script verrà semplicemente sovrascritto, quindi non è necessario rimuoverlo altrimenti.

Bello, grazie! Va anche notato che anche Python 3.x è un requisito per il funzionamento di questo script.
Pompalini,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.