3.6. Uso de comandos y aplicaciones

Con objeto de alcanzar una mayor homogeneización entre los sistemas, el estándar POSIX recoge una lista de comandos que deben ser implementados en cualquier sistema, clasificándolos según sean ordenes internas del shell (built-in) o aplicaciones externas.

3.6.1. Comandos internos

Los comandos internos corresponden a órdenes interpretadas por el propio shell (luego no existe ningún fichero ejecutable asociado al comando). Se distinguen dos tipos de comandos internos:

  • Especiales: un error producido al ejecutar este comando da lugar a que el shell termine. Por consiguiente, el script termina con un error y un valor de retorno mayor de cero (vea el apartado 2.8.2 del estándar para saber el valor de retorno).

  • Regulares: el shell no tiene que terminar cuando se produce un error en estos comandos.

A continuación se recogen los comandos internos especiales definidos en el estándar.

break, continue, export, return, unset, .

Se han descrito anteriormente.

:

Comando nulo. Se suele utilizar en estructuras de control que requieren un comando para ser sintácticamente correctas, pero no se quiere hacer nada.

eval

Permite crear comandos a partir de sus argumentos (ver más adelante)

exec

Ejecuta comandos (sustituyendo al shell actual) y abre, cierra y copia descriptores de fichero

exit

Provoca que el shell termine (ver más adelante)

readonly

Permite hacer que una variable sea de sólo lectura (no admite asignaciones)

set

Establece opciones del proceso shell actual y modifica los parámetros posicionales.

shift

Elimina el número indicado de parámetros posicionales empezando desde el 1, desplazando el resto de parámetros a posiciones inferiores.

times

Muestra los tiempos de procesamiento del shell y sus procesos hijos.

trap

Permite atrapar o ignorar señales del sistema.

Puede obtener más información en el estándar.

Como comandos internos regulares, el estándar define los siguientes:

Básicos regulares

bg, cd, false, fg, jobs, kill, pwd, read, true, wait

Para profundizar regulares

alias, command, fc, getopts, newgrp, umask, unalias

Consulte el estándar para más información.

Entre dichos comandos (especiales y regulares), por su utilidad en los shell-scripts deben destacarse: exit, read y eval.

3.6.1.1. Salida del proceso shell actual, exit

La sintaxis de este comando es:

exit [ n ]

exit provoca la eliminación inmediata del proceso correspondiente al shell que está leyendo el script. El parámetro opcional es un número entero que corresponde al valor devuelto por el script. Si no se indica ningún parámetro, el valor devuelto por el script será el del último comando ejecutado.

TAREAS

  1. Abra una consola de comandos. Mediante el comando su abra una sesión con el superusuario. Al abrir la sesión con root, se ha creado un nuevo proceso en memoria correspondiente al shell encargado del intérprete de comando en la sesión del root. Use el comando ps ax para localizar dicho proceso.

  2. Ejecute el comando exit, volviendo al usuario normal. Esto habrá provocado la eliminación del proceso shell encargado de la línea de comandos como en la que trabajaba root. Ejecute de nuevo ps ax comprobando cómo dicho proceso ha desaparecido

  3. Mire el contenido del script script_exit.sh, que deberá contener lo siguiente:

    script_exit.sh
    echo Dentro del script
    exit 3
    echo Fuera del script
    
  4. Compruebe que dispone del permiso de ejecución general. Vuelva a usar el comando su para abrir una  sesión con el superusuario. Desde dicha sesión ejecute el comando anterior mediante las siguientes invocaciones:

    /bin/bash   script_exit.sh
    ./script_exit.sh
    

    Ambas invocaciones provocan la creación de un subshell (un nuevo proceso shell) encargado de leer el script. Por ello, cuando se llega al comando exit se para la interpretación del script y dicho subshell es eliminado, volviendo al proceso shell padre correspondiente a la línea de comandos desde la que estábamos trabajando.

    Ejecute el comando echo $? para comprobar cómo el script ha devuelto el código de error 3.

  5. Ejecute los siguientes comandos:

    • script_exit.sh && echo Hola, comprobando que no se imprime la cadena Hola debido a que el script devuelve un código de error (>0).

    • script_exit.sh || echo Hola, comprobando que ahora sí se imprime.

    • Edite el script para que el comando exit devuelva cero (exit 0), y vuelva a invocar el comando script_exit.sh && echo Hola, comprobando que ahora también se imprime la cadena Hola.

  6. Vuelva a invocar el script pero ahora mediante:

    .  script_exit.sh
    

    Verá cómo la sesión del root se cierra automáticamente y vuelve a la sesión del usuario normal. Esto se debe a que en este caso no se está creando ningún nuevo subshell, sino que el propio shell de la línea de comandos del usuario root es el encargado de interpretar el script. Al llegar al comando exit, éste provoca la eliminación del proceso shell que lee el script, esto es, la eliminación de la sesión del usuario root.

    Ejecute el comando echo $? para comprobar cómo el script ha devuelto el código de error 0 (sin error) correctamente.

  7. Ejecute y analice el funcionamiento de los siguientes comandos:

    sh -c "exit 0" &&
      echo Sin error1A ||
      echo Con error1B
    
    sh -c "exit 1" &&
      echo Sin error2A ||
      echo Con error2B
    

3.6.1.2. Entrada estándar a un shell-script, read

El comando read lee una línea de la entrada estándar (teclado) y la guarda en variables. Solo funciona en shell interactivos (leyendo la entrada del teclado), de lo contrario no hace nada. En su forma más básica, presenta la siguiente sintaxis:

read VAR1 [ VAR2 … ]

Este comando espera a que el usuario introduzca una línea de texto incluyendo espacios (la entrada termina cuando el usuario pulsa la tecla intro; la pulsación intro no forma parte del valor asignado a la cadena). Esta línea se divide en campos (según la variable IFS). Tras ello, el comando define las variables dadas como argumentos, inicializándolas con los campos obtenidos en la división. Si hay más campos que variables, los campos restantes se asignan a la última variable. Si hay más variables que campos, las variables sobrantes reciben como valor la cadena vacía "".

Consulte la página del estándar para obtener más información.

Algunos intérpretes de comandos como bash añaden otras opciones a este comando, como la posibilidad de imprimir un mensaje usando la opción -p (vea la ayuda de read en bash con el comando man bash).

TAREAS

Cree el script script_read.sh (éste, como es breve, no se le proporciona) que contenga lo siguiente:

script_read.sh
echo " Introduzca una cadena "
read CAD
echo " Cadena introducida: $CAD "

Asígnele el permiso de ejecución general, invóquelo y analice su funcionamiento.

El comando read también puede ser útil, por ejemplo, para detener la interpretación del script hasta que el usuario pulse una tecla:

TAREAS

Cree el script script_read_pause.sh que contenga lo siguiente:

script_read_pause.sh
echo "Pulse intro para continuar..."
read CAD
echo " Continuamos... "

Asígnele el permiso de ejecución general, invóquelo y analice su funcionamiento.

Resulta habitual el uso de estructuras while, combinadas con case y read, para crear menús interactivos, permitiendo mantenerse dentro del menú.

TAREAS

  1. Edite el script script_case_menu.sh para que tenga el siguiente contenido:

    script_case_menu.sh
    #!/bin/sh
    
    clear
    SALIR=0
    OPCION=0
    while [ $SALIR -eq 0 ]; do
       echo "Menu:"
       echo "1) Opcion 1"
       echo "2) Opcion 2"
       echo "3) Salir"
       echo "Opcion seleccionada: "
       read OPCION
       case $OPCION in
           1)
               echo "1 seleccionada" ;;
           2)
               echo "2 seleccionada" ;;
           3)
               SALIR=1 ;;
           *)
             echo "Opcion erronea";;
       esac
    done
    

    El comando clear, tampoco recogido en el estándar POSIX, también suele encontrarse habitualmente en la mayoría de los sistemas UNIX. Su funcionalidad es, simplemente, limpiar la información impresa en la consola de comandos.

  2. Ejecute el comando siguiente y seleccione las opciones del menú::

    script_case_menu.sh
    

3.6.1.3. Construcción de comandos en tiempo de ejecución, eval

El comando eval construye un comando mediante la concatenación de sus argumentos (pueden ser variables, etc.) separados por espacios. Dicho comando construido es leído por el shell e interpretado. La sintaxis del comando es:

eval [ argumentos … ]

Un posible uso es la creación de referencias indirectas a variables (parecido a usar punteros en lenguaje de programación C). En la tarea siguiente se muestra esto.

TAREAS

Cree el script script_eval.sh que contenga lo siguiente:

script_eval.sh
 # Ejemplo de referencia indirecta
 #  con eval

 VAR="Texto"

 # REF es una variable que vale VAR
 REF=VAR

 # equivale a ejecutar OTRA=$VAR
 eval OTRA='$'$REF

 # se accede al contenido de VAR
 #  a través de REF
 echo $OTRA

Asígnele el permiso de ejecución, invóquelo y analice su funcionamiento.

3.6.2. Comandos externos

Los comandos externos corresponden a ficheros ejecutables externos al shell. Cualquier posible aplicación pertenecería a esta categoría de comandos (ps, firefox, emacs,…). El estándar POSIX recoge una lista de comandos externos que aconsejablemente deberían estar en un sistema UNIX, clasificándolos en obligatorios u opcionales según se exija o no su implementación para satisfacer el estándar. Entre los comandos externos obligatorios, el estándar define los siguientes:

Básicos

cat, chmod, chown, cmp, cp, date, dirname, echo, expr, printf

Para profundizar

awk, basename, chgrp

TAREAS

Busque información sobre el comando echo y printf. Ejecute los siguientes comandos y analice su funcionamiento:

echo Uno
echo –n Uno; echo Dos
echo –e "Uno\nDos"
N=Ana
printf "Hola %s. Adios %s\n" $N $N