sábado, 15 de septiembre de 2007

Como averiguar si un script está en una consola

En un mundo en el que las interfaces gráficas de usuario en general y los entornos de escritorio son algo omnipresente no deja de resultar muy curioso el hecho de que cada sistema operativo ha optado por métodos muy diferentes a la hora de ejecutar sus scripts diseñados para la consola desde el entorno de escritorio. Es decir, cuando hacemos doble click sobre el icono correspondiente al script.

Windows y OS/2, por ejemplo, abren una consola cada vez que se ejecuta un fichero bat o cmd (en el caso de OS/2, los ficheros cmd pueden ser programas escritos en REXX o incluso pueden ser programas escritos en Python o Perl no simples ficheros de proceso por lotes). Windows no ofrece muchas facilidades para ocultar la ventana de la consola. OS/2 ofrece bastantes alternativas para ocultarlo si es necesario y modos de ejecutar pequeños diálogos gráficos cuando la consola está oculta.

BeOS nunca abre una consola cuando se ejecuta un script. Tradicionalmente en BeOS todo aquel script que estuviese pensado para el escritorio utilizaba el comando alert de BeOS que permitía mostrar al usuario pequeños diálogos con sus correspondientes mensajes y botones.

Con los entornos de escritorio usuales en Linux (Gnome y KDE, aunque haya docenas más con muy buenas ideas, por cierto) lo habitual es que el comportamiento fuese el mismo que en BeOS. Actualmente lo usual en Gnome (por ejemplo) es que cuando un usuario hace doble click sobre un script aparezca un diálogo que le pide confirmar si quiere ejecutarlo, ejecutarlo abriendo una terminal, editarlo o cancelar la apertura.

Ocasionalmente puede ser interesante que un script averigüe si se está ejecutando en una consola o no y para ello el comando tty nos puede servir muy bien puesto que la salida de ese comando nos indica el número de terminal en el primer caso o nos dice "not a tty" en caso contrario. Así podemos hacer de forma sencilla lo siguiente:
  #!/bin/bash

if [ "$(tty)" = "not a tty" ]; then
echo "No es una terminal"
else
echo "Sí es una terminal"
fi

exit 0

Lo que en REXX quedaría como:
  /*bin/true;exec rexx "$0" "$@";exit # REXX */

'tty | rxqueue'
parse pull tty

if tty = 'not a tty' then
say 'No es una terminal'
else
say 'Sí es una terminal'

exit 0

El código de retorno del comando nos da la misma información:
  #!/bin/bash

tty=$(tty)

if [ $? = 1 ]; then
echo "No es una terminal"
else
echo "Sí es una terminal" # $? es igual a 0
fi

exit 0

En REXX:
  /*bin/true;exec rexx "$0" "$@";exit # REXX */

'tty > /dev/null'

if rc = 1 then
say 'No es una terminal'
else
say 'Sí es una terminal' /* rc es igual a 0 */

exit 0

Esto nos permite, por ejemplo, forzar la ejecución del programa en una terminal:
  #!/bin/sh
# Ejemplo para BeOS
# Cada entorno de escritorio tiene su propio ejecutable
# para la terminal.
myself=$0
if [ "$(tty)" = "not a tty" ]; then
Terminal -t "Ejemplo" /bin/sh -c "$myself"
else
echo 'Sí una terminal'
fi

Con kdialog, zenity o xdialog podemos hacer pequeños scripts interactivos como en el siguiente caso:
  /*bin/true;exec rexx "$0" "$@";exit # REXX */

current_date = date('S')

'tty > /dev/null'

gui = rc

if gui = 1 then do
'zenity --title "Escoja su fecha de nacimiento"' ||,
' --calendar --date-format %Y%m%d | rxqueue'
pull birthday_date
if rc = 1 then
exit 1 /* Pulsado el botón "Cancelar" */
end
else do
say 'Introduzca su fecha de cumpleaños (19770223):'
parse pull birthday_date
end

age_in_days = say date('B', current_date, 'S'),
- date('B', birthday_date, 'S')

if gui = 1 then do
'zenity --warning --text "Su edad en días es:',
age_in_days '"'
else do
say 'Su edad en días es' age_in_days

exit 0

No hay comentarios: