¿Cómo puedo enviar comandos a ventanas de terminal específicas?

13


Me gustaría escribir un script para abrir múltiples programas (servidores) simultáneamente en terminales separadas, no importa cuál, y asignar diferentes comandos a diferentes terminales con comandos "aterrizando" dentro del terminal correcto. es posible?
Tal vez, algo como esto:

  1. abrir terminal1
  2. abra terminal2 // simultáneamente con 1.
  3. comando1 // ejecutar en terminal1 sin abrir una nueva ventana de terminal
  4. comando2 // ejecutar en terminal2 sin abrir una nueva ventana de terminal
  5. ...

¿Puedo etiquetar de alguna manera las ventanas de terminal para que los comandos se ejecuten dentro del terminal correcto?

También me gustaría ver todos los terminales mientras se ejecutan sus programas: mis programas tienen un argumento para imprimir el seguimiento / depuración en el terminal. Entonces me gustaría ver qué mensajes se intercambian entre ellos.

NOTA: Estoy menos preocupado por la seguridad de los datos intercambiados ya que este script debería servir como una "simulación". He configurado cada servidor para que se ejecute desde un puerto asignado en localhost.

Aliakbar Ahmadi
fuente
Compruebe pssh ....
heemayl
Cuán preciso debe ser el tiempo; ¿Es apropiado un margen de, digamos, 2 segundos (por terminal)?
Jacob Vlijm
@JacobVlijm: es más importante para mí asignar comandos correctamente a la "ventana" del terminal correspondiente
Aliakbar Ahmadi
1
Se puede hacer, especialmente cuando se trata de simulación, se publicará de nuevo :)
Jacob Vlijm
1
@JacomVlijm: en realidad mi pregunta se resuelve incidentalmente: para enviar un comando a su instancia correcta, cada comando debe tener el prefijo datadir en el que comienza esa instancia. Pero para mi suerte, esto se implementa en bitcoin, pero dejaré la pregunta sin responder ... ¿tal vez alguien tenga una idea más general para cualquier programa? :) Pero gracias!
Aliakbar Ahmadi

Respuestas:

14

Como menciona que resolvió el problema para su situación específica, a continuación encontrará una solución para fines generales. Gracias a xdotoolla --syncopción, funciona bastante confiable en las pruebas que realicé; Pude "enviar" comandos a ventanas de terminal específicas y funcionó perfectamente sin una excepción.

Cómo funciona en la práctica

La solución existe a partir de un script, que se puede ejecutar con dos opciones -sety -run:

  1. Para configurar (abrir) un número arbitrario de ventanas de terminal, en este ejemplo 3:

    target_term -set 3

    Se abrirán tres nuevas terminales, su identificación de ventana se recuerda en un archivo oculto:

    ingrese la descripción de la imagen aquí

    Por razones de claridad, minimicé la ventana de terminal desde la que ejecuté el comando :)

  2. Ahora que he creado tres ventanas, puedo enviar comandos a cualquiera de ellos con el comando de ejecución (por ejemplo):

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

    Como se muestra a continuación, el comando se ejecutó en la segunda terminal:

    ingrese la descripción de la imagen aquí

    Posteriormente, puedo enviar un comando a la primera terminal:

     target_term -run 1 sudo apt-get update

    haciendo sudo apt-get updatecorrer en la terminal 1:

    ingrese la descripción de la imagen aquí

    y así...

Como instalar

  1. El script necesita ambos wmctrly xdotool:

    sudo apt-get install wmctrl xdotool
  2. Copie el script a continuación en un archivo vacío, protéjalo como target_term(¡sin extensión!) En ~/bin(cree el directorio ~/binsi es necesario.

  3. Haga que el script sea ejecutable (no lo olvide) y cierre la sesión / inicie sesión o ejecute:

    source ~/.profile
  4. Ahora configure sus ventanas de terminal, con el número de ventanas requeridas como argumento:

    target_term -set <number_of_windows>
  5. Ahora puede "enviar" comandos a cualquiera de sus terminales con el comando:

    target_term -run <terminal_number> <command_to_run>

La secuencia de comandos

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

Notas

  • El script está configurado para gnome-terminal, pero puede usarse para cualquier terminal (u otro programa también) cambiando el applicationen la sección de encabezado del script:

    #--- set your terminal below
    application = "gnome-terminal"
    #---
  • Los comandos anteriores también se pueden ejecutar (por supuesto) desde un script en caso de que no lo use para algún tipo de simulación.
  • La secuencia de comandos espera hasta que la ventana de destino tenga el foco y el comando termine de escribir, por lo que el comando siempre aterrizará en la ventana de terminal derecha.
  • No es necesario decir que el script solo funciona con la configuración del terminal (windows) que fue invocada por el comando:

    target_term -set

    Las ventanas de terminal serán "etiquetadas" por el script, como usted menciona en su pregunta.

  • En caso de que comience una nueva target_termsesión, el archivo oculto, creado por el script, simplemente se sobrescribirá, por lo que no es necesario eliminarlo de lo contrario.
Jacob Vlijm
fuente
Agradable, gracias! También se debe tener en cuenta que python 3.x también es un requisito para que este script funcione.
pompalini