¿Cómo se puede obtener el nombre real del terminal de control (si hay uno, sino un error) como nombre de ruta?
Por "nombre real", quiero decir que no /dev/tty
, que no puede ser utilizado por otros procesos arbitrarios para referirse al mismo terminal. Prefiero la respuesta como un simple código de shell (como el ejemplo a continuación) si es posible, de lo contrario como una función C.
Tenga en cuenta que esto debe funcionar incluso si la entrada estándar se redirige, de modo que la tty
utilidad no se puede usar: not a tty
en ese caso, se obtendría un error, ya que tty
solo imprime el nombre del archivo del terminal conectado a la entrada estándar.
Bajo Linux, uno puede usar:
echo "/dev/`ps -p $$ -o tty | tail -n 1`"
pero esto no es portátil, ya que según POSIX, el formato del nombre del terminal no está especificado .
En cuanto a las funciones de C, ctermid (NULL)
devuelve /dev/tty
, que aquí es inútil.
Nota: de acuerdo con la zsh
documentación, uno debería poder hacer
zsh -c 'echo $TTY'
pero esto actualmente (versión 5.0.7) falla cuando se redirigen tanto la entrada estándar como la salida estándar:
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty
fuente
ps
solución cubre la mayoría de los sistemas (ywho
no ayuda más queps
), posiblemente con un poco más de código para manejar solo el identificador (como "04"). Me preguntaba si habría una solución aún más portátil.man xterm
:-Sccn
Esta opción permitexterm
ser utilizada como un canal de E / S para un programa existente ... El valor de la opción es unas pocas letras del nombre de una pty para usar en modo esclavo, más el número fd heredado. Si la opción contiene un carácter "/", delimita el nombre pty del fd.ps
desde busybox (que es utilizada por Android, por cierto), incluso bajo GNU / Linux. ¿Qué quiere decir con "xterm
puede manejar eso04
"?busybox
no es compatible con POSIX.toybox
, sin embargo, lo hace muy bien.Respuestas:
El "terminal de control" alias. ctty, se distingue de " la terminal con la que interactúa un proceso".
La forma estándar de obtener el camino de ctty es ctermid (3). Al llamar a esto, en freebsd desde la versión 10, se busca una ruta real [1], mientras que las implementaciones anteriores de freebsd y glibc [2] devuelven incondicionalmente "/ dev / tty"].
ps (1) del paquete linux procps 3.2.8, lea la entrada numérica en / proc / * / stat [3], y luego deduzca el nombre de ruta parcialmente adivinando [4, 5] debido a la falta de soporte del sistema [6] .
Sin embargo, si no estamos estrictamente interesados en el ctty pero cualquier terminal asociada con stdio, tty (1) imprime la ruta del terminal conectada a stdin, que es idéntica a
ttyname(fileno(stdin))
in c, y una alternativa esreadlink /proc/self/fd/0
.Pensamiento menos importante con respecto al comportamiento incondicional "/ dev / tty": las especificaciones simplemente dicen que la cadena devuelta por ctermid "cuando se usa como nombre de ruta, se refiere al terminal de control actual", en lugar de algo sencillo "es el nombre de ruta de la corriente terminal de control ". Podría interpretarse como que "/ dev / tty" no es el terminal de control, sino que solo se refiere al terminal de control si el mismo proceso lo abre (3). Por lo tanto, no violar la regla "un terminal puede ser insignificante para, como máximo, una sesión" [7].
Otra consecuencia es que cuando no tengo ningún terminal de control, ctermid no falla, tal falla está permitida por las especificaciones [8], así que solo puedo darme cuenta de mi falta de confianza hasta que falle una apertura posterior (3), lo cual está bien ya que las especificaciones también dicen que llamar a open (3) no está garantizado para tener éxito.
fuente
ps
solución que di en mi pregunta, ya que no todos los sistemas operativos tienen un/proc
sistema de archivos. Tenga en cuenta queps
usa un enlace de lectura/proc/self/fd/2
(que funciona incluso si el error estándar se redirige).tty
.stderr
es probablemente el mejor porque se especifica que debe estar abierto r / w. Por lo tantotty <&2
.ctermid()
siempre regrese"/dev/tty"
. Ese nombre siempre se refiere al terminal de control del proceso que accede a él , que varía según la sesión. El terminal es específico de la sesión, pero el nombre por el que se accede no necesita serlo.La especificación POSIX realmente cubre sus apuestas en lo que respecta al Terminal de Control , y que define así:
/dev/tty
es sinónimo del terminal de control asociado con un proceso.Eso está en la lista de Definiciones, y eso es todo lo que hay. Pero en General Terminal Interface , se dice algo más:
Un terminal puede pertenecer a un proceso como su terminal de control. Cada proceso de una sesión que tiene un terminal de control tiene el mismo terminal de control. Un terminal puede ser el terminal de control para, como máximo, una sesión. El líder de sesión asigna el terminal de control para una sesión de una manera definida por la implementación. Si un líder de sesión no tiene terminal de control y abre un archivo de dispositivo de terminal que no está asociado con una sesión sin usar la opción O_NOCTTY (ver open ()), se define la implementación si el terminal se convierte en el terminal de control de la sesión líder.
El terminal de control es heredado por un proceso hijo durante una llamada a la función fork (). Un proceso renuncia a su terminal de control cuando crea una nueva sesión con el
setsid()
función; otros procesos restantes en la sesión anterior que tenía este terminal como su terminal de control continúan teniendo. Al cerrar el último descriptor de archivo en el sistema (esté o no en la sesión actual) asociado con el terminal de control, no se especifica si todos los procesos que tenían ese terminal como terminal de control dejan de tener algún terminal de control. No se especifica si y cómo un líder de sesión puede volver a adquirir un terminal de control después de que el terminal de control haya sido cedido de esta manera. Un proceso no renuncia a su terminal de control simplemente cerrando todos sus descriptores de archivos asociados con el terminal de control si otros procesos continúan abriéndolo.Quedan muchas cosas sin especificar , y sinceramente, creo que tiene sentido. Si bien el terminal es una interfaz de usuario clave, en algunos casos también es todo tipo de otras cosas, como hardware real o incluso una especie de impresora, pero en muchos casos prácticamente no es nada, como
xterm
un emulador . Es difícil ser específico allí, y no creo que sea de gran interés para Unix de todos modos, porque los terminales hacen mucho más que Unix.De todos modos, POSIX también es bastante dudoso sobre cómo
ps
debe comportarse en lo que respecta a la comunidad.Ahí está el
-a
interruptor:Excelente. Los líderes de sesión pueden ser omitidos. Eso no es muy útil.
Y
-t
:<blank>
lista separada por comas. Los identificadores de terminal se darán en un formato definido por la implementación .... que es otra decepción. Pero continúa diciendo esto sobre los sistemas XSI:
tty04
) o, si el nombre de archivo del dispositivo comienza contty
, solo el identificador que sigue a los caracterestty
(por ejemplo04
) .Eso es un poco mejor, pero no es un camino. También en los sistemas XSI existe el
-d
interruptor:... que al menos está claro. Puede especificar el
-o
modificador de rendimiento también con latty
cadena de formato, pero, como ha notado, su formato de salida está definido por la implementación. Aún así, creo que es tan bueno como se pone. Creo que, con mucho trabajo, los interruptores anteriores en combinación con algunas otras utilidades pueden darle un buen estadio. Sin embargo, para ser sincero, no sé cuándo / cómo se rompe para usted, y no he podido imaginar una situación en la que lo haría. Pero, creo que probablemente si agregamosfuser
yfind
podemos verificar la ruta.El
/dev/null
material era solo para mostrar que podía funcionar cuando ninguna de las subcapas de búsqueda tenía ninguna conexión de 0,1,2 conectada a la comunidad. De todos modos, eso imprime:Ahora lo anterior obtiene el camino completo en mi máquina, e imagino que lo haría para la mayoría de las personas en la mayoría de los casos. También me imagino que podría fallar. Es solo una heurística aproximada.
Probablemente, esto podría fallar por muchas otras razones, pero si está en un sistema que permite que el líder de la sesión renuncie a todos los descriptores y, sin embargo, siga siendo el sid, según lo permitan las especificaciones, entonces esto definitivamente no va a ayudar. Dicho esto, creo que esto puede obtener una estimación bastante buena en la mayoría de los casos.
Por supuesto, el más fácil de lo que debe hacer si tiene algún descriptores conectados a su CTTY es sólo ...
...o similar.
fuente