Como verificar qual emulador de terminal está sendo usado atualmente?


15

Eu tenho o gnome-terminal e o Guake instalados. Desejo fornecer diferentes mensagens de inicialização a serem exibidas nesses emuladores de terminal assim que elas forem iniciadas. Que código devo escrever em .bashrc para que isso seja alcançado?

Respostas:


10

Esta função deve fazer o trabalho:

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

Boa resposta! Não se esqueça de realmente chamar a função containerapós a definição.
rosch 31/10/12

Eu esperava que isso fosse óbvio, mas você está certo, resposta atualizada em conformidade.
Jlliagre 31/10/12

@ jlliagre Eu tentei o código. Funciona sem problemas no terminal gnome, mas tem um problema no Guake. Não dá saída. Em vez disso, meio que congela como se estivesse em um impasse. Eu tenho que Ctrl + C para usá-lo. Realmente não entendi o código, então não sei onde está dando errado.
VedVals

Código fixo. Eu perdi o guake é executado por python e tinha um bug que impedia a função de sair. Obrigado pelo feedback.
Jlliagre

Desculpe cara, ainda não está funcionando direito. Dá erro bash: [: too many arguments. Obtive o bash v4.2.24, o python v2.7.3, se ajudar.
VedVals #

10

Tente o seguinte:

echo $TERM

Isso é mais autoritário, mas pode ser uma bagunça nos seus programas. No entanto, no meu, ele diz xterme no ttys linux, o que eu acho que significa Linux Console.


2
$TERMé uma variável que se refere à especificação relatada pelo emulador de terminal que você está usando, e não ao próprio emulador. Por exemplo, no meu sistema, echo $TERMretorna xtermmesmo que eu esteja executando o lxterminal. O que está acontecendo é o auto-relatório final de conformidade xterm. O lxterminal não é totalmente compatível com o xterm, portanto, você deve prestar atenção. Os arquivos de especificação geralmente estão localizados em /usr/share/terminfo.
stazher

7

Você pode obter o nome do emulador de terminal, preenchendo o nome do processo dos pais. Portanto, ele funciona com qualquer emulador de terminal.

No bash, zsh, etc .:

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

Com casca de peixe:

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

Observe, no entanto, que isso capturará argumentos do programa quando o emulador de terminal for iniciado com eles.
Robobenklein

Isso funciona se eu estiver conectado usando SSH?
user3731622

@ user3731622 não vai! Você terá que encaminhar a partir do cliente.
Enrico

2

Em muitos sistema linux echo $TERMretorno xtermver post stazher acima.

Para obter o terminal real em uso, faça o seguinte:

1: Feche todas as instâncias do terminal em execução no momento.

2: Abra um novo terminal usando seu método usual.

3: Digite o comando da seguinte maneira:

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

4: O retorno deve ser algo como:

lxterminal --geometry=135x20

Aqui está o detalhamento:

Então: psé "status do processo"

A opção ps -oé Exibir informações associadas à lista de palavras-chave especificadas por espaço ou vírgula. Parece complicado, mas não é realmente. (espaço ou vírgula) separado (lista de palavras-chave) especificado.

Portanto, (lista de palavras-chave) é 'cmd='apenas uma palavra-chave na lista. Então, apenas pedindo para exibir o comando para abrir o terminal.

A opção ps -pé "por identificação do processo" Uau, essa é uma opção muito boa para ps. O problema é que você deve passar para ps esse ID do processo. Então, como obter a identificação do processo? Desembrulhamos a expressão $(ps -o 'ppid=' -p $$)

Aqui devemos começar a pensar um pouco mais fundo. Eu gostaria de ter inventado essa linha única do bash, mas não o fiz. Acho que roubei de https://wiki.archlinux.org/ em algum lugar, não consegui encontrar novamente. Esses caras são incríveis, mas muitas vezes não consigo entender o que eles dizem para fazer até depois de muito estudo. O que podemos fazer é entender agora, porque vou explicar.

então sabemos que $é operador de expansão no bash. Eu gosto de pensar "desembrulhar". Assim, $(foo -opt bar)desembrulhará ou expandirá "foo -opt bar". Mas no bash, a chave redonda única (...)abre o subshell.

Então, $(foo -opt bar)expande "foo -opt bar" como executado no shell da filha . Muito estranho e difícil de entender.

OK, agora estamos executando o comando quase idêntico novamente, ps -o 'ppid=' -p $$mas desta vez ps, status do processo, mostra o que ele pode ver na instância do shell filha .

-olista de palavras-chave, apenas uma palavra-chave como antes, mas ppid=isso está solicitando diretamente a identificação do processo do shell pai !! DENTRO DA CASCA DA FILHA! Muito esperto, sim? Estou tão empolgado quando consigo entender isso!

-pnovamente, "por identificação do processo" e em bash $$é a identificação do processo.

Se você chamar ps -o 'ppid=' -p $$, ou qualquer outro comando que solicite $$diretamente do primeiro shell, ele pode dizer pid = 1, ou o pid do xWindow, ou do seu programa de desktop, ou talvez você tenha um pid real do shell. Se você perguntar muitas vezes, talvez obtenha respostas diferentes a cada vez!

Mas, se você invocar uma filha e perguntar "quem é seu pai", ela lhe dirá! Muito esperto. Eu gostaria de poder ser tão gênio para inventar esse método.


OK, portanto, a AU não permitirá a decomposição adequada em um post. Desculpe, não estou disposto a lutar com o sistema de blogs e fazer várias postagens. Talvez você possa ter uma ideia.
stazher

Sua outra resposta parece ser um comentário sofisticado e informativo sobre essa resposta, e não uma resposta à pergunta ... Seria ótimo se você pudesse combinar suas duas respostas em uma e excluir uma delas, e adicionar a ela para que ela responde totalmente à pergunta. Use ---- para desenhar uma linha no meio? Há um botão também.
Zanna 01/01

Acho que respondi à pergunta do OP exatamente e com detalhes. Você pulou em mim antes que eu tivesse a chance de entender o sistema de edição de blogs e terminar. Traga os votos negativos, estou acostumado.
stazher

11
Eu não acho que eu saltei em você, eu estava apenas fazendo revisão ... obrigado por fazer o seu post mais completo
Zanna

Obrigado pela sua resposta. Sinto muito, talvez eu pulei em você. Peço desculpas muito.
stazher

1

Usando pstreee awké a maneira mais fácil:

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

Explicando

  1. Exiba uma árvore de processos com pstreede $$(o processo atual).
  2. Os pstreeargumentos:

    • -s: exibe os pais de um processo
    • -A: exibe a saída em ASCII puro.
  3. A awkferramenta varre um padrão e -Fargumento é usado para dividir os processos.

  4. Finalmente, '{ print $2 }'diz para awkenviar apenas o segundo padrão de correspondência (neste caso, o nome do emulador de terminal).

Você tem certeza $2? No meu caso, o que é canalizado em awké realmente systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis

@EnricoMariaDeAngelis Ya. Obrigado pela sua observação. No meu caso, o emulador de terminal inicializa diretamente no serviço systemd. Verifico novamente o código e o edito com uma correção.
silvadev

Isso não funciona quando eu uso um atalho de teclado para iniciar o emulador. No XFCE, eu recebo em xfsettingsdvez do terminal que estou usando.
Michael Hoffmann

Funciona melhor se você começar do final:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff

0

Você está correto, eu só respondi a pergunta principal, não a pergunta no corpo. Então aqui está, e o tio de Bob.

Não sei ao certo o motivo da troca de caso, em uma resposta mostrada acima. Essa troca de gabinete não é necessária. Meu script ~ / .bashrc é na verdade apenas uma linha simples, todos os comandos echo são apenas para diversão. Como explicar...

Qualquer termo ao iniciar lê ~ / .bashrc e executa os comandos que ele verá em .bashrc. Portanto, não importa qual termo seja chamado, ele lerá .bashrc e executará os comandos; portanto, apenas a estrutura necessária no .bashrc seria modificar o comportamento ou excluir um termo ou outro. O comportamento desejado é que cada termo execute o mesmo comando, portanto, a troca de maiúsculas e minúsculas não é necessária. O próprio Terminal lhe dirá como ele foi chamado, então não há necessidade de se diferenciar.

Nota (1) Não testei o guake, mas funciona para todos os outros mencionados na primeira resposta por jlliagre.

Nota (2) Devido à formatação na marcação para wiki, você não pode recortar e colar como mostrado. Você deve excluir cada backtick , inclusive para excluir os caracteres de sublinhado, e adicionar backtick real, sem espaço antes psou depois do -p $$).

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

Isso foi muito divertido. Eu adicionei isso ao meu próprio ~ / .bashrc.


por Nota (1), testado em Tilda, funciona bem. O Guake é semelhante ao Tilda, mas é escrito em python, portanto, ainda não sabemos sobre o Guake.
stazher

0

se você estiver usando o bash, acho que este comando irá ajudá-lo:

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


0

Se você estava usando o ZSH, existe uma solução melhor (mais rápida), que usa apenas os componentes internos do ZSH e manipula /proc/$pid/{stat,cmdline}diretamente.

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
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.