Come verificare quale emulatore di terminale è attualmente in uso?


15

Ho gnome-terminal e Guake installati. Voglio dare diversi messaggi di avvio da visualizzare su questi emulatori di terminali all'avvio. Quale codice dovrei scrivere in .bashrc per raggiungere questo obiettivo?

Risposte:


10

Questa funzione dovrebbe fare il lavoro:

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

Bella risposta! Non dimenticare di chiamare effettivamente la funzione con containerdopo la definizione.
Rosch

Mi aspettavo che questo fosse ovvio, ma hai ragione, rispondi aggiornato di conseguenza.
jlliagre,

@jlliagre Ho provato il codice. Funziona senza problemi su gnome-terminal ma ha un problema su Guake. Non dà alcun output. Invece si blocca come se fosse in deadlock. Devo Ctrl + C per usarlo. Non ho davvero capito il codice, quindi non so dove sta andando storto.
VedVals

Codice fisso Mi sono perso guake è gestito da Python e aveva un bug che impediva l'uscita della funzione. Grazie per il feedback.
jlliagre,

Mi dispiace amico, non funziona ancora del tutto. Dà errore bash: [: too many arguments. Ottenuto bash v4.2.24, python v2.7.3 se aiuta.
VedVals,

10

Prova questo:

echo $TERM

Questo è più autorevole, ma potrebbe essere incasinato dai tuoi programmi. Comunque sul mio, dice xterme su tty dice linux, che penso sia l'acronimo di Linux Console.


2
$TERMè una variabile che si riferisce alla specifica come auto-segnalata dall'emulatore di terminale che si sta utilizzando, non all'emulatore stesso. Ad esempio, sul mio sistema, echo $TERMritorna xtermanche se in realtà sto eseguendo lxterminal. Quello che sta succedendo è la conformità xterm di auto-report estremi. lxterminal non è in realtà completamente conforme a xterm, quindi devi fare attenzione. I file delle specifiche si trovano di solito in /usr/share/terminfo.
Stazher

7

È possibile ottenere il nome dell'emulatore di terminale immettendo il nome del processo parent. Pertanto funziona con ogni emulatore di terminale.

In bash, zsh, ecc .:

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

Con guscio di pesce:

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

Si noti tuttavia che questo catturerà gli argomenti del programma quando l'emulatore di terminale viene lanciato con loro.
Robobenklein,

Funziona se sono connesso tramite SSH?
user3731622

@ user3731622 non lo farà! Dovrai inoltrarlo dal client.
Enrico,

2

Su molti sistemi linux echo $TERMreturn xtermvedi post più stazher sopra.

Per utilizzare il terminale effettivo, procedere come segue:

1: Chiudi tutte le istanze del terminale attualmente in esecuzione.

2: Apri un nuovo terminale usando il tuo solito metodo.

3: immettere il comando come segue:

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

4: Il ritorno dovrebbe essere qualcosa del genere:

lxterminal --geometry=135x20

Ecco la ripartizione:

Così: ps è "stato del processo"

opzione ps -o è Visualizza informazioni associate all'elenco di parole chiave specificato da spazi o virgole. Sembra complicato, ma non lo è. (spazio o virgola) separato (elenco di parole chiave) specificato.

Quindi, (elenco di parole chiave) è 'cmd=' solo una parola chiave nell'elenco. Quindi, sto solo chiedendo di visualizzare il comando per aprire il terminale.

opzione ps -p è "per ID processo" Wow, questa è un'opzione molto bella per ps. Il problema è che devi passare a ps questo id processo. Quindi, come ottenere l'ID processo? Scartiamo l'espressione $(ps -o 'ppid=' -p $$)

Qui dobbiamo iniziare a pensare un po 'più a fondo. Vorrei aver inventato questo bash one-liner, ma non l'ho fatto. Penso di averlo rubato da qualche parte da https://wiki.archlinux.org/ , che non sono riuscito a trovare. Quei ragazzi sono fantastici, ma molte volte non riesco a capire cosa dicono di fare fino a dopo molti studi. Quello che possiamo fare è capirlo ora, perché lo spiegherò.

quindi sappiamo che $è l'operatore di espansione in bash. Mi piace pensare "un-wrap". Quindi, $(foo -opt bar)scarterà o espanderà "foo -opt bar". Ma in bash, la parentesi graffa rotonda singola (...)apre subshell.

Quindi, $(foo -opt bar)espande "foo -opt bar" come eseguito nella shell figlia . Molto strano e difficile da capire.

OK, quindi ora stiamo eseguendo di nuovo un comando quasi identico, ps -o 'ppid=' -p $$ma questa volta ps, lo stato del processo, ci mostra cosa può vedere dall'istanza della shell figlia .

-oelenco di parole chiave, solo una parola chiave come prima, ma ppid=questo richiede direttamente l'id di processo della shell padre !! Da WITHIN DAUGHTER SHELL! Molto intelligente, sì? Sono così eccitato quando posso capirlo!

-pdi nuovo, "per ID processo" e in bash $$è l'ID processo.

Se chiami ps -o 'ppid=' -p $$, o qualsiasi altro comando che richiede $$direttamente dalla prima shell, potrebbe dire pid = 1, o il pid da xWindow, o dal tuo programma desktop, o potresti ottenere un vero pid di shell. Se lo chiedi più volte, potresti ricevere risposte diverse ogni volta!

Ma se invochi una figlia e le chiedi "Chi è il tuo papà" te lo dirà! Molto intelligente. Vorrei poter essere così geniale da inventare questo metodo.


OK, quindi AU non consentirà un'adeguata suddivisione in un post. Siamo spiacenti, non sono disposto a combattere con il sistema di blog e a pubblicare più post. Forse puoi farti un'idea.
Stazher

La tua altra risposta sembra essere un commento sofisticato e informativo su questa risposta piuttosto che una risposta alla domanda ... Sarebbe bello se tu potessi combinare le tue due risposte in una e cancellarne una e aggiungerla in modo che risponde pienamente alla domanda. Usa ---- per tracciare una linea nel mezzo? C'è anche un pulsante.
Zanna

Penso di aver risposto esattamente alla domanda OP, e in dettaglio. Mi hai saltato addosso prima che avessi la possibilità di capire il sistema di modifica del blog e di finire. Metti i voti bassi, ci sono abituato.
Stazher

1
Non credo di averti saltato addosso, stavo solo facendo una recensione ... grazie per aver reso il tuo post più completo
Zanna

Grazie per la vostra risposta. Mi dispiace, forse ti sono saltato addosso. Mi scuso molto.
Stazher

1

Usare pstreeed awkè il modo più semplice:

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

spiegando

  1. Visualizza un albero di processi con pstreeof $$(il processo effettivo).
  2. Gli pstreeargomenti:

    • -s: mostra i genitori di un processo
    • -A: visualizza l'output in puro ASCII.
  3. Lo awkstrumento analizza un modello e un -Fargomento viene utilizzato per dividere i processi.

  4. Alla fine '{ print $2 }'dice di awkemettere solo il secondo modello di corrispondenza (in questo caso, il nome dell'emulatore di terminale).

Ne sei sicuro $2? Nel mio caso, ciò che viene convogliato è in awkrealtà systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis,

@EnricoMariaDeAngelis Ya. Grazie per la tua osservazione Nel mio caso l'emulatore di terminale si inizializza direttamente nel servizio systemd. Ricontrollo il codice e lo modifico con una correzione.
silvadev,

Questo non funziona quando uso una scorciatoia da tastiera per avviare l'emulatore. Su XFCE, ottengo xfsettingsdinvece il terminale che sto usando.
Michael Hoffmann,

Funziona meglio se inizi dalla fine:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff

0

Hai ragione, ho solo dato una risposta alla domanda principale, non alla domanda nel corpo. Quindi ecco qua e Bob è il tuo zio.

Non sono sicuro di quale sia stato il cambio di caso, in una risposta mostrata sopra. Tale interruttore caso non è necessario. Il mio script ~ / .bashrc è in realtà solo una riga semplice, tutti i comandi echo sono solo per divertimento. Come spiegare...

Qualsiasi termine all'avvio legge ~ / .bashrc ed esegue tutti i comandi che vedrà in .bashrc. Quindi, indipendentemente dal termine chiamato, leggerà .bashrc ed eseguirà i comandi, quindi solo la struttura necessaria in .bashrc sarebbe quella di modificare il comportamento o escludere un termine o un altro. Il comportamento desiderato è che ogni termine esegua lo stesso comando, quindi non è necessario cambiare caso. Lo stesso Terminal ti dirà come è stato chiamato, quindi non è necessario differenziare.

Nota (1) Non ho testato il falso, ma funziona per tutti gli altri citati nella prima risposta da jlliagre.

Nota (2) A causa della formattazione nel markdown per wiki, non è possibile tagliare e incollare come mostrato. È necessario eliminare ogni backtick , anche per eliminare i caratteri di sottolineatura, e aggiungere backtick effettivo, senza spazio prima pso dopo il -p $$).

script per ~ / .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."

Questo è stato molto divertente. Ho aggiunto questo al mio ~ / .bashrc.


per Nota (1), hanno testato su Tilda, funziona benissimo. Guake è simile a Tilda, ma è scritto in pitone, quindi non conosco ancora Guake.
Stazher

0

se stai usando bash, penso che questo comando ti aiuterà:

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


0

Se stavi usando ZSH, esiste una soluzione migliore (più veloce), che utilizza solo i builtin ZSH e manipola /proc/$pid/{stat,cmdline}direttamente.

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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.