A especificação POSIX realmente protege suas apostas no que diz respeito ao Terminal de Controle e define assim:
- Terminal de controle
- A questão sobre qual dos possíveis arquivos especiais referentes ao terminal é abordada no POSIX.1. O nome do caminho
/dev/tty
é um sinônimo para o terminal de controle associado a um processo.
Está na lista de definições - e é tudo o que existe. Mas na Interface Geral do Terminal , mais um pouco é dito:
Um terminal pode pertencer a um processo como seu terminal de controle. Cada processo de uma sessão que possui um terminal de controle possui o mesmo terminal de controle. Um terminal pode ser o terminal de controle por no máximo uma sessão. O terminal de controle de uma sessão é alocado pelo líder da sessão de uma maneira definida pela implementação. Se um líder de sessão não tiver um terminal de controle e abrir um arquivo de dispositivo de terminal que ainda não esteja associado a uma sessão sem usar a opção O_NOCTTY (consulte open ()), será definido como implementação se o terminal se tornará o terminal de controle da sessão líder.
O terminal de controle é herdado por um processo filho durante uma chamada de função fork (). Um processo renuncia ao seu terminal de controle quando cria uma nova sessão com osetsid()
função; outros processos restantes na sessão antiga que possuíam esse terminal como seu terminal de controle continuam a ter. Após o fechamento do último descritor de arquivo no sistema (se está ou não na sessão atual) associado ao terminal de controle, não é especificado se todos os processos que tinham esse terminal como terminal de controle deixam de ter qualquer terminal de controle. Não é especificado se e como um líder de sessão pode recuperar um terminal de controle depois que o terminal de controle foi abandonado dessa maneira. Um processo não renuncia ao seu terminal de controle simplesmente fechando todos os descritores de arquivo associados ao terminal de controle se outros processos continuarem a abri-lo.
Ainda há muita coisa não especificada - e honestamente acho que faz sentido. Embora o terminal seja uma interface principal do usuário, em alguns casos também existem todos os tipos de outras coisas - como hardware real ou até mesmo um tipo de impressora - mas em muitos casos praticamente não é praticamente nada - como um xterm
que é apenas um emulador . É difícil ser específico lá - e eu não acho que seria muito do interesse do Unix, porque os terminais fazem muito mais do que o Unix.
De qualquer forma, o POSIX também é bastante duvidoso sobre como ps
deve se comportar no que diz respeito ao ctty.
Aqui está o -a
interruptor:
- Escreva informações para todos os processos associados aos terminais. As implementações podem omitir os líderes de sessão desta lista.
Ótimo. Os líderes da sessão podem ser omitidos. Isso não é muito útil.
E -t
:
- Escreva informações para processos associados aos terminais fornecidos na lista de termos. O aplicativo deve garantir que a lista de termos seja um argumento único na forma de uma lista
<blank>
ou separada por vírgula. Os identificadores de terminal devem ser fornecidos em um formato definido pela implementação .
... que é outra decepção. Mas continua dizendo isso sobre os sistemas XSI:
- Nos sistemas compatíveis com XSI, eles devem ser fornecidos em uma de duas formas: o nome do arquivo do dispositivo (por exemplo
tty04
) ou, se o nome do arquivo do dispositivo começar tty
, apenas o identificador após os caracteres tty
(por exemplo 04
) .
Isso é um pouco melhor, mas não é um caminho. Também em sistemas XSI, há o -d
switch:
- Escreva informações para todos os processos, exceto os líderes da sessão.
... o que é pelo menos claro. Você pode especificar a -o
opção utput também com a tty
string format, mas, como você observou, o formato de saída é definido pela implementação. Ainda assim, acho que é o melhor possível. Eu acho que - com muito trabalho - as opções acima, combinadas com outros utilitários, podem lhe proporcionar uma estimativa muito boa. Para ser sincero, porém, não sei quando / como isso acontece para você - e não pude imaginar uma situação em que isso aconteceria. Mas acho que provavelmente se adicionarmos fuser
e find
podemos verificar o caminho.
exec 2<>/dev/null
ctty=$(sh -c 'ps -p "$$" -o tty=' <&2)
sid=$(sh -c 'ps -Ao pid= -o tty=|
grep '"$ctty$"' |
grep -Fv "$(ps -do pid=)"' <&2)
find / -type c -name "*${ctty##*/}*" \
-exec fuser -uv {} \; 2>&1 |
grep ".*$ctty.*${sid%%"$ctty"*}"
O /dev/null
material era apenas para mostrar que poderia funcionar quando nenhum dos subconjuntos de pesquisa tinha 0,1,2 conectado ao ctty. Enfim, isso imprime:
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
Agora, o texto acima mostra o caminho completo na minha máquina, e imagino que seria para a maioria das pessoas na maioria dos casos. Eu também posso imaginar que poderia falhar. São apenas heurísticas grosseiras.
Provavelmente, isso pode falhar por muitas outras razões, mas se você estiver em um sistema que permita ao líder da sessão renunciar a todos os descritores ao ctty e ainda assim permanecer como sid, conforme a especificação permitir, isso definitivamente não ajudará. Dito isto, acho que isso pode obter uma estimativa muito boa na maioria dos casos.
Claro que a coisa mais fácil de fazer se você tiver algum descritor conectado ao seu ctty é apenas ...
tty <&2
...ou similar.
ps
solução cobre a maioria dos sistemas (ewho
não ajuda mais do queps
), possivelmente com um pouco mais de código para lidar com o identificador sozinho (como "04"). Fiquei me perguntando se havia uma solução ainda mais portátil.