ฉันจะส่งคำสั่งไปยังหน้าต่างเทอร์มินัลเฉพาะได้อย่างไร


13


ฉันต้องการเขียนสคริปต์สำหรับการเปิดหลาย ๆ โปรแกรม (เซิร์ฟเวอร์) พร้อมกันในเทอร์มินัลแยกกัน - ไม่สำคัญว่าจะใช้อันไหน - และกำหนดคำสั่งต่าง ๆ ให้กับเทอร์มินัลต่าง ๆ ด้วยคำสั่ง เป็นไปได้ไหม
อาจจะเป็นอย่างนี้:

  1. เปิดเทอร์มินัล 1
  2. เปิด terminal2 // พร้อมกันกับ 1
  3. command1 // ดำเนินการใน terminal1 โดยไม่ต้องเปิดหน้าต่างเทอร์มินัลใหม่
  4. command2 // ดำเนินการใน terminal2 โดยไม่ต้องเปิดหน้าต่างเทอร์มินัลใหม่
  5. ...

ฉันสามารถติดฉลากเทอร์มินัล windows เพื่อรันคำสั่งภายในเทอร์มินัลที่ถูกต้องได้หรือไม่?

ฉันต้องการดูเทอร์มินัลทั้งหมดในขณะที่โปรแกรมกำลังทำงาน - โปรแกรมของฉันมีอาร์กิวเมนต์สำหรับการพิมพ์การติดตาม / การดีบักไปยังเทอร์มินัล ดังนั้นฉันต้องการดูว่ามีการแลกเปลี่ยนข้อความระหว่างกันอย่างไร

หมายเหตุ: ฉันไม่ค่อยกังวลเกี่ยวกับความปลอดภัยของข้อมูลที่แลกเปลี่ยนเนื่องจากสคริปต์นี้ควรทำหน้าที่เป็น "การจำลอง" ฉันได้กำหนดค่าเซิร์ฟเวอร์แต่ละเครื่องให้เรียกใช้จากพอร์ตที่จัดสรรบน localhost


ตรวจสอบpssh ....
heemayl

เวลาควรแม่นยำเพียงใด; มาร์จสมมุติว่า 2 วินาที (ต่อเทอร์มินัล) เหมาะสมหรือไม่
Jacob Vlijm

@JacobVlijm: มันเป็นสิ่งสำคัญมากขึ้นกับผมที่จะกำหนดคำสั่งที่ถูกต้องตาม "หน้าต่าง" ขั้ว
Aliakbar Ahmadi

1
สามารถทำได้โดยเฉพาะอย่างยิ่งเมื่อมันเป็นเรื่องเกี่ยวกับการจำลองจะโพสต์กลับมา :)
จาค็อบ Vlijm

1
@JacomVlijm: จริง ๆ แล้วคำถามของฉันแก้ไขโดยบังเอิญ: สำหรับการส่งคำสั่งไปยังอินสแตนซ์ที่ถูกต้องแต่ละคำสั่งจะต้องนำหน้าด้วย datadir ที่อินสแตนซ์เริ่มต้นขึ้น! แต่เพื่อความโชคดีของฉันนี่ใช้บิทคอยน์ แต่ฉันจะทิ้งคำถามที่ยังไม่ได้ตอบ .. บางทีอาจมีบางคนคิดไอเดียเพิ่มเติมสำหรับโปรแกรมใด ๆ !? :) แต่ขอบคุณนะ!
Aliakbar Ahmadi

คำตอบ:


14

เนื่องจากคุณพูดถึงว่าคุณได้แก้ไขปัญหาสำหรับสถานการณ์เฉพาะของคุณด้านล่างโซลูชันสำหรับวัตถุประสงค์ทั่วไป ขอขอบคุณที่xdotoolเป็น--syncตัวเลือกที่จะทำงานได้สวยน่าเชื่อถือในการทดสอบฉันวิ่ง; ฉันสามารถ "ส่ง" คำสั่งไปยังหน้าต่างเทอร์มินัลเฉพาะและมันทำงานได้อย่างสมบูรณ์แบบโดยไม่มีข้อยกเว้น

มันทำงานอย่างไรในทางปฏิบัติ

โซลูชันมีมาจากสคริปต์ซึ่งสามารถรันด้วยสองตัวเลือก -setและ-run:

  1. ในการตั้งค่า (เปิด) จำนวนเทอร์มินัล windows ในตัวอย่างนี้ 3:

    target_term -set 3

    สามเทอร์มินัลใหม่จะเปิดขึ้น id หน้าต่างจะถูกจดจำในไฟล์ที่ซ่อนอยู่:

    ป้อนคำอธิบายรูปภาพที่นี่

    เพื่อเหตุผลที่ชัดเจนฉันย่อเล็กสุดหน้าต่างเทอร์มินัลฉันรันคำสั่งจาก :)

  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ทำงานใน terminal 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 เป็นข้อกำหนดสำหรับสคริปต์นี้ในการทำงาน
pompalini
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.