Як я можу надсилати команди до конкретних вікон терміналів?


13


Я хотів би написати сценарій для відкриття декількох програм (серверів) одночасно в окремих терміналах - неважливо, який з них - і призначити різні команди різним терміналам з командами "посадка" всередині потрібного терміналу. Чи можливо це?
Можливо, щось подібне:

  1. відкритий термінал1
  2. відкритий термінал2 // одночасно з 1.
  3. command1 // виконувати в terminal1 без відкриття нового вікна терміналу
  4. command2 // виконувати в terminal2 без відкриття нового вікна терміналу
  5. ...

Чи можу я якось позначити вікна терміналу, щоб команди виконувалися всередині правильного терміналу?

Я також хотів би переглянути всі термінали, поки їх програми працюють - у моїх програм є аргумент для друку трасування / налагодження до терміналу. Тож я хотів би побачити, якими повідомленнями обмінюються між собою.

ПРИМІТКА. Мене менше турбує безпека обмінюваних даних, оскільки цей сценарій повинен слугувати "симуляцією". Я налаштував кожен сервер для запуску з виділеного порту на localhost.


Перевірте pssh ....
heemayl

Наскільки точними повинні бути терміни; чи підходить марж, скажімо, 2 секунди (за термінал)?
Яків Влійм

@JacobVlijm: для мене важливіше правильно призначити команди відповідно до термінального "вікна"
Aliakbar Ahmadi

1
Це можна зробити, особливо якщо мова йде про моделювання, опублікуватимемо :)
Яків Влійм

1
@JacomVlijm: насправді моє запитання вирішено випадково: для відправки команди на її правильний екземпляр кожна команда повинна мати префікс із datadir, з якого починається екземпляр! Але на щастя, це реалізовано в біткойнах, але я просто залишу питання без відповіді. Можливо, хтось придумає більш загальну ідею для будь-якої програми !? :) Але дякую хоч!
Аліакбар Ахмаді

Відповіді:


14

Оскільки ви згадуєте, ви вирішили проблему для вашої конкретної ситуації, нижче - рішення загального призначення. Завдяки опції xdotool'' --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 також є вимогою для роботи цього сценарію.
помпаліні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.