Tabla de contenidos
Para la relación con el sistema el administrador debe utilizar un interface. Evidentemente en los sistemas modernos los interfaces visuales son la principal forma de dar ordenes al ordenador, pero en Unix y en Linux el administrador debería conocer también un interface textual.
Cuando se utiliza en linea para introducir directamente comandos se denomina shell interactiva.
Para el administrador, el interprete de comandos (shell) y "guiones" del interprete de comandos (shell scripts) son muy importantes por varias razones:
La mayor parte de herramientas y aplicaciones están preparadas para utilizarse mediante la shell y los scripts.
La configuración del sistema y de la mayoría de los servicios proporcionados se hacen mediante herramientas proporcionadas en forma de shell scripts.
La principal forma de automatizar procesos de administración es mediante la creación de shell scripts por parte del administrador.
También veremos algunos servicios donde se utilizan habitualmente los shell script.
Los shell scripts son ficheros de texto que contienen comandos de sistema, comandos propios del interprete de comandos y estructuras de control necesarias para procesar el flujo del programa (tipo while, for, etc). Los ficheros script son directamente ejecutables por el sistema bajo el nombre que se haya dado al fichero. Para ejecutarlos, se invoca el shell junto con el nombre del fichero, o bien se dan permisos de ejecución.
La programación en shell es muy útil y cómoda para crear programas fácilmente modificables, pequeños, no complejos, que resuelvan tareas repetitivas, típicas de los administradores. Además, es un lenguaje preparado para manejar ristras y procesar y filtrar texto, por lo que es mucho más fácil programar en shell, que, por ejemplo, en C.
Un inconveniente es que no es un lenguaje estandarizado si no que hay varias versiones del shell.
Algunos de los más comunes son:
El shell Bourne (sh). El shell estándar UNIX, y el que todos los UNIX poseen en alguna versión, en linux es un bash renombrada. El sh fue creado por Stephen Bourne en AT&T a finales de los setenta. El prompt por defecto suele ser un '$' y en usario root '#'.
El shell Bash (bash). El shell Linux por defecto. Deriva de la bourne shell pero se ha impuesto en gran medida por su utilización en Linux.
El shell Korn (ksh). Es una mejora del Bourne, escrito en AT&T por David Korn en los años ochenta, intenta combinar la sencillez del Bourne con la eficacia de la shell C, más algún añadido. El prompt por defecto es el $.
El shell C (csh). Fue desarrollado en la Universidad de Berkeley por Bill Joy a finales de los setenta y tiene unos cuantos añadidos interesantes al Bourne, como un histórico de comandos, alias, aritmética desde la línea de comandos, completa nombres de ficheros y control de trabajos en segundo plano. El prompt por defecto para los usuarios es `%'. Una ventaja de los scripts en C shell es que, como su nombre indica, su sintaxis está basada en el lenguaje C. Como shell posteriores recogen las mejoras de esta, hace que no se utilice mucho, aunque todavía se encuentran muchos scripts desarrollados para esta shell.
Existen muchas otras que son variantes de estas, normalmente versiones reducidas con aplicaciones específicas.
Cada shell cambia un poco el lenguaje pero tienen muchas características comunes. Vamos a ver un resumen de la sintaxis del lenguaje:
Los comentarios se comienzan con #. En la primera linea se debe escribir #! con la shell que (o incluso un interprete, como perl o php) con la que queremos ejecutarla, por ejemplo:
#!/bin/bash
Para realizar redirecciones de los programas se utilizan
>
para salida, <
para
entrada, &<
para salida de error y
|
túnel (pipe).
cat laza.txt |wc -l > lineas_laza.count
La salida del comando cat que es le fichero
laza.txt
se le pasa al comando wc
-l que cuenta las lineas y lo mete en el fichero lineas_laza.count
.
Para definir variables se debe poner el nombre seguido de igual y su valor. Para referenciarlas con el símbolo dolar ($). Existen variables predefinidas, como $1 para el primer parámetro del shell script, $HOME directorio home de usuario, $? código de salida de programa recién ejecutado y muchas más dependiendo de la shell.
FILE=/tmp/salida cat laza.txt | wc -l >> $FILE
Crea la variable FILE poniendo un nombre de fichero y la utiliza para añadir la salida del resultado del contador de lineas.
Hay tres tipos de comillas, las dobles interpretan las variables que hay dentro, las simples no, y la comilla invertida ejecuta su contenido como un comando y lo mete en la variable.
DATE=`date +%d-%m-%Y`; MSG1="La fecha es $DATE"; MSG2='La variable donde guardo la fecha se llama $DATE con el comando date +%d-%m-%Y'; echo $DATE; echo $MSG1; echo $MSG2;
Para ejecutar este script:
[pcm@sal]#
sh comillas.sh
14-04-2007 La fecha es 14-04-2007 La variable donde guardo la fecha se llama $DATE con el comando date +%d-%m-%Y
[pcm@sal]#
Para las shell la condición verdadera es el 0 y el resto lo interpreta como falso. Existen bastantes operadores para realizar las condiciones. Pueden hacerse condiciones sobre fichero: si es un fichero (-f), si es un directorio (-d), si hay permiso de lectura (-r). También sobre cadenas, sobre números y combinar condiciones.
Por ejemplo [ -d .ssh -a \( -n $JDK_HOME -o -n $JAVA_HOME \) ]
nos
devolvería como verdadero si existe el directorio .ssh
y alguna de las dos variables
no deben ser vacías.
Para el control de flujo tenemos las estructuras
if
, case
,
while
, for
y until
.
Existen un conjunto de herramientas que son muy utilizadas en los
shell script, como pueden ser cut
,
grep
, sed
,
awk
, date
, etc...
Para hacer debug podemos chequear la sintaxis del shell script con:
sh -n mishell.sh
También podemos hacer que nos muestre la ejecución de los comandos que hay en el shell script y los valores que van tomando las variables con:
sh -x mishell.sh
Como ejemplo de programa shell script vamos a hacer una utilidad para buscar ficheros de texto de DOS en el directorio actual y preguntarnos si lo queremos convertir a fichero de texto UNIX. Los ficheros de texto en la plataformas DOS/Windows para finalizar cada linea llevan dos caracteres de control, el ascii 10 (LF) y el ascii 13 (CR). En cambio en UNIX, y por tanto el Linux los fichero de linea sólo utilizan el carácter de control ascii 10 (LF).
La mayor parte de los editores de Linux ya distinguen si es un texto de DOS o Unix. Además existe un comando para realizar esta conversión, dos2unix. Por lo que no suele hacer falta una shell para esta tarea, a no ser que no dispongamos del conversor en el sistema. El programa sería:
#!/bin/bash for fichero in *.txt; do if grep ^M $fichero &>/dev/null; then resp=x while [ $resp != "s" -a $resp != "n" ]; do echo "'$fichero' es un fichero texto DOS. convertir? (s/n) " read resp done case $resp in s) sed 's/^M//' $fichero > /tmp/FILE_TMP mv /tmp/FILE_TMP $fichero echo "El fichero '$fichero' convertido a texto UNIX";; n) echo "El fichero '$fichero' se deja texto DOS";; *) echo "ERROR";; esac fi done
Primeramente ponemos el comentario para indicar que es un script para bash.
El for nos va a realizar un bucle por todos
los fichero que terminen en .txt
.
Hacemos una condición que con el comando grep nos mire si el fichero tiene lineas con carácter ascii 13 (CR). Para introducir el carácter ^M hemos pulsado Control+V y Control+M, no se escribe con ^ y la M. Este comando si no encuentra ninguna linea devuelve 1, y si encuentra al menos una linea devuelve cero, con lo cual cumplimos la condición.
A continuación vamos a pedir al usuario que nos confirme la conversión. Para ello ponemos por pantalla la pregunta y con el comando read cogemos el valor introducido. Con un while insistimos con la pregunta mientras la contestación no sea s o n.
Con case comprobamos que ha metido. Sería más lógico hacerlo con un if else, pero así vemos está estructura. Sí selecciono n se imprime por pantalla que no se hizo nada con el fichero.
Cuando opto por convertir el fichero utilizamos la herramienta sed que mediante expresiones regulares nos permite hacer sustituciones dentro de un fichero de texto. En este caso le estamos diciendo que sustituya los CR por nada. La salida la redirigimos a un fichero temporal que luego sustituye al original.
Para ejecutar el programa tendríamos dos posibilidades, o bien lo hacemos ejecutable con el comando chmod u+w txtunixdir.sh y luego lo arrancamos como ./txtunixdir.sh o bien le pasamos a una shell como parámetro nuestro programa:
[pcm@sal]#
sh txtunixdir.sh
cursos.txt' es un fichero texto DOS. convertir? (s/n)
n
El fichero 'cursos.txt' se deja texto DOS 'lazae11.txt' es un fichero texto DOS. convertir? (s/n)
s
El fichero 'lazae11.txt' convertido a texto UNIX
[pcm@sal]#
Si al escribir el programa nos hubiésemos dejado sin poner los dos puntos y coma en las opciones del case tendríamos un error, que antes de ejecutar nos lo advertiría.
... n) echo "El fichero '$fichero' se deja texto DOS" ...
Si solo queremos comprobar sin ejecutar lo podríamos hacer con la opción -n.
[pcm@sal]#
sh -n txtunixdir.sh
txtunixdir.sh: line 16: syntax error near unexpected token `)' txtunixdir.sh: line 16: ` *)'
[pcm@sal]#
Corregimos de nuevo, y ahora ejecutamos pero con la opción -x.
[pcm@sal]#
sh -x txtunixdir.sh
+ grep $'\r' cursos.txt + resp=x + '[' x '!=' s -a x '!=' n ']' + echo ''\''cursos.txt'\'' es un fichero texto DOS. convertir? (s/n) ' 'cursos.txt' es un fichero texto DOS. convertir? (s/n) + read resp
s
+ '[' s '!=' s -a s '!=' n ']' + sed $'s/\r//' cursos.txt + mv /tmp/FILE_TMP cursos.txt + echo 'El fichero '\''cursos.txt'\'' convertido a texto UNIX' El fichero 'cursos.txt' convertido a texto UNIX + grep $'\r' iptables.txt + grep $'\r' lazae11.txt
[pcm@sal]#