Как я могу отправлять команды в определенные окна терминала?

13


Я хотел бы написать скрипт для одновременного открытия нескольких программ (серверов) в отдельных терминалах - неважно, какой из них - и назначать разные команды для разных терминалов с командами «посадки» внутри нужного терминала. Это возможно?
Может быть, что-то вроде этого:

  1. открыть терминал1
  2. открыть терминал 2 // одновременно с 1.
  3. command1 // выполнить в терминал1, не открывая новое окно терминала
  4. command2 // выполнить в терминал2, не открывая новое окно терминала
  5. ...

Можно ли как-то пометить окна терминала, чтобы команды выполнялись внутри правильного терминала?

Я также хотел бы наблюдать за всеми терминалами, пока их программы работают - у моих программ есть аргумент для печати трассировки / отладки на терминал. Поэтому я хотел бы посмотреть, какие сообщения обмениваются между ними.

ПРИМЕЧАНИЕ: я меньше беспокоюсь о безопасности обмениваемых данных, так как этот скрипт должен служить «симуляцией». Я настроил каждый сервер для запуска с выделенного порта на localhost.

Алиакбар Ахмади
источник
Проверьте pssh ....
Heemayl
Насколько точным должно быть время? допустим, скажем, маржа в 2 секунды (на терминал)?
Якоб Влийм
@JacobVlijm: для меня важнее правильно назначать команды для соответствующего терминального «окна»
Алиакбар Ахмади
1
Может быть сделано, особенно когда речь идет о симуляции, отправит обратно :)
Якоб Vlijm
1
@JacomVlijm: на самом деле мой вопрос случайно решен: для отправки команды ее правильному экземпляру перед каждой командой должен стоять префикс данных, с которого начинается экземпляр! Но, к счастью, это реализовано в биткойнах, но я просто оставлю вопрос без ответа .. возможно, кто-то придумает более общую идею для любой программы !? :) Но спасибо, хотя!
Алиакбар Ахмади

Ответы:

14

Поскольку вы упоминаете, что решили проблему для конкретной ситуации, ниже приведено решение для общего назначения. Благодаря xdotool«S --syncвариант, он работает довольно надежен в тестах я побежал; Я мог «отправлять» команды в определенные окна терминала, и он работал без исключений.

Как это работает на практике

Решение существует из сценария, который может быть запущен с двумя вариантами -setи -run:

  1. Чтобы установить (открыть) произвольное количество окон терминала, в этом примере 3:

    target_term -set 3

    Откроются три новых терминала, их идентификатор окна запомнен в скрытом файле:

    введите описание изображения здесь

    Для ясности я свернул окно терминала, из которого запускал команду :)

  2. Теперь, когда я создал три окна, я могу отправлять команды любому из них с помощью команды run (например):

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

    Как показано ниже, команда выполняется во втором терминале:

    введите описание изображения здесь

    Впоследствии я могу отправить команду на первый терминал:

     target_term -run 1 sudo apt-get update

    решений на sudo apt-get updateработы в терминале 1:

    введите описание изображения здесь

    и так далее...

Как настроить

  1. Скрипту нужны оба wmctrlи xdotool:

    sudo apt-get install wmctrl xdotool
  2. Скопируйте приведенный ниже скрипт в пустой файл, сохраните его как target_term(без расширения!) В ~/bin(создайте каталог, ~/binесли это необходимо.

  3. Сделайте скрипт исполняемым (не забудьте) и выйдите из системы, войдите в нее или запустите:

    source ~/.profile
  4. Теперь настройте окна терминала, указав в качестве аргумента количество необходимых окон:

    target_term -set <number_of_windows>
  5. Теперь вы можете «отправлять» команды на любой из ваших терминалов с помощью команды:

    target_term -run <terminal_number> <command_to_run>

Сценарий

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

Примечания

  • Скрипт установлен для gnome-terminal, но может использоваться для любого терминала (или другой программы), изменив applicationв разделе заголовка скрипта:

    #--- set your terminal below
    application = "gnome-terminal"
    #---
  • Вышеприведенные команды могут (конечно) также запускаться из скрипта, если вы захотите использовать его для какой-то симуляции.
  • Сценарий ожидает, пока целевое окно не будет сфокусировано, и команда не завершит набор текста, поэтому команда всегда будет находиться в правом окне терминала.
  • Не нужно говорить, что скрипт работает только с настройками терминала (windows), которые были вызваны командой:

    target_term -set

    Окна терминала будут «помечены» сценарием, как вы упомянули в своем вопросе.

  • Если вы начинаете новый target_termсеанс, скрытый файл, созданный сценарием, будет просто перезаписан, поэтому нет необходимости удалять его в противном случае.
Якоб Влейм
источник
Хороший, спасибо! Также следует отметить, что python 3.x также является обязательным требованием для работы этого скрипта.
Помпалини