Sie sind auf Seite 1von 17

Tema 3: Linux: Shell de Linux, Programacin con Bash

Objetivos:
- Entender el uso de scripts in sistemas Linux.
- Aprender comandos y sintax de Bash shell
- Formar programas con lenguaje de programacin de Bash

Fundamentos de los shells de Linux

El intrprete de lnea de comandos de Linux se llama el shell


Capa de insulacin entre sistema operativo y el usuario
Lenguaje poderoso; programas se refiere con nombre script
Pegar comandos juntos
Conocimiento de shell scripting es fundamental para sistema operativo

El Lenguaje con los siguientes construcciones: (1) construciones de bucles, (2)


construcciones de condicionale, (3) funciones de shell, (4) funciones built-in
Porque Scripts?
Script importante para administracipn y configuracin
Por Ejemplo: Linux arranque: ejecuta el shell scripts en el directorio de
/etc/rc.d para restorar el configuracin de sistema y
iniciar los servicios.
sintaxis es como pegando comandos junto.
un manera rpido para hacer prototipos.
Cuando no debe usar scripting
tareas intensivas de los recursos, velocidad es importante
aplicaciones complejos - programacin estructurad es importante
tratamiento de ficheros; E/S intensivo
necesidad de generar o tratar con grficos o GUIs
necesidad de tener aceso directo al hardware de sistema
necesidad de utilizar E/S de sockets
necesidad de utilizar librarias
Ejemplos de Scripts
En el caso ms sencillo, el script es solo una lista de comandos guardado en un fichero.
Por ejemplo, limpiar ficheros en /var/log
# limpiar
# Ejecuta como root
cd /var/log
cat /dev/null > messages
cat /dev/null > wtmp
echo "Log limpia."

Un ejemplo de un script ms complicado es la siguiente. (Tenemos que estudiar distintos


elementos de este script)

#!/bin/bash
# cleanup, version 2
# Ejecutar como root
LOG_DIR=/var/log
ROOT_UID=0
#
LINES=50
#
E_XCD=66
#
E_NOTROOT=67
#

Only users with $UID 0 have root privileges.


Default number of lines saved.
Can't change directory?
Non-root exit error.

if [ "$UID" -ne "$ROOT_UID" ]


then
echo "Must be root to run this script."
exit $E_NOTROOT
fi
if [ -n "$1" ]
# Test if command line argument present (non-empty).
then
lines=$1
else
lines=$LINES # Default, if not specified on command line.
fi
cd $LOG_DIR
if [ `pwd` != "$LOG_DIR" ]

# or
if [ "$PWD" != "$LOG_DIR" ]
# Not in /var/log?

then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi # Doublecheck if in right directory, before messing with log file.
tail -$lines messages > mesg.temp # Saves last section of message log file.
mv mesg.temp messages
# Becomes new log directory.
cat /dev/null > wtmp #
echo "Logs cleaned up."

': > wtmp' and '> wtmp'

have the same effect.

exit 0

Un valor cero desde el script cuando exit indica exito. el simbolo #! en primer linea indica que
el fichero es listo para un conjunto de comandos. En realidad es un nmero magico de dos
bytes que indica el tipo de fichero.

Otros ejemplos que llama interpredores son:

#!/bin/sh
#!/bin/bash
#!/usr/bin/perl
#!/usr/bin/tcl
#!/bin/sed -f
#!/usr/awk -f

Llamando el script
sh < scriptname >
chmod 555 scriptname (gives everyone read/execute permission)
chmod +rx scriptname (gives everyone read/execute permission)
chmod u+rx scriptname (gives only the script owner read/execute

permission)

2.2 Operaciones Basicas


Dentro de operaciones bsicas que estamos interesados: caracteres especiales, variables y
parametros, quoting, estatus de salir. En este apartado, investigamos estas posibilidades.

Caracteres Especiales
\# Comentarios
; Separador de Comandos. Permite dos o ms comandos, echo hola; echo buenos
;; Terminador de sentencia case [Double semicolon]
Considera la siguiente ejemplo:
case "$variable" in
abc) echo "$variable = abc" ;;
xyz) echo "$variable = xyz" ;;
esac

En esta ejemplo, utilizamos full quoting. Si tenemos 'STRING' preserva todos los caracteres
especiales dentro de STRING. El operador coma: El operador coma enlace operaciones
aritmeticas; para que todos estan evaluadas, pero solo se devuelve el ltimo

let "t2 = ((a = 9, 15 / 3))"

# Set "a" and calculate "t2".

Expansion de variables y Sustitucin de subcadenas.


La combinacin :> (: con el operador de redireccin >), se puede poner el tamao de fichero a
cero, sin cambiar los permisos. Si el fichero no existe, lo crea.
.
: > data.xxx

# Fichero "data.xxx" ahora vacio

Tiene la misma efecto que cat /dev/null >data.xxx Pero no va a fork un procesos nuevo,
debido que ":" es una funcin builtin. La caractera ":" tambien sirve como separador de campo
en /etc/passwd, y en la definicin del variable de entorno $PATH.

bash$ echo $PATH


/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games

Mas Caracteres especiales:


? es el operador de prueba; dentro de ciertos expresiones, la caractera ? indica una
prueba para una condicin.
$ sustitucin de variable
[] prueba; la expresin de prueba va dentro de las claves [ ].

var1=5
var2=23skidoo
echo $var1
echo $var2

# 5
# 23skidoo

Manipulando y/o expandiendo variables

${parametro} Es lo mismo que $parametro, eg. , el valor del parametro de variable. Se puede
utilizarlo para concatenar variables con cadenas. En bash las cadenas y expresiones
numericos se trata en una manera similar.
your_id=${USER}-on-${HOSTNAME}
echo "$your_id"
#
echo "Old \$PATH = $PATH"
PATH=${PATH}:/opt/bin #Add /opt/bin to $PATH for duration of script.
echo "New \$PATH = $PATH"

Sentencias de control: until


until TEST-COMMANDS; do CONSEQUENT-COMMANDS; done

Ejecutar CONSEQUENT-COMMANDS hasta el comando final


TEST-COMMANDS tiene un estatus de salida que no es cero.
#!/bin/bash
COUNTER=20
until [ $COUNTER -lt 10 ]; do
echo COUNTER $COUNTER
let COUNTER-=1
done

Sentencias de control: while


while TEST-COMMANDS; do CONSEQUENT-COMMANDS; done

Ejecutar CONSEQUENT-COMMANDS hasta el comando final


TEST-COMMANDS tiene un estatus de salida que es cero.
#!/bin/bash
COUNTER=0
while [ $COUNTER -lt 10 ]; do
echo The counter is $COUNTER
let COUNTER=COUNTER+1
done

Sentencia de control: for


for NAME [in WORDS ...]; do COMMANDS; done

Ejecutar COMMANDS para cada miembro en WORDS, con NAME enlazada al miembro actual
for i in vacas cabritos cerdos pollos
do
echo ``$i es un animal de granja''
done
echo -e pero \n GNUs no son ''

Sentencias Condicional: if
if TEST-COMMANDS; then
CONSEQUENT-COMMANDS;
[elif MORE-TEST-COMMANDS; then
MORE-CONSEQUENTS;]
[else ALTERNATE-CONSEQUENTS;]
fi

Un ejemplo de un script utilizando la sentencia if:


#!/bin/sh
X=10
Y=5
if test ``$X'' -gt ``$Y'' ; then
echo ``$X is greater than $Y''
elif test ``$X'' -lt ``$Y'' ; then
echo ``$X is less than $Y''
else
echo ``$X is equal to $Y''
fi

Ejemplo utilizando test


#!/bin/sh
if test ``$1'' = ``'' ; then
echo ``Usage: backup-lots.sh <filename>''
exit
fi
for i in 0 1 2 3 4 5 6 7 8 9 ; do
NEW_FILE=$1.BAK-$i
if test -e $NEW_FILE ; then
echo ``backup-lots.sh : warning $NEW_FILE''
echo ``
already exists''
else
cp $1 $NEW_FILE
fi
done

Sentencias Condicional: case


`case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac'

Ejecutar selectivamente los COMMANDS basada sobre WORD que match PATTERN.
La barra $|$ esta utilizado para separar patrones multiples.

echo -n "Entra el nombre del animal: "


read ANIMAL
echo -n "El \$ANIMAL tiene "
case \$ANIMAL in
caballo | perro | gato) echo -n "four";;
hombre | kangaroo ) echo -n "two";;
*) echo -n "un numero no conocido de";;
esac
echo "piernes."

Funciones de Shell
[`function'] NAME () { COMMAND-LIST; }

#!/bin/bash
function quit {
exit
}
function hola {
echo Hola!
}
hola
quit
echo foo

#!/bin/sh
if test ``$1'' = ``'' ; then
echo ``Usage: backup-lots.sh <filename>''
exit
fi
for i in 0 1 2 3 4 5 6 7 8 9 ; do
NEW_FILE=$1.BAK-$i
if test -e $NEW_FILE ; then
echo ``backup-lots.sh : warning $NEW_FILE''
echo ``
already exists''
else
cp $1 $NEW_FILE
fi
done

Sentencias Condicional: case


`case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac'

Ejecutar selectivamente los COMMANDS basada sobre WORD que match PATTERN.
La barra $|$ esta utilizado para separar patrones multiples.

echo -n "Entra el nombre del animal: "


read ANIMAL
echo -n "El \$ANIMAL tiene "
case \$ANIMAL in
caballo | perro | gato) echo -n "four";;
hombre | kangaroo ) echo -n "two";;
*) echo -n "un numero no conocido de";;
esac
echo "piernes."

Factorial con bucle while


Funciones en en bash son como programas en C. Este ejemplo es lo mismo del factorial de
antes, pero este vez utilizando un bucle while.
function factorial ()
{
N=$1
A=1
while test $N -gt 0 ; do
A = 'expr $A '+' $N'
N = 'expr $N - 1'
done
echo $A
}

Algunas Bourne Shell Builtins


:
expander argumentos y hacer redirecciones
.
Leer y ejecutar los comandos del FILENAME en contexto de shell actual
break Salir del bucle
cd
cambiar directorio actual de trabajo
continue resumir la proximo iteracin dentro un bucle.
Echo
imprime argumentos a salida estandar
eval
argumentos estan concatenado
exec
exit
Salir del shell
export pasar a procesos hijos
getopts Parse options to shell scripts or functions.
hash
kill
seal para para proceso
pwd
imprime directorio actual
read
lear del entrada del shell
return devuelve un funci\'on de shell con valor
test, '['} Evaluar un expresin conditional.
'imes imprime los usuarios y tiempos de sistema usado por los hijos.

Variables
IFS
PATH
HOME
CDPATH
MAILPATH
PS1
PS2
OPTIND
OPTARG

una lista de caracteres que separar campos utlizado cuando el


shell compartir palabras como parte de la expansin
lista de directorios que shell puede buscar comandos
directorio home de usuario
lista de directorios usado por comando cd
lista de ficheros que el shell mira para nuevas mensajes de correo
cadena primaria de prompt
cadena secundaria de prompt
el indice de la ltima opcin procesado por getopts
el valor de la ltima argumenta procesado por getopts

Ejemplos
# cleanup: Un script para limpiar los ficheros log en /var/log
# Ejecutar como root
cd /var/log
cat /dev/null > messages
cat /dev/null > wtmp
echo "Los logs esta limpia."

Example 2-2. cleanup An enhanced and generalized version of above


#!/bin/bash
# cleanup, version 2
# Run as root, of course.

script.

if [ -n $1 ]
# Test if command line argument present.
then
lines=$1
else
lines=50
# default, if not specified on command line.
Fi
cd /var/log
tail -$lines messages > mesg.temp
# Saves last section of message log file.
mv mesg.temp messages
# cat /dev/null > messages
# No longer needed, as the above method is safer.
cat /dev/null > wtmp
echo "Logs cleaned up."
exit 0
# A zero return value from the script upon exit
# indicates success to the shell.

Conditionals with variables


#!/bin/bash
T1="foo"
T2="bar"
if [ "$T1" = "$T2" ]; then
echo expression evaluated as true
else
echo expression evaluated as false
fi

Caracteres especiales de Bash


Algunas caracteres tiene distintos signficacia dependiendo en su contexto. Dos de ellos puede
ser las caracteres siguientes:

; Seperador de comandos. Puede poner dos comandos en misma linea.


: null command. Exit status 0, alias for true, see below

echo hola; echo amigo

En este ejemplo, vemos la manera de separar dos comandos.

Endless loop:
while :
do
operation-1
operation-2
...
operation-n
done
if condition
then :
# Do nothing and branch ahead
else
take-some-action
fi

${} Parameter substitution.

${parameter-default}
${parameter=default}
${parameter+otherwise}
${parameter?err_msg}

Si parametro no esta fija, usar default


Si parametro no esta fija, fijar al default
Si parametro fija, usar 'otherwise", else usar null string
Si parametro fjio, usarlo, else imprimir err_msg

#!/bin/bash
: ${HOSTNAME?} {USER?} {MAIL?}
echo $HOSTNAME
echo $USER
echo $MAIL
echo Critical env. variables set.
exit 0

Sustitucin y expansin

${var#pattern}, ${var##pattern} quitar mas corta/mas larga parte de patron


si es similar a principio de variable
${var%pattern}, ${var%%pattern} quitar mas corta/mas larga si es similar a
final de variable
${var:pos} variable var expandido, empezando con posicin pos
${var:pos:len} expansin a max de longitud len de caracteres de variable var
desde la posicin pos
${var/patt/replacement} primer similaridad de patron, dentro var replaced with
replacement.
${var//patt/replacement} all matches of pattern, within var replaced with
replacement.

Ejemplo
#!/bin/bash
var1=abcd-1234-defg
echo "var1 = $var1"
t=${var1#*-*}
echo "var1 (with everything, up to and including first - stripped out) = $t"
t=${var1%*-*}
echo "var1 (with everything from the last - on stripped out) = $t"
path_name=/home/bozo/ideas/thoughts.for.today
echo "path_name = $path_name"
t=${path_name##/*/}
# Same effect as
t=`basename $path_name`
echo "path_name, stripped of prefixes = $t"
t=${path_name%/*.*}
# Same effect as
t=`dirname $path_name`
echo "path_name, stripped of suffixes = $t"
t=${path_name:11}
echo "$path_name, with first 11 chars stripped off = $t"
t=${path_name:11:5}
echo "$path_name, with first 11 chars stripped off, length 5 = $t"
t=${path_name/bozo/clown}
echo "$path_name with bozo replaced = $t"
t=${path_name//o/O}
echo "$path_name with all o's capitalized = $t"
exit 0

Grupo de Comandos
(.)
Grupo de comandos. \texttt{(a=hello; echo \$a)}
{ .} Bloque de cdigo. Crea un funci\'on anonimo. Bloque de codigo puede tener E/S
rediricionado desde y hacia el.
#!/bin/bash
# Bloques de cdigo y E/S redireccin
{
read fstab
} < /etc/fstab
echo "Primer linea de /etc/fstab es:"
echo "$fstab"
exit 0

Redireccin

The concept of a standard input and a standard output is one of the most useful features of
UNIX-like operating systems. The idea is that every program, no matter how diverse, should be
reading input and generating output in a uniform, clearly understood way. Once you have that, it
makes it much easier for programs to talk to one another directly. It is also possible to write generic
programs that bridge the input and output of any two programs, which is an amazingly handy ability
to have.
Send standard output to a file.

>
<
2>
>>
|

Read standard input from a file.


Redirect standard error as specified.
Append standard output to the specified file.
Couple the standard output of one program to the standard input of another
program.
Copy standard input to a file and also to standard output.

tee
script Save the activity on your screen in a file.
xargs Read multiple arguments from standard input and use them as arguments to
some specified command.

scriptname >filename
command >&2
scriptname >>filename

<<
|
>|
-

(redireccionar salida de un comando a stderr)


(anadir la salida de scriptname a un fichero)

redireccionar stdin
Tuberia. Salida de un comando a otro o shell
forzar redirecci\'on. Sobre-escribir un fichero existente.
redirecci\'on desde/hacia stdin or stdout.

Ejemplos:
echo ls -l | sh

cat *.lst | sort | uniq

# ordenar la salida de .lst


# ficheros y borrar lineas duplicados.

(cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)


# Mover arbol de fichero entero desde un directorio a otro

bunzip2 linux-2.2.15.tar.bz2 | tar xvf -

Redireccin y ficheros
Hay tres descriptores de ficheros: stdin, stdout y stderr

redireccionar stdout a un fichero


redireccionar stderr a un fichero
redireccionar stdout a un fichero
redireccionar stderr a stdout
redireccionar stderr y stdout a un fichero
redireccionar stderr y stdout a stdout
redireccionar stderr y stdout a stderr

1 representa stdout
2 representa stderr
grep da * 2> grep-errors.txt

Escribir sderr a un fichero

grep da * 1>&2

Escribir stdout a misma descriptor de fichero que stderr

Escribir sterr a misma descriptor de fichero que stdout


grep * 2>&1
rm -f $(find / -name core) &> /dev/null

Tuberias

ls -l | sed -e "s/[aeio]/u/g"
ls -l | grep "\.txt$"

Acceder Parametros
$0, $1,etc. parametros positional (desde linea de comandos o desde funcin, o
un variable)
$#
numero de argumentos o parametros posicional en linea de comandos
$$
id de proceso de script, utilizado a menudo en scripts para construir nombre de
ficheros temporal
$?
estatus de salida (exit) de funcin o de script
$*
todo los parametros positionales
$@
lo mismo de $*, pero para cada parametro es un string en comillas
$flags passed to script
$!
PID de ltima job ejecutando en fondo
=
asignacin de variables (no espacio antes y despues de &)
Obtener valor de return de un programa

Valor de salida return value de una programa esta guardad en un variable especial, denomida
$?.
Ejemplo de como capturar valor de salida:
#!/bin/bash
cd /dada &> /dev/null
echo rv: $?
cd $(pwd) &> /dev/null
echo rv: $?

Comparicin de Cadenas
s1 = s2 s1 igual a s2
s1 != s2 s1 no es igual a s2
s1 < s2
s1 > s2
-n s1 s1 no es null
z s1 s1 es null

#!/bin/bash
S1='string'
S2='String'
if [ $S1=$S2 ];
then
echo "S1('$S1') no es igula a S2('$S2')"
fi
if [ $S1=$S1 ];
then
echo "S1('$S1') es igual a S1('$S1')"
fi

Sentencia de if/then
#!/bin/bash
if [ condition-true ]
then
command 1
command 2
...
else
# Opcional para anadir mas chequeos
command 3
command 4
...
fi

if [ -x filename ]; then
elif

if [ 0 ]
then
echo "0 es verdad."
else
echo "0 es falso."
fi
if [ ]
#NULL (empty condition)
then
echo "NULL es verdad."
else
echo "NULL es falso."
fi
if [ xyz ]
#string
then
echo "string aleatorio es verdad."
else
echo "string aleatorio es falso."
fi

Equivalence of [ ] and test


#!/bin/bash
if test -z $1
then
echo "No command-line arguments."
else
echo "First command-line argument is $1."
fi
# Both code blocks are functionally identical.
if [ -z $1 ]
# if [ -z $1
# also works, but outputs an error message.
then
echo "No command-line arguments."
else
echo "First command-line argument is $1."
fi
exit 0

Tests, command chaining, redireccin


#!/bin/bash
filename=sys.log
if [ ! -f $filename ]
then
touch $filename; echo "Creating file."
else
cat /dev/null > $filename; echo "Cleaning out file."
fi
# Nota /var/log/messages tiene que tener permisos (644) para que este funciona
tail /var/log/messages > $filename
echo "$filename contains tail end of system log."
exit 0

Aritmetica y comparaciones de cadenas

#!/bin/bash
a=4
b=5

# a y b puede estar tratado como enteros o strings.


if [ $a -ne $b ]
then
echo "$a is not equal to $b"
echo "(arithmetic comparison)"
fi
echo
if [ $a != $b ]
then
echo "$a is not equal to $b."
echo "(string comparison)"
fi
echo
Operadores Aritmeticas
Arithmetic operators: +, -, *, /
Arithmetic relational operators: -lt (<),

-gt (>), -le (<=), -ge (>=), -eq (==),

Using expr: Arithmetic Operators


#!/bin/bash
echo Arithmetic Operators
echo
a=`expr 5 + 3`
echo 5 + 3 = $a
a=`expr $a + 1`
echo
echo a + 1 = $a
echo \(incrementing a variable\)
a=`expr 5 % 3`
# modulo
echo
echo 5 mod 3 = $a

Logical Operators
#!/bin/bash
echo Logical Operators
a=3
echo a = $a
b=`expr $a \> 10`
echo 'b=`expr $a \> 10`, therefore...'
echo "If a > 10, b = 0 (false)"
echo b = $b
b=`expr $a \< 10`
echo "If a < 10, b = 1 (true)"
echo b = $b

-ne (!=)

Comparison Operators

#!/bin/bash
echo Comparison Operators
echo
a=zipper
echo a is $a
if [ `expr $a = snap` ]
# Force re-evaluation of variable 'a'
then
echo "a is not zipper"
fi

String Operators
#!/bin/bash
echo String Operators
echo
a=1234zipper43231
echo The string being operated upon is $a.
# index: position of substring
b=`expr index $a 23`
echo Numerical position of first 23 in $a is $b.
# substr: print substring, starting position & length specified
b=`expr substr $a 2 6`
echo Substring of $a, starting at position 2 and 6 chars long is $b.
# length: length of string
b=`expr length $a`
echo Length of $a is $b.
# 'match' operations similarly to 'grep'
b=`expr match $a [0-9]*`
echo Number of digits at the beginning of $a is $b.
b=`expr match $a '\([0-9]*\)'`
echo The digits at the beginning of $a are $b.

exit 0

Letting let do some arithmetic

#!/bin/bash
let a=11
# Same as 'a=11'
let a=a+5
# Equivalent to let "a
# (double quotes makes
echo "a = $a"
let "a <<= 3"
# Equivalent of let "a
echo "a left-shifted 3

= a + 5"
it more readable)

= a << 3"
places = $a"

let "a /= 4"


# Equivalent to let "a = a / 4"
echo $a
let "a -= 5"
# Equivalent to let "a = a - 5"
echo $a
let "a = a * 10"
echo $a
let "a %= 8"
echo $a
exit 0

xargs
[-0prtx] [-e[eof-str]] [-i[replace-str]] [-l[maxlines]] [-n max-args] [-s max-chars][-P max-procs] [-null] [--eof[=eof-str]] [--replace[=replace-str]] [--max-lines[=max-lines]] [--interactive] [-maxchars=max-chars] [--verbose] [--exit] [--max-procs=maxprocs] [--max-args=max-args] [--norun-if-empty] [-version] [--help] [command [initial-arguments]]
Read arguments from standard input, construct a command line using those arguments and
arguments provided on its own command line, and execute the constructed commands.
Example: Suppose you have some time on your hands and you want to grep through every file in
the /usr/local filesystem for the string "datum". First, generate a list of the files using the find
command; then pipe the results of that find to grep via the xargs command. (If you don't use xargs,
grep will look only at the names of the files for the string "datum", and not look in the files
themselves.) In other words, use
find /usr/local -type f -print | xargs grep "datum"

--null, -0
--eof[=eof-str], -e[eofstr]
--help
--replace[=replace-str], i[replace-str]
--max-lines[=max-lines], l[max-lines]
--max-args=max-args, -n maxargs
--interactive, -p

Input files are terminated by Null rather than the


end-of-file character.
Treat the specified string as the end-of-file marker.
Display a listing of the possible arguments to
xargs.
Replace occurrences of replace-str in the initial
arguments with names read from standard input.
Limit commands to at most max-lines nonblank
lines per command (default 1).
Limit commands to at most max-args.
Prompt the user before executing a generated
command line.

--no-run-if-empty, -r
--msax-chars=max-chars, -s
max-chars
--verbose, -t
--version
--exit, -x
--max-procs=max-procs, -P
max-procs

If the generated command line is empty, don't run


it.
Specify a maximum length for a command line.
Before executing the command, display it to
standard output.
Output the version number and exit.
Exit if the size specified by -s is exceeded.
Specify an upper limit of processes to be
simultaneously

Das könnte Ihnen auch gefallen