Bagaimana saya bisa mengirim perintah ke jendela terminal tertentu?

13


Saya ingin menulis skrip untuk membuka banyak program (server) secara bersamaan di terminal terpisah - tidak masalah yang mana - dan menetapkan perintah yang berbeda untuk terminal yang berbeda dengan perintah "pendaratan" di dalam terminal yang benar. Apakah ini mungkin?
Mungkin, kira-kira seperti ini:

  1. terminal terbuka1
  2. buka terminal2 // secara simultan dengan 1.
  3. command1 // jalankan di terminal1 tanpa membuka jendela terminal baru
  4. command2 // jalankan di terminal2 tanpa membuka jendela terminal baru
  5. ...

Bisakah saya memberi label windows terminal sehingga perintah dijalankan di dalam terminal yang benar?

Saya juga ingin menonton semua terminal saat program mereka berjalan - program saya memiliki argumen untuk mencetak jejak / debug ke terminal. Jadi saya ingin melihat pesan apa yang dipertukarkan di antara mereka.

CATATAN: Saya kurang khawatir tentang keamanan data yang dipertukarkan karena skrip ini harus berfungsi sebagai "simulasi". Saya telah mengkonfigurasi setiap server untuk dijalankan dari port yang dialokasikan di localhost.

Aliakbar Ahmadi
sumber
Periksa pssh ....
heemayl
Seberapa akurat seharusnya waktunya; apakah lebih dari katakanlah 2 detik (per terminal) tepat?
Jacob Vlijm
@JacobVlijm: lebih penting bagi saya untuk memberikan perintah dengan benar ke terminal "window" yang sesuai
Aliakbar Ahmadi
1
Dapat dilakukan, terutama ketika ini tentang simulasi, akan memposting kembali :)
Jacob Vlijm
1
@ JacomVlijm: sebenarnya pertanyaan saya kebetulan dipecahkan: untuk mengirim perintah ke instance yang benar, setiap perintah harus diawali dengan datadir yang memulai instance! Tetapi untuk keberuntungan saya ini diimplementasikan dalam bitcoin tetapi saya hanya akan meninggalkan pertanyaan yang belum terjawab .. mungkin seseorang datang dengan ide yang lebih umum untuk program apa pun !? :) Tapi terima kasih!
Aliakbar Ahmadi

Jawaban:

14

Karena Anda menyebutkan bahwa Anda telah memecahkan masalah untuk situasi spesifik Anda, di bawah solusi untuk tujuan umum. Berkat xdotool's --syncpilihan, bekerja dengan cukup handal dalam tes Aku berlari; Saya bisa "mengirim" perintah ke jendela terminal tertentu dan itu berjalan dengan sempurna tanpa kecuali.

Cara kerjanya dalam praktik

Solusinya ada dari skrip, yang dapat dijalankan dengan dua opsi -setdan -run:

  1. Untuk mengatur (membuka) sejumlah jendela terminal yang sewenang-wenang, dalam contoh 3 ini:

    target_term -set 3

    Tiga terminal baru akan terbuka, id window mereka diingat dalam file tersembunyi:

    masukkan deskripsi gambar di sini

    Untuk alasan kejelasan saya meminimalkan jendela terminal saya menjalankan perintah dari :)

  2. Sekarang saya membuat tiga jendela, saya dapat mengirim perintah ke salah satu dari mereka dengan menjalankan perintah (misalnya):

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

    Seperti yang ditunjukkan di bawah ini, perintah dijalankan di terminal kedua:

    masukkan deskripsi gambar di sini

    Selanjutnya, saya dapat mengirim perintah ke terminal pertama:

     target_term -run 1 sudo apt-get update

    Membuat sudo apt-get updateberjalan di terminal 1:

    masukkan deskripsi gambar di sini

    dan seterusnya...

Cara mengatur

  1. Script membutuhkan keduanya wmctrldan xdotool:

    sudo apt-get install wmctrl xdotool
  2. Salin skrip di bawah ini ke file kosong, simpan sebagai target_term(tanpa ekstensi!) Di ~/bin(buat direktori ~/binjika perlu.

  3. Jadikan skrip dapat dieksekusi (jangan lupa) dan keluar / masuk atau jalankan:

    source ~/.profile
  4. Sekarang atur jendela terminal Anda, dengan jumlah jendela yang diperlukan sebagai argumen:

    target_term -set <number_of_windows>
  5. Sekarang Anda dapat "mengirim" perintah ke salah satu terminal Anda dengan perintah:

    target_term -run <terminal_number> <command_to_run>

Naskah

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

Catatan

  • Skrip diatur untuk gnome-terminal, tetapi dapat digunakan untuk terminal apa pun (atau program lain juga) dengan mengubah applicationbagian kepala skrip:

    #--- set your terminal below
    application = "gnome-terminal"
    #---
  • Perintah di atas dapat (tentu saja) dijalankan dari skrip juga jika Anda ingin menggunakannya untuk beberapa jenis simulasi.
  • Script menunggu sampai kedua jendela yang ditargetkan memiliki fokus dan perintah selesai mengetik, sehingga perintah akan selalu mendarat di jendela terminal kanan.
  • Tidak perlu dikatakan bahwa skrip hanya berfungsi dengan pengaturan terminal (windows) yang dipanggil oleh perintah:

    target_term -set

    Jendela terminal kemudian akan "diberi label" oleh skrip, seperti yang Anda sebutkan dalam pertanyaan Anda.

  • Jika Anda memulai target_termsesi baru , file tersembunyi, yang dibuat oleh skrip hanya akan ditimpa, sehingga tidak perlu menghapusnya jika tidak.
Yakub Vlijm
sumber
Bagus, terima kasih! Juga harus dicatat bahwa python 3.x juga merupakan persyaratan agar skrip ini berfungsi.
pompalini