วิธีตรวจสอบเทอร์มินัลอีมูเลเตอร์ใดที่ใช้อยู่ในปัจจุบัน


15

ฉันติดตั้ง gnome-terminal และ Guake แล้ว ฉันต้องการที่จะให้ข้อความเริ่มต้นที่แตกต่างกันที่จะแสดงบนเทอร์มินัลอีมูเลเตอร์เมื่อเริ่มต้น ฉันควรเขียนโค้ดอะไรใน. bashrc เพื่อให้บรรลุผล?

คำตอบ:


10

ฟังก์ชั่นนี้ควรทำงาน:

container() {
    pid=$$
    while true; do
        pid=$(ps -h -o ppid -p $pid 2>/dev/null)
        case $(ps -h -o comm -p $pid 2>/dev/null) in
        (gnome-terminal) echo "Running in gnome terminal";return;;
        (xterm) echo "Running in xterm";return;;
        (rxvt) echo "Running in rxvt";return;;
        (python) if [ ! -z "$(ps -h -o args -p $pid 2>/dev/null | grep guake)" ]; then echo "Running in Guake"; return; fi ;;
        esac
        [[ $(echo $pid) == 1 ]] && break
    done
}
container

คำตอบที่ดี! อย่าลืมเรียกใช้ฟังก์ชันด้วยcontainerหลังจากนิยาม
rosch

ฉันคาดหวังว่าสิ่งนี้จะชัดเจน แต่คุณพูดถูกต้องตอบรับการอัปเดตตามนั้น
jlliagre

@jlliagre ฉันลองใช้รหัส มันทำงานได้อย่างราบรื่นบน gnome-terminal แต่มันมีปัญหากับ Guake มันไม่ได้ให้ผลลัพธ์ใด ๆ แต่มันกลับแข็งตัวราวกับกำลังหยุดชะงัก ฉันต้องกด Ctrl + C เพื่อใช้งาน ไม่เข้าใจรหัสจริง ๆ ดังนั้นจึงไม่รู้ว่าจะเกิดอะไรขึ้น
VedVals

รหัสได้รับการแก้ไข ฉันพลาด guake ที่ทำงานโดย python และมีข้อผิดพลาดที่ทำให้ฟังก์ชันไม่สามารถออกได้ ขอบคุณสำหรับความคิดเห็น.
jlliagre

ขออภัยเพื่อน ๆ ยังไม่ได้ผล bash: [: too many argumentsให้ข้อผิดพลาด มีทุบตี v4.2.24, python v2.7.3 ถ้ามันช่วยได้
VedVals

10

ลองสิ่งนี้:

echo $TERM

สิ่งนี้มีสิทธิ์มากกว่า แต่อาจทำให้โปรแกรมของคุณยุ่งเหยิง อย่างไรก็ตามในของฉันมันพูดxtermและ ttys มันพูดlinuxซึ่งฉันคิดว่าหมายถึง Linux Console


2
$TERMเป็นตัวแปรที่อ้างถึงสเปคตามที่รายงานด้วยตนเองโดยเทอร์มินัลอีมูเลเตอร์ที่คุณใช้ไม่ใช่ตัวจำลองที่แท้จริง ตัวอย่างเช่นในระบบของฉันecho $TERMคืนค่าxtermแม้ว่าฉันกำลังเรียกใช้ lxterminal สิ่งที่เกิดขึ้นคือการปฏิบัติตามรายงาน xterm ด้วยตนเอง lxterminal lxterminal ไม่สอดคล้องกับ xterm จริง ๆ ดังนั้นคุณต้องระวัง /usr/share/terminfoไฟล์ข้อมูลจำเพาะมักจะอยู่ใน
stazher

7

คุณสามารถรับชื่อเทอร์มินัลอีมูเลเตอร์โดยการ grepping ชื่อกระบวนการผู้ปกครอง ดังนั้นจึงสามารถใช้งานได้กับเครื่องจำลองการทำงาน

ใน bash, zsh ฯลฯ :

basename "/"$(ps -f -p $(cat /proc/$(echo $$)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

ด้วยเปลือกปลา:

basename "/"(ps -f -p (cat /proc/(echo %self)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

อย่างไรก็ตามโปรดทราบว่าสิ่งนี้จะจับข้อโต้แย้งของโปรแกรมเมื่อเทอร์มินัลอีมูเลเตอร์ถูกเปิดใช้งาน
Robobenklein

ใช้งานได้หรือไม่ถ้าฉันเชื่อมต่อโดยใช้ SSH
user3731622

@ user3731622 ไม่เป็น! คุณจะต้องส่งต่อจากลูกค้า
เอนรีโก

2

ในหลายระบบecho $TERMกลับlinux xtermดูโพสต์ stazher ข้างต้น

ในการรับเครื่องที่ใช้งานจริงให้ทำสิ่งนี้:

1: ปิดทุกอินสแตนซ์เทอร์มินัลที่กำลังทำงานอยู่

2: เปิดเทอร์มินัลใหม่โดยใช้วิธีการปกติของคุณ

3: ป้อนคำสั่งดังนี้:

ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)

4: การกลับมาควรมีลักษณะดังนี้:

lxterminal --geometry=135x20

นี่คือรายละเอียด:

ดังนั้น: psคือ "สถานะกระบวนการ"

ตัวเลือก ps -oคือแสดงข้อมูลที่เกี่ยวข้องกับช่องว่างหรือรายการคำหลักที่คั่นด้วยเครื่องหมายจุลภาคที่ระบุ ฟังดูซับซ้อน แต่ไม่ได้จริงๆ (เว้นวรรคหรือเครื่องหมายจุลภาค) คั่น (รายการคำหลัก) ที่ระบุ

ดังนั้น (รายการคำหลัก) เป็น'cmd='เพียงหนึ่งคำหลักในรายการ ดังนั้นเพียงแค่ขอให้แสดงคำสั่งเพื่อเปิดเทอร์มินัล

ตัวเลือก ps -pคือ "รหัสกระบวนการ" ว้าวนี่เป็นตัวเลือกที่ดีมากสำหรับ ps ปัญหาคือคุณต้องส่งไปยัง ps รหัสกระบวนการนี้ ดังนั้นวิธีรับ id กระบวนการ? เราแกะการแสดงออก $(ps -o 'ppid=' -p $$)

ที่นี่เราจะต้องเริ่มคิดลึกลงไปอีกหน่อย ฉันหวังว่าฉันจะประดิษฐ์นี้ bash หนึ่งซับ แต่ฉันไม่ได้ ฉันคิดว่าฉันขโมยมันจากhttps://wiki.archlinux.org/ที่ไหนสักแห่งฉันหาอีกไม่พบ พวกนั้นยอดเยี่ยม แต่หลายครั้งฉันไม่สามารถเข้าใจสิ่งที่พวกเขาบอกว่าจะทำจนกระทั่งหลังจากการศึกษามาก สิ่งที่เราทำได้คือเข้าใจในตอนนี้เพราะฉันจะอธิบาย

ดังนั้นเราจึงรู้ว่า$ผู้ประกอบการส่วนขยายในทุบตี ฉันชอบคิดว่า "un-wrap" ดังนั้น$(foo -opt bar)จะแกะหรือขยาย "foo -opt bar" แต่ในทุบตีรั้งรอบเดียว(...)เปิด subshell

ดังนั้น$(foo -opt bar)ขยาย "foo -opt บาร์" เป็นระยะในเปลือกลูกสาว แปลกมากและเข้าใจยาก

ตกลงดังนั้นตอนนี้เราจะใช้คำสั่งเหมือนกันเกือบอีกครั้งps -o 'ppid=' -p $$แต่คราวนี้ PS เวลาสถานะกระบวนการแสดงให้เราเห็นสิ่งที่เขาสามารถมองเห็นจากภายในเช่นเปลือกลูกสาว

-oรายการคำหลักเพียงคำเดียวก่อนหน้าppid=นี้แต่จะขอรหัสกระบวนการโดยตรงของเปลือกหอย !! จากภายในเปลือกหอย! ฉลาดมากใช่ไหม ฉันตื่นเต้นมากเมื่อฉันเข้าใจสิ่งนี้!

-pอีกครั้ง "ตามกระบวนการ id" และใน bash $$คือรหัสกระบวนการ

หากคุณโทรps -o 'ppid=' -p $$หรือคำสั่งอื่น ๆ ที่ขอ$$โดยตรงจากเชลล์แรกเขาอาจพูดว่า pid = 1 หรือ pid จาก xWindow หรือจากโปรแกรมเดสก์ท็อปของคุณหรือคุณอาจได้รับ pid เชลล์จริง หากคุณถามหลายครั้งคุณอาจได้รับคำตอบที่แตกต่างกันในแต่ละครั้ง!

แต่ถ้าคุณเรียกลูกสาวและถามเธอว่า "ใครคือพ่อของคุณ" เธอจะบอกคุณ! ฉลาดมาก. ฉันหวังว่าฉันจะเป็นอัจฉริยะเช่นนี้ในการคิดค้นวิธีการนี้


ตกลงดังนั้น AU จะไม่อนุญาตให้มีการวิเคราะห์ที่เหมาะสมภายในหนึ่งโพสต์ ขออภัยไม่ต้องการต่อสู้กับระบบบล็อกและสร้างโพสต์หลายรายการ บางทีคุณอาจจะได้ความคิด
stazher

คำตอบอื่น ๆ ของคุณดูเหมือนจะเป็นความคิดเห็นที่ซับซ้อนและให้ข้อมูลเกี่ยวกับคำตอบนี้แทนที่จะตอบคำถาม ... มันจะดีถ้าคุณสามารถรวมสองคำตอบเป็นหนึ่งและลบหนึ่งคำตอบและเพิ่มไปเพื่อให้มัน ตอบคำถามอย่างเต็มที่ ใช้ ---- เพื่อวาดเส้นตรงกลาง? นอกจากนี้ยังมีปุ่ม
Zanna

ฉันคิดว่าฉันได้ตอบคำถาม OP อย่างแน่นอนและในรายละเอียดคุณกระโดดมาที่ฉันก่อนที่ฉันจะมีโอกาสเข้าใจระบบแก้ไขบล็อกและเสร็จสิ้น นำมาลงคะแนนฉันคุ้นเคยกับมัน
stazher

1
ฉันไม่คิดว่าฉันเพิ่มขึ้นกับคุณฉันเพียงแค่ทำการตรวจสอบ ... ขอบคุณที่ทำให้การโพสต์ของคุณสมบูรณ์มากขึ้น
Zanna

ขอขอบคุณสำหรับการตอบสนองของคุณ. ฉันขอโทษฉันอาจจะกระโดดขึ้นกับคุณ ฉันขอโทษมาก
stazher

1

การใช้pstreeและawkเป็นวิธีที่ง่ายที่สุด:

pstree -sA $$ | awk -F "---" '{ print $2 }'

อธิบาย

  1. แสดงต้นไม้ของกระบวนการที่มีpstreeของ$$(กระบวนการ atual)
  2. pstreeข้อโต้แย้ง:

    • -s: แสดงพาเรนต์ของกระบวนการ
    • -A: แสดงผลใน pure ASCII
  3. awkเครื่องมือสแกนรูปแบบและ-Fข้อโต้แย้งที่จะใช้ในการแยกกระบวนการ

  4. ในที่สุดก็'{ print $2 }'บอกให้awkส่งออกเฉพาะรูปแบบการจับคู่ที่ 2 (ในกรณีนี้ชื่อจำลองเทอร์มินัล)

คุณแน่ใจ$2เหรอ ในกรณีของฉันสิ่งที่ส่งเข้ามาawkนั้นจริง ๆ แล้วsystemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis

@EnricoMariaDeAngelis Ya ขอบคุณสำหรับการสังเกต ในกรณีของฉันเทอร์มินัลอีมูเลเตอร์เริ่มต้นโดยตรงในบริการ systemd ฉันตรวจสอบรหัสอีกครั้งและแก้ไขด้วยการแก้ไข
silvadev

สิ่งนี้ไม่ทำงานเมื่อฉันใช้แป้นพิมพ์ลัดเพื่อเรียกใช้ตัวจำลอง บน XFCE ฉันได้รับxfsettingsdแทนที่จะใช้เทอร์มินัล
Michael Hoffmann

ทำงานได้ดีขึ้นถ้าคุณเริ่มต้นจากจุดสิ้นสุด: pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff

0

คุณถูกต้องฉันทำเพียงคำตอบสำหรับคำถามหัวข้อไม่ใช่คำถามในร่างกาย ดังนั้นที่นี่คุณไปและลุงของบ๊อบ

ฉันไม่แน่ใจว่าสวิตช์ตัวเรือนเป็นอย่างไรในหนึ่งคำตอบที่แสดงไว้ด้านบน ไม่จำเป็นต้องสลับสวิตช์กรณีดังกล่าว สคริปต์ ~ / .bashrc ของฉันเป็นเพียงหนึ่งบรรทัดง่ายๆคำสั่ง echo ทั้งหมดนั้นสนุก จะอธิบายอย่างไร ...

คำใด ๆ เมื่อเริ่มอ่าน ~ / .bashrc และดำเนินการคำสั่งอะไรก็ตามที่เขาจะเห็นใน. bashrc ดังนั้นไม่ว่าจะเรียกคำใดคำหนึ่งเขาจะอ่าน. bashrc และดำเนินการคำสั่งดังนั้นโครงสร้างที่จำเป็นใน. bashrc เท่านั้นที่จะแก้ไขพฤติกรรมของหรือแยกคำหนึ่งหรืออีกคำหนึ่งออก พฤติกรรมที่ต้องการสำหรับทุกคำศัพท์ในการดำเนินการคำสั่งเดียวกันดังนั้นไม่จำเป็นต้องสลับกรณี เทอร์มินัลจะบอกคุณว่าเขาถูกเรียกดังนั้นจึงไม่จำเป็นต้องแยกความแตกต่าง

หมายเหตุ (1) ฉันไม่ได้ทดสอบการหลอกลวง แต่ทำงานเพื่อคนอื่น ๆ ที่กล่าวถึงในคำตอบแรกโดย jlliagre

หมายเหตุ (2) เนื่องจากการจัดรูปแบบใน markdown สำหรับ wiki คุณไม่สามารถตัดและวางตามที่แสดง คุณต้องลบแต่ละbacktickรวมทั้งการลบตัวอักษรที่ขีดเส้นใต้และเพิ่ม backtick ที่เกิดขึ้นจริงกับไม่มีช่องว่างก่อนหรือหลังps-p $$)

สคริปต์สำหรับ ~ / .bashrc

# show welcome message for actual terminal in use
echo "Welcome.  You are attempting to use"
echo ""
echo _backtick_ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)_backtick_
echo ""
echo "Good Luck and God Speed."

มันสนุกมาก ฉันได้เพิ่มสิ่งนี้ใน ~ / .bashrc ของฉันเอง


ต่อ Note (1) ทดสอบบน Tilda แล้วใช้งานได้ดี Guake คล้ายกับ Tilda แต่เขียนด้วยภาษาไพ ธ อนดังนั้นจึงยังไม่รู้เกี่ยวกับ Guake
stazher


0

หากคุณกำลังใช้ ZSH จะมีวิธีแก้ปัญหาที่ดีกว่า (เร็วกว่า) ซึ่งใช้ ZSH builtins และจัดการ/proc/$pid/{stat,cmdline}โดยตรงเท่านั้น

get-terminal-emulator() {
    if [[ $TTY = "/dev/tty"* ]]; then
        echo "linux-console"
        return
    fi
    local pid=$$ name=''
    while true; do
        proc_stat=(${(@f)$(</proc/${pid}/stat)})
        name=${proc_stat[2]//[()]/}
        case "${name}" in
            gnome-terminal|konsole|rxvt|xterm)
                echo "${name}"; return ;;
            python*)
                local cmdline=(${(@f)$(</proc/${pid}/cmdline)})
                if [[ "$cmdline" =~ "\\bguake.main\\b" ]]; then
                    echo "guake"; return
                fi
                ;;
        esac
        if test "$pid" = "1" -o "$pid" = ""; then
            echo "unknown"
            return
        fi
        pid=${proc_stat[4]}       
    done
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.