Juan Garcés

Personal Blog

Programación de Shell Scripts – Linux

septiembre 10th, 2013

Contenidos

1    Introducción
2    Conceptos
2.1    Shells
2.2    Ejecución
2.3    Estructura
2.4    Formatos
3    Variables
3.1    Variables de Entorno
3.2    Manejo de Strings
3.2.1    String entre comillas simples
3.2.2    String entre comillas dobles
3.2.3    Escape de Caracteres
4    Estructuras de Control
4.1    Condicionales
4.2    Bucles
4.3    Comparación de archivos y variables con el comando test

 

Introducción

 

Los Shell Scripts son pequeños, pero a la vez muy útiles, archivos de texto que contienen una serie de comandos para shell que el sistema ejecuta ordenadamente, de arriba abajo. Para editarlos, tan solo hace falta un editor de textos, como Emacs o Vi. Se guardan con extensión “.sh” y se ejecutan desde la Shell mediante el comando: sh nombre de script.sh o mediante el operador “./” nombre de script.sh. Los scripts, se comportan de igual manera que los comandos de la shell.

 

Conceptos

 

Shells

 

Si se desea saber qué Shells se tienen instalados en una distribución GNU/Linux sólo se tiene que teclear el comando:

 

cat /etc/shells

 

La salida de la instrucción anterior podría ser:

 

/bin/sh

/bin/bash

/sbin/nologin

/bin/ash

/bin/bsh

/bin/ksh

/usr/bin/ksh

/usr/bin/pdksh

/bin/tcsh

/bin/csh

/bin/zsh

 

Ejecución

Es importante también saber que un script puede ejecutarse en primer o en segundo plano:

  • Primer plano (foreground): se lanza introduciendo el nombre del script, pero hasta que el script no termine no se devolverá el control de la shell al usuario.

 

  • Segundo plano (background): se lanza igual que el anterior, pero añadiendo a continuación un &. El control de la shell pasa inmediatamente al usuario (este proceso es normalmente usado para procesos de larga duración)

 

 

Estructura

 

    La estructura de un shell script es la siguiente:

  1. El nombre del archivo debe tener la extensión .sh
  2. En su primera línea debe tener:

 

#!/bin/sh

Esto indica el tipo de shell que estamos programando.

  1. Instrucciones de shell

 

Ejemplo:

#!/bin/sh

echo “HOLA MUNDO”

 

Formatos

 

Comentarios: Los comentarios en shell script se indican con el operador “#” al inicial la línea que se desea como comentario.

Sensibilidad de Caracteres: En shell script se hace diferencia entre mayúsculas y minúsculas.

Tipos de Datos: No es necesario definir tipos de datos para las variables, sólo se requiere de la asignación de valores.

Cadenas de Caracteres: Las cadenas de caracteres se escriben entre dobles comillas: “”

Variables

 

En los shell scripts no es necesario definir los tipos de datos de las variables, sólo se requiere de la asignación por medio del operador =.

Ejemplo: variable=10

 

Para visualizar el contenido de una variable se utiliza:

Ejemplo: echo $variable

 

Para borrar el contenido de una variable se utiliza:

Ejemplo: unset variable

 

A continuación se muestra una tabla con una serie de variables especiales que nos serán de utilidad a la hora de escribir nuestros scripts:

VARIABLE  

DESCRIPCION  

$0 

Nombre del Shell-Script que se está ejecutando. 

$n 

Parámetro o argumento pasado al Shell-Script en la posición n, n=1,2,… 

$# 

Número de argumentos.

$* 

Lista de todos los argumentos. 

$? 

Salida del último proceso ejecutado. 

$$ 

Número de identificación del proceso (PID) 

$! 

Número del último proceso invocado por la shell 

 

Variables de Entorno

 

Por defecto, cuando asignamos un valor a una variable, es local, es decir, es conocida por esa shell, pero si se abre otra shell a partir de la que estamos, estas nuevas “subshells” desconocen el valor de las variables que hemos asignado anteriormente.

En cambio, las variables del entorno están disponibles para las subshells, es decir, los valores de estas variables son conocidos por los procesos hijos de la shell.

Para hacer que una variable se almacene en el área de entorno, se utiliza el siguiente comando:

Ejemplo: export variable=10

 

Para conocer todas las variables de entorno definidas debemos ejecutar el comando env, cuya salida es similar a la siguiente:

[usuario@srv-prueba01]/u02/prueba> env

HOSTNAME=srv-prueba01

TERM=xterm

SHELL=/bin/bash

HISTSIZE=1000

QTDIR=/usr/lib/qt-3.3

SSH_TTY=/dev/pts/1

PWD=/u02/prueba

EDITOR=/usr/bin/emacs

LANG=C

PS1=[$USER@$HOSTNAME]$PWD>

SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass

SHLVL=1

HOME=/u02/prueba

 

Manejo de Strings

En las shell scripts nos podemos encontrar con diferentes tipos de cadenas de caracteres y aquí analizaremos aquellas entre comillas simples y dobles y cómo utilizar las secuencias de escape.

String entre comillas simples

Las comillas simples nos sirven para hacer que la shell interprete lo encerrado entre ellas como una expresión literal, ya sean variables, comodines u otras expresiones, es decir, el contenido no es interpretado por la shell.

Para entenderlo mejor, imaginemos que deseamos crear una carpeta de nombre # o *. Si lo intentamos, es decir si tecleamos mkdir #, la shell indicará un error. Sin embargo si escribimos mkdir ‘#’, el intérprete de comandos tomará el carácter # como un literal y podremos crear la carpeta con ese nombre.

String entre comillas dobles

Este tipo de cadenas de caracteres permiten la sustitución de parámetros, la sustitución de comandos y la evaluación de expresiones aritméticas, pero ignoran las sustituciones de tilde, expansión de caracteres comodines, aliases y la división de palabras vía delimitadores.

Las comillas simples dentro de las comillas dobles no tienen efecto. Se pueden incluir comillas dobles dentro de una cadena con comillas dobles anteponiendo un \.

Es decir, se produce sustitución de variable (el signo de pesos se interpreta) por ejemplo, podremos ejecutar ls “$PWD” y nos devolverá correctamente el listado de archivos del directorio en que nos encontramos, pero si hacemos ls “*”, el comodín será tomado como un literal.

Escape de Caracteres

Una barra inversa permite escapar al carácter que acompaña, por ejemplo:

echo “\$alida con \” escapes \” ”

    En el ejemplo anterior, los caracteres $ (pesos) y ” (comillas) han sido escapados, por lo que no se interpretará una variable $alida ni darán error las dobles comillas incluidas.

 

Estructuras de Control

Cómo en cualquier lenguaje de programación, necesitaremos una serie de estructuras de control que permitan modificar el flujo de ejecución de las instrucciones de nuestro script.

 

Condicionales

if: Corresponde a la instrucción más sencilla y su sintaxis es:

if [ condicion ]

then

    sentencias

fi

 

if/else:

if [ condicion ]

then

    sentencias 1

else

    sentencias 2    

fi

 

    if/elif/else:

if [ condicion1 ]

then

    sentencias 1

elif [ condicion2 ]; then

    sentencias 2

else

    sentencias 3

fi

 

case: En esta estructura cuando se encuentre un patrón que coincida, se ejecuta la lista de comandos hasta los “;;” y se termina la ejecución de case.

case expresion in

1)

sentencias 1    

;;

2)

    sentencias 2


 

*)

    sentencias n

;;

Esac

 

Bucles

for: El bucle ‘for’ es una estructura de control iterativa que permite repetir una sección del programa, un número fijo de veces. Su sintaxis pueden ser las siguientes:

 

        for variable in [lista]

do

            sentencias

done

 

for (( inicio ; condicion_termino ; incremento ))

do

    sentencias

done

 

    Ejemplos:

        for variable in `seq 1 10`

do

echo $variable

done

 

        for ((variable=0; variable <= 10; variable++))

do

echo $variable

done

 

    while: Sirve para repetir un bucle mientras se cumpla la condición:

while [ condicion ]

do


sentencias

done

 

    Ejemplo:

num=0

while [ $num -le 10 ]

do

echo “numero: $num”

num=`expr $num + 1`

done

 

 

until: Igual que while, pero el ciclo se ejecutará mientras la condición sea falsa:

 

        until [ condicion ]

        do

            sentencias

        done

 

 

Ejemplo:

 

num=0

until [ $num -eq 10 ]

do

echo “numero: $num”

num=`expr $num + 1`

done

 

Comparación de archivos y variables con el comando test

Para evaluar expresiones condicionales dentro de los “if” u otras estructuras, se utiliza el comando “test”. Veamos un resumen en la siguiente tabla:

 

Expresión

DESCRIPCIóN

-b archivo

Cierto si archivo existe y es un dispositivo de bloques.

-c archivo

Cierto si archivo existe y es un dispositivo de caracteres.

-d archivo

Cierto si archivo existe y es un directorio.

-e archivo

Cierto si archivo existe.

-f archivo

Cierto si archivo existe y es un archivo normal.

-g archivo

Cierto si archivo existe y tiene el bit de grupo activado.

-k archivo

Cierto si archivo tiene el bit de sticky activado.

-L archivo

Cierto si archivo existe y es un enlace simbólico.

-p archivo

Cierto si archivo existe y es una tubería nombrada.

-r archivo

Cierto si archivo existe y es legible.

-s archivo

Cierto si archivo existe y su tamaño es mayor que cero.

-S archivo

Cierto si archivo existe y es un socket.

-t [df]

Cierto si df está abierto en un terminal. Si df es omitido, se toma 1 (salida estándar) por defecto. 

-u archivo

Cierto si archivo existe y tiene el bit de usuario activo.

-w archivo

Cierto si archivo existe y es escribible.

-x archivo

Cierto si archivo existe y es ejecutable.

-O archivo

Cierto si archivo existe y es propiedad del identificador efectivo del usuario.

-G archivo

Cierto si archivo existe y es propiedad del identificador efectivo del grupo.

archivo1 -nt archivo2

Cierto si archivo1 es más reciente (en base a la fecha de modificación) que archivo2.

archivo1 -ot archivo2

Cierto si archivo1 es más antiguo que archivo2.

archivo1 -ef archivo2

Cierto si archivo1 y archivo2 tienen el mismo número de dispositivo y de nodo-i.

-z cadena

Cierto si la longitud de cadena es cero.

-n cadena

Cierto si la longitud de cadena no es cero. 

cadena

Cierto si la longitud de cadena no es cero. 

cadena1 = cadena2

Cierto si las cadenas son iguales. 

cadena1 != cadena2

Cierto si las cadenas no son iguales.

! expr

Cierto si expr es falsa. 

expr1 -a expr2

Cierto si expr1 y expr2 son ciertas. 

expr1 -o expr2

Cierto si expr1 o expr2 son ciertas. 

arg1 OP arg2

OP es uno de los siguientes valores:

 

-eq igual que,

-ne distinto,

-lt menor que,

-le menor o igual que,

-gt mayor que,

-ge mayor o igual que.

 

arg1 y arg2 pueden ser enteros positivos, enteros negativos 

 

Ejemplos:

a.

    if [ -r «script.out» ]

then

echo “Archivo existe”

else

echo “Archivo no existes”

fi

 

b.

    if test -r “script.out”

then

echo “Archivo existe”

else

echo “Archivo no existes”

fi

 

c.

read variable

if test $variable -le 10

then

echo “Menor o igual que 10″

else

echo “Mayor que 10″

fi


 

Comments

3 Comments

RSS

Juan Garcés

Personal Blog