Come posso verificare se la mia shell è in esecuzione in un terminale?


22

Voglio eseguire alcune azioni solo se la mia shell è "connessa" a un terminale, vale a dire solo se il mio input standard proviene dall'input di un terminale e il mio output standard (e l'errore standard? Forse non importa) viene stampato / echo su un terminale.

Come posso farlo, senza fare affidamento direttamente su specifiche GNU / Linux (come /proc/self)?


Risposte:


33

isattyè una funzione per verificarlo e il -tflag del testcomando lo rende accessibile da uno script shell:

-t file_descriptor

Vero se il numero del descrittore di file file_descriptor è aperto ed è associato a un terminale. Falso se file_descriptor non è un numero descrittore di file valido o se il numero descrittore di file file_descriptor non è aperto o se è aperto ma non è associato a un terminale.

Puoi verificare se FD 0 (input standard) è un TTY con:

test -t 0

Puoi fare lo stesso per gli FD 1 e 2 per controllare i flussi di output e di errore, o tutti loro:

test -t 0 -a -t 1 -a -t 2

Il comando restituisce 0 (esito positivo) se i descrittori sono collegati a un terminale, altrimenti è falso.

testè disponibile anche come [comando per un "test di parentesi":

 if [ -t 0 ] ; then ...

è un modo idiomatico di scrivere questo condizionale.


8

Immagino che questo sia un duplicato, ma non riesco a trovarlo. Uso

[ -t 0 ]

e

[ -t 1 ]

per verificare rispettivamente se l'ingresso e l'uscita standard sono collegati a un terminale. man testha i dettagli.


7

Solo una nota in più sulle ottime risposte che sono già state fornite. Si noti che [ -t 0 ]verifica che il descrittore di file 0 sia aperto in un file che è un file di dispositivo con una disciplina tty line (in genere, ciò viene fatto controllando che un innocuo termio (s) ioctl () abbia successo).

Inoltre, ciò non significa necessariamente che ci sia un emulatore di terminale o terminale (con un vero utente che digita su una tastiera) dall'altra parte (anche se nella stragrande maggioranza dei casi e probabilmente la maggior parte di quelli a cui tieni, è abbastanza buono un approssimazione).

I dispositivi tty e pty possono anche essere utilizzati per il trasferimento di dati o come meccanismo di comunicazione tra processi.

Ad esempio, si potrebbe fare:

(stty raw -echo; myscript) < /dev/ttyS0

Per alimentare ciò che viene ricevuto tramite RS232 a myscript.

echo test | ssh -tt host myscript

lo myscriptstdin sarebbe un dispositivo pty (con sshddall'altra parte, ed eventualmente (attraverso la connessione ssh) non un terminale, ma un tubo alimentato da echo)

Per verificare ulteriormente che ci sia un terminale all'altra estremità di quella linea o pty RS232, puoi anche verificare che una $TERMvariabile sia impostata e non vuota ( [ -n "$TERM" ]) e inviare una sequenza di escape del rapporto sullo stato del dispositivo su quella fd e verificare che tu riceva una risposta (oltre a [ -t 0 ]e [ -n "$TERM" ]).

printf >&0 '\e[5n'

Viene risposto con a \e[0ndalla maggior parte dei terminali.

Ora ci sono diversi problemi con questo, quindi non consiglierei di farlo tranne nel caso in cui desideri verificarlo perché vuoi eseguire un'applicazione TUI visiva (nel qual caso, sarebbe meglio usare librerie come ncurses, e invece del DSR, preferiresti inviare una sequenza di escape di identificazione del dispositivo per interrogare il tipo di terminale in modo più preciso che via $TERM):

  • Per fortuna, nella maggior parte dei casi in cui stdin non è un terminale, sarà stato aperto in modalità di sola lettura, il che causerebbe un printferrore, ma nel caso in cui stdin sia un dispositivo tty aperto in modalità lettura + scrittura, ciò avrà l'effetto collaterale di inviare quella sequenza all'altro capo. Ad esempio nel nostro esempio di ssh sopra, che effettivamente invierà la sequenza a un terminale (ma la risposta non arriverà su stdin)
  • È difficile leggere la risposta in modo affidabile e portabile. Dovresti cambiare temporaneamente la disciplina della linea tty e leggere un byte alla volta. Dovrai anche decidere un timeout entro il quale se la risposta non viene visualizzata, ti arrendi e decidi che non esiste un terminale. Se si desidera prendere in considerazione le persone che effettuano la chiamata tramite connessioni satellitari, ciò significa un lungo timeout.
  • Leggere da un terminale in background sospenderebbe il tuo script con un segnale SIGTTIN.
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.