Risposte:
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
bash: [: too many arguments
. Ottenuto bash v4.2.24, python v2.7.3 se aiuta.
Prova questo:
echo $TERM
Questo è più autorevole, ma potrebbe essere incasinato dai tuoi programmi. Comunque sul mio, dice xterm
e su tty dice linux
, che penso sia l'acronimo di Linux Console.
$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 $TERM
ritorna xterm
anche 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
.
È 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/^.* //')
Su molti sistemi linux echo $TERM
return xterm
vedi 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 .
-o
elenco 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!
-p
di 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.
Usare pstree
ed awk
è il modo più semplice:
pstree -sA $$ | awk -F "---" '{ print $2 }'
pstree
of $$
(il processo effettivo).Gli pstree
argomenti:
-s
: mostra i genitori di un processo-A
: visualizza l'output in puro ASCII.Lo awk
strumento analizza un modello e un -F
argomento viene utilizzato per dividere i processi.
'{ print $2 }'
dice di awk
emettere solo il secondo modello di corrispondenza (in questo caso, il nome dell'emulatore di terminale).$2
? Nel mio caso, ciò che viene convogliato è in awk
realtà systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree
...
xfsettingsd
invece il terminale che sto usando.
pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
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 ps
o 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.
se stai usando bash, penso che questo comando ti aiuterà:
which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))
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
}
container
dopo la definizione.