Como detectar o número de terminais abertos pelo usuário

9

Estou usando o Ubuntu e posso alterar manualmente a bashcor do prompt do shell para verde usando

export PS1="\e[0;32m[\u@\h \W]\$ \e[m" 

No entanto, quero que a cor do prompt do shell seja alterada automaticamente sempre que abrir um novo terminal ou guia. Estou ciente de que o termo tty básico tem 16 cores e não há problema em girar as cores se houver mais de 16 terminais abertos. A solução também funcionará quando eu conectar Putty, tmuxou screen.

Minha idéia é escrever um script de shell e colocá-lo no .bashrcqual detecta a nova sessão do terminal que o usuário abriu e incrementa um contador global de \e[0;31m[para \e[0;47m[. Como detectar o número de terminais abertos pelo usuário?

manav mn
fonte

Respostas:

8

Se você realmente precisar obter o número de terminal aberto, faça uma contagem dos arquivos de sua propriedade /dev/pts(embora isso possa incluir os abertos por processos em segundo plano, não pelos emuladores gráficos de terminal). Como alternativa, conte o número de processos filhos do (s) seu (s) emulador (s) de terminal, conforme mostrado por Jacob na primeira linha de sua resposta.

Evite confiar na whosaída de e procurar gnome-pty-helperprocessos, pois eles não funcionam em gnome-terminalversões mais recentes.

Observe que hoje em dia praticamente todos os emuladores de terminais gráficos (incluindo massa de vidraceiro) e multiplexadores (tela, tmux) suportam 256 cores. Você pode receber avisos coloridos realmente agradáveis ​​se usar esta paleta.

Minha recomendação para uma solução muito simples é basear a cor no número da linha tty atual. Por exemplo, processe a saída do ttycomando para pegar apenas o número e derivar a cor disso. Um certo número de linha tty é dado apenas a um terminal de cada vez; você deve fechar o terminal primeiro antes que o mesmo número de linha seja reemitido pelo kernel. Isso, combinado com 256 cores, garante automaticamente que você não verá a mesma cor duas vezes em um determinado momento (e mesmo com 16 cores, a distribuição seria uniforme). Não é necessário manter um contador global e não é necessário contar terminais ou processos.

Egmont
fonte
1
Bela ideia com tty. Eu acho que nós / outros nos concentramos demais nessa "questão" e esqueci que pode haver outras soluções para toda a "necessidade" :) Eu até brincaria com a implementação do seletor de cores aleatório. Se houver 256 cores, a seleção de cores iguais / semelhantes não deve acontecer muito. No entanto, a configuração manual de cores para determinados números de pontos dará uma melhor personalização.
GreggD
@TedM. Sim, a pergunta foi formulada como uma pergunta XY, na linha de: "Desejo ter cores diferentes em cada terminal, então me diga: como posso contar o número de terminais?"
egmont 20/05
@TedM. Random também é uma boa ideia! (Uma propriedade de um mapeamento determinista é que depois sudoing o novo usuário pode facilmente configurar a mesma cor pronta Esta pode ou não o que o consulente originais quer ter..)
Egmont
1
O randomizador é bastante fácil: color="\e[38;5;"$(((RANDOM % 231 )+1))"m"(apenas 231 para rejeitar a escala de cinza), no entanto muitas dessas cores eram apenas tons diferentes e algumas são escuras, então podem ser quase invisíveis e eu acho que ninguém vai usar isso na vida real ...
GreggD
Não conhecemos a versão Ubuntu do solicitante. No 16.04, definitivamente não existe mais o gnome-pty-helper ( git.gnome.org/browse/vte/commit/?id=299c700 ). Não vou fazer o downgrade para verificar a hierarquia exata do processo nas versões mais antigas. Eu sei que costumava haver esse processo, mas não tenho muita certeza de como era a hierarquia pai-filho. A propósito, peguei a idéia de contagem de processos filhos da sua resposta original, então não entendo que "(também por você)", deixa pra lá.
egmont 20/05
5

Em uma situação de usuário único, se usarmos o exemplo de xterm, podemos simplesmente contar o número de pids de xterm; xtermcria um pid separado para cada janela.
gnome-terminalno entanto, executa um único pid, mas a boa notícia é que ele cria um processo filho para cada janela e / ou guia. podemos recuperar esses processos filhos pelo comando:

pgrep -P <pid_of_gnome-terminal>

No entanto, existem algumas complicações para lidar com:

  • Lendo sua pergunta, podemos assumir que, nesse caso , o usuário é realmente o proprietário da x-session . Geralmente, podemos simplesmente usar a $USERvariável-, mas isso pode não corresponder ao usuário atualmente conectado $DISPLAY.

  • Em uma situação multiusuário, os pids pertencentes ao (ou qual) aplicativo de terminal não pertencem necessariamente ao atual $DISPLAY. Precisamos separar apenas os pids e pids relevantes.

  • No Unity (15.10 ou inferior), se um segundo usuário efetuar login, um processo adicional será iniciado ( gnome-pty-helper), que aparecerá como um processo filho gnome-terminal, mas o processo (obviamente) não terá janela ou guia. No Mate , o processo existe de qualquer maneira.

Em resumo

Para contar o número de guias e / ou janelas de um aplicativo de terminal, precisamos:

  • Veja se executamos um aplicativo de terminal com vários pids ou um único pid em um $DISPLAY(x-session)
  • Nos processos em execução, separe apenas os pids relevantes, executando neste$DISPLAY
  • Se o aplicativo executar processos filhos para seu pid (para janelas / guias), veja se gnome-pty-helperé executado, para corrigir o número.

No entanto, isso pode muito bem ser guiado por script, para encontrar com segurança o número de janelas e / ou guias atualmente abertas.

O script

No script abaixo, o aplicativo de terminal de destino é usado como argumento . O script funciona em muitos terminais em que eu testei. Uma exceção está Tildaneste momento.

Um exemplo

  • Eu tenho dois usuários conectados, um (não o atual) com duas gnome-terminaljanelas, um (aquele na imagem) com três gnome-terminaljanelas e duas xtermjanelas.

insira a descrição da imagem aqui

O comando:

/path/to/get_terms.sh gnome-terminal

saídas:

3

enquanto

/path/to/get_terms.sh xterm

saídas:

2

O script

#!/bin/bash

terminal=$1

# get the user running the current x-session
username=$(who | grep $DISPLAY | head -1 | awk '{print $1}')
# get the pid of the terminal for the current user
userpid=$(pgrep -u $username $terminal)
# check what type the terminal is (multi pid/single pid)
npids="$(echo "$userpid" | wc -w)"
# in case of a single pid, count the children
if [ "$npids" -eq 1 ]; then
  # check if gnome-pty-helper runs (starts when multiple users are logged in)
  ptpid=$(pgrep gnome-pty-helpe)
  # get number of child- procs
  let "orig = $( pgrep -P $(pgrep -u $username $terminal) | wc -w )" 
  # if pty-helper runs, correct the number of child procs
  if [ -n "$ptpid" ] && [ -n "$userpid" ]; then
    let "n_terms = $orig-1"; else let "n_terms = $orig"
  fi
  # if no child procs run, n-terminals = n-counted pids (difference Mate <> Unity)
  if [ "$n_terms" -eq 0 ]; then echo $orig; else echo $n_terms; fi
# in case of multiple pids, count the pids
elif [ "$npids" -gt 1 ]; then echo $npids
fi

Usar

  • Copie o script em um arquivo vazio, salve-o como get_terms.sh, torne-o executável e execute-o pelo comando:

    /path/to/get_terms.sh <terminal_application>
Jacob Vlijm
fonte
Aqui sempre tenho um em gnome-pty-helperexecução, mesmo quando há apenas um usuário conectado (logo após a reinicialização) e quando abro qualquer quantidade de terminais, ele é executado em segundo lugar, o mesmo ajudante. Seu novo script parece estar funcionando para o mate-terminal (não foi possível causar essa coisa zero), mas com o xterm, quando eu apenas abri 1, ele mostra 0e começa a mostrar um bom número somente após o segundo e com o gnome-terminal sempre mostra um número a menos (saída 0quando apenas um é aberto).
GreggD
@TedM. Obrigado, essa é uma informação útil, corrigida agora.
Jacob Vlijm
Eu realmente admiro sua "paixão" :) ... mas ainda há um problema com o gnome-terminal. Um dá 1, dois dá 1, três dá 2, quatro dá 3, etc. Além disso, minha nova descoberta, o "Tilda" do MATE (aquele terminal "desconhecido" extra na minha resposta) também tem o mesmo problema que o gnome-terminal, mas com suas abas. O xterm e o mate-terminal parecem estar funcionando bem.
GreggD
@TedM. Obrigado por mencionar! Pergunta boba, mas você tem certeza de que usa o código mais recente? No Mate 15.10, todos os testes executam o trabalho sem exceção. Qual é a sua versão do Mate? No Unity, tudo já funcionou bem.
Jacob Vlijm
@TedM. Também no meu bonito 15.10 Mate, ele está lá por padrão. Apenas refiz os testes, perfeitamente! posso pedir-lhe amanhã para executar uma versão editada do script e postar a saída em algum lugar, para ver o que causa a exceção no seu caso?
Jacob Vlijm
1

Uma awkmaneira:

who | awk 'BEGIN{count=0}{ if(NR!=1){count++} }END{print count}'

Explicação:

No comando acima de 1 liner, awké usado para encontrar a contagem de terminais. Dentro do awkprograma, está apenas verificando o número de linhas retornadas por quem comanda - 1.

bisbilhoteiro
fonte
isso retorna 0 para mim, o que é claramente falso ...
Zanna
Este funciona muito bem para o meu mate-terminal & xterm, parece à prova de balas.
GreggD
Concisa: who | awk 'END{print NR - 1}', já que o que você quer é o número de linhas - 1.
Muru
0

A maneira simples também pode ser executada System Monitor(se for iniciado no Terminal, você deve escrever gnome-system-monitor) e, na guia "Processos", organize os processos em execução por Nome e depois conte o número de ocorrências Bashna lista (eles estarão todos juntos, se você organizar por nome, por isso é fácil contar).

Observe que você deve procurar Bashe não Gnome Terminalse deseja ver o número de terminais abertos por usuário. Depois de aberto, um terminal Gnome Terminaltambém aparecerá na lista de processos, mas permanecerá apenas um, mesmo que mais terminais sejam abertos. O botão "Visualizar" System Monitorpermite definir quais processos visualizar, por exemplo. Todos os processos / processos do usuário / ativo ...

NonStandardModel
fonte
Como o OP deseja usar o resultado para definir automaticamente as cores dos terminais, isso não parece ser uma opção realmente relevante.
Jacob Vlijm
Desculpe, vejo agora que ele quer usá-lo no script. Mas então seria ps -ef | Nome de usuário grep | grep bash | grep -v grep | wc -l não funciona?
NonStandardModel