IV Jornadas Sistema Operativo Linux
Programando Scripts en Bourne Shell
Andrés J. Díaz <
[email protected]> ¿<
[email protected]>?
¿Qué es un Shell?
Definición técnica:
«El shell es una parte del SO encargada de validar los comandos introducidos por parte del
usuario, para posteriormente enviar las órdenes a otra parte del sistema operativo para su ejecuci
ón.»
Definición «cutre»:
El programita que traduce lo que tecleamos en cosas que entienda el sistema operativo.
¿Qué es un Shell tipo Bourne?
Tipos de shell en UNIX:
Bourne (sh)
Stephen Bourne 1979
C (csh)
Bill Joy 1980
Korn (ksh)
David Korn 1980
¡Y Bash!
«Bourne Again Shell» (Otro shell Bourne)
Proyecto GNU
Estándar IEEE POSIX
El Bourne Shell
Dos estilos de Shell Bourne:
Estilo BSD
Estilo SysV
Pero con POCAS diferencias:
BSD:
echo -n "sinretornodelinea"
SysV:
echo "sinretornodelinea\c"
El C Shell
Novedades
Mejoras en interactividad
Expansión de tildes (~)
Expansión de llaves ({a,b,...,n})
Builtins: pushd, popd, logout...
Además...
¡Creador de VI!
Bill Joy, Univ. de Berkeley (1980)
El Shell de Korn
Novedades
Expresiones aritméticas
Historial de comandos
Más expansiones de parámetros
Vectores («Arrays»)
Alias
Variables enteras
David Korn, Bell Labs (1957)
Bourne Again Shell (BASH)
¿Otro shell?
Proyecto GNU, por lo tanto libre
Mejoras de csh y de ksh
Más funcionalidad
for aritmético: for ((expr1; expr2; expr3)); do list; done
Mejoras con respecto a Korn Shell (ksh88)
de acuerdo con POSIX
«tilde expansion»
sustitución de procesos con tuberías
expansión del «prompt»
«!»: extensión de historial del estilo csh
«**»: operador de exponenciación
«Arrays» de tamaño ilimitado
redirección: &> (stdout y stderr), <<<, [n]<&palabra-, [n]>&palabra-
¿Por qué un Shell tipo Bourne?
Creado para ser programable
Programación estructurada
Muy mejorado con BASH
Está más extendido
Csh NO es un buen shell de programación
Es mucho más cómodo :-)
Posee estructuras de control «builtin»
Sentencias de bifurcación (if, case ...)
Bucles (for, while ...)
Diferentes tipos de variables
y... ¡Funciones!
¿Por qué NO CSH?
No soporta descriptores directos a ficheros:
BASH: cmd 2>/dev/null
CSH: (cmd > /dev/tty) >& /dev/null
Ortogonalidad de comandos (i.e. sleep 1 |while)
BASH: espera por un «do ... done»
CSH: error en while y se procesa ¿sleep |?
Espupideces varias sin nombre científico ;-)
% kill -1 ‘cat foo‘
ERROR!!!! --> ‘cat foo‘: Ambiguous.
% /bin/kill -1 ‘cat foo‘
¡¡¡¡¿¿¿¿¿OK?????!!!!
¿Para qué programar en Shell?
Nos ayuda en nuestra vida diaria :-)
Evitar la repetición sistemática de comandos
Personalizar utilidades
Por pura comodidad
Crear utilidades automáticas que hagan labores de mantenimiento o instalación
Autodetección de hardware
Para trastear un poco
Meterse con los que usan Perl para hacer trivialidades ;-)
Juegos para BOFHs (expulsar usuarios...)
Sentencias y comandos
Ejecutar comandos
Llamada directa al ejecutable (/bin/ls o ls si está en el PATH)
Usando un alias (alias ll=’ls -l’)
Mediante una variables (LS=/bin/ls; $LS)
Separar comandos
Cada línea un comando
En la misma línea separado por punto y coma (;)
Comandos y expresiones
Listas de comandos
En el propio entorno shell: { comando1; comando2; ...; comando n }
En un subshell: ( comando1; comando2; ...; comando n )
Expresiones Aritméticas
variable=$(( expresión ))
(( expresión ))
variable=$[ expresión ](¡NO!)
Expresiones Condicionales
[[ expresión ]]
[ expresión ]
test expresión
«Builtins» versus Comandos
Diferencias:
Comandos son ejecutables independientes del shell
Builtins con funciones propias de shell
Builtins:
Evalúa expresiones
Evaluación aritmética
Sentencia vacía
Lee y ejecuta ficheros
(( ))
[[ ]]
:
.
Expresiones Aritméticas (I)
var++ var--
Post-incremento y post-decremento
++var --var
Pre-incremento y pre-decremento
- +
Signos negativos y positivos
! ~
Negación lógica y bit a bit
**
Exponenciación
* / %
Producto, división y módulo
+ -
Suma y resta aritmética
Expresiones Aritméticas (II)
Igualdad y no igualdad
<< >>
Desplazamiento de bits
<= >= < >
Comparaciones lógicas
== !=
&
Y binario (AND)
^
O-Exclusivo binario (XOR)
|
O binario (OR)
&&
Y Lógico
Expresiones Aritméticas (y III)
||
O Lógico
?:
Evaluación condicional («si en línea»)
= *= /= %= += -= <<= >>= &= ^= |=
Asignación
,
Separador de sentencias
[base#]n
0xn, 0Xn
0n
Indicador de base numérica
i.e: 16#f --> 15
Indicador de base hexadecimal
Indicador de base octal
Comparaciones (I)
Numéricas:
[ $a -eq 1 ] --> a = 1
[ $a -ne 1 ] --> a <> 1
[ $a -lt 1 ] --> a < 1
[ $a -gt 1 ] --> a > 1
[ $a -le 1 ] --> a <= 1
[ $a -ge 1 ] --> a >= 1
Cadenas:
[ $a = ’hola’ ] --> a = «hola»
[ $a != ’hola’] -> a <> «hola»
[ -z $a ] -------> a = «»
[ -n $a ] -------> a <> «»
[ $a ] ----------> a <> «»
Comparaciones (y II)
Ficheros:
[ a -ef b ] --> el fichero «a» tiene el mismo dispositivo e inodos que «b»
[ a -nt b ] --> «a» es más moderno que «b»
[ a -ot b ] --> «a» es más antiguo que «b»
[ -b fich ] --> «fich» existe y es un fichero especial de bloques
[ -c fich ] --> «fich» existe y es un fichero especial de carácteres
[ -d fich ] --> «fich» existe y es un directorio
[ -e fich ] --> «fich» simplemente existe :-)
[ -f fich ] --> «fich» existe y es un fichero regular
[ -h fich ] --> «fich» existe y es un enlace simbólico
[ -p fich ] --> «fich» existe y es una tubería
[ -r fich ] --> «fich» existe y tiene permisos de lectura
[ -w fich ] --> «fich» existe y tiene permisos de escritura
[ -x fich ] --> «fich» existe y tiene permisos de ejecución
Variables (I)
Características:
No hay tipos de contenido «variables comunistas» :-)
Locales al script, a menos que se exporten
Se accede a su contenido con el símbolo dólar ($)
Identificador «¡CASE SENSITIVE!»
Por convenio en mayúsculas si se exportan
Hay variables «especiales»
Realmente $ expande un parámetro, no son variables en el sentido estricto.
Asignación:
VARIABLE=valor
VARIABLE=’valor’ (no se expande el contenido de valor)
VARIABLE="valor" (se expande el contenido de valor)
Acceso:
$VARIABLE
Variables (II)
La sentencia «declare»:
declara variables con ciertos atributos:
exportables: declare -x VARIABLE=valor
sólo lectura: declare -r VARIABLE=valor
vectores (arrays): declare -a VARIABLE=valor
análoga a la antigua «typeset»
La sentencia «export»
export VARIABLE[=valor]
exporta una variable al entorno padre
accesible desde el shell que invocó el script
igual que declare -x
Variables (III)
«export» exporta la variable desde el shell o subshell al
entorno
padre.
Variables (IV)
Variables Especiales:
$$ --> PID del script actual
$_ --> PID del shell padre
$? --> Valor de retorno de la última ejecución
$# --> Número de argumentos
$! --> PID del último trabajo en segundo plano
$0 --> Nombre de la llamada al script
$1, $2, ..., $n --> Argumentos
$@, $* --> Todos los argumentos
PS1,PS2...Pn --> Prompts :-)
Variables (y V)
Expresión de parámetros:
${parametro} --> Análogo a $parámetro(DEMO)
${parametro:-valor} --> Si parametro es vacío, devuelve valor
${parametro:+valor} --> Si parametro es no vacío, devuelve valor
${parametro:=valor} --> Si parametro es vacío, le asigna y devuelve valor
${parametro:?[valor]} --> Si parametro es vacío, muestra el mensaje de error valor
Sustitución de comandos
‘comandante‘ --> ejecuta el comando cuyo nombre es el devuelto por comandante(DEMO)
$(comandante) -> Ídem
$(cat fichero) <=> $(< fichero)
Patrones
¿Qué es un patrón?
Una expresión que engloba un contenido variado
Al expandirse se consigue todos los comandos que engloba
Similar a los conocidos «comodines»
El carácter nulo nunca puede ser expandido
Los caráceteres que constituyen un patrón deben ser expandidos si no se quieren interpretar
como tales.
Patrones en Bourne (y Csh):(DEMO)
? --> El interrogante simboliza cualquier carácter, pero sólo uno.
* --> El asterisco simboliza una ristra de cualquier longitud y de cualquier carácter
[...] --> Simboliza al menos uno de los carácteres encorchetados
¡¡{...} NO ES UN PATRÓN!!
Redirección (I)
Salida estándar
comando > fichero
Entrada estándar
comando < fichero
En general:
comando [n]>{&n | fichero]
Podemos redirigir a
descriptor de fichero (i.e dispositivo)
fichero
Redirección (II)
Descriptores de fichero
0 --> Entrada estándar
1 --> Salida estándar
2 --> Salida de errores estándar
/dev/fd/n --> dirige al descriptor «n»
/dev/stdin --> Análogo a 0
/dev/stdout --> Análogo a 1
/dev/stderr --> Análogo a 2
/dev/tcp/host/puerto --> redirige a la conexión establec
Comentarios de: Programando Scripts en Bourne Shell (0)
No hay comentarios