Está en la página 1de 75

Guía de programación de

scripts Bash

por Fernando Sosa Gil


Noviembre de 2005
¿Qué es la shell?

✔ Es el programa que interpreta las peticiones del usuario para ejecutar


programas.

✔ Hay muchas: /bin/sh, /bin/bash, /bin/csh...


(en MSDOS era command.com)

✔ Bash (Bourne-Again SHell) se ha convertido en el estándar de facto.


Inicio de bash
/bin/bash se ejecuta de 3 modos diferentes:

✔ Intérprete interactivo de ingreso: Tras hacer login en modo texto

• Ejecuta /etc/profile (vbles de entorno y funciones para todo el sistema)


• Ejecuta ~/.profile (específico del usuario, redefine variables
generalmente ejecuta ~/bashrc)

• Presenta el prompt

✔ Intérprete interactivo de no ingreso: Terminal en ventana gráfica

• Copia el entorno padre y luego ejecuta ~/.bash_rc


• Presenta el prompt

✔ Intérprete no interactivo: Al lanzar un script


Ciclo de vida de Bash

✔ Una vez presentado el prompt (que se puede cambiar en variable $PS1


generalemente en ~/bashrc), se queda a la espera de comandos

✔ Cuando se introduce un comando:


• Hace sustitución de variables
• Expande los metacaracteres
• Maneja redireccionamientos de entrada y salida y las tuberías
• Realiza la sustitución de comandos
• Ejecuta el comando, pasándolo al núcleo
• Cuando finaliza el programa vuelve a presentar el prompt
Documentación

✔ El comando más importante: man

✔ Internet. Esto es un resumen de “Advanced Bash-Scripting Guide”


http://www.tldp.org/LDP/abs/
Requisitos mínimos de un script
✔ Fichero textual con permisos de ejecución

✔ Primera línea del script (carácter Sha-bang #! )

#!/bin/bash

Esto no es obligatorio, pero facilita la cosas:


• Cuando ejecutemos el script, la shell detecta el caracter #! y lanza /
bin/bash para que procese el script.
• Nos asegura que siempre será ejecutado por bash, aunque nuestra
shell actual sea otra (csh, sh...)
✔ Cada lenguaje script indica su binario:
#!/usr/bin/perl

✔ Se ejecuta como cualquier otro comando


./script.sh
#!/bin/sh
# Comentario
# /bin/sh es enlace simbolico a /bin/bash en linux

comando1
comando2 \
comando_2_continúa
#podemos partir líneas con \

comando3;comando4
#los comandos se separan por fin de línea, o por ;
Variables y parámetros
✔ Reglas típicas: no comenzar por dígitos, no carácteres especiales, etc.

✔ Sólamente aparece sin el $ en:


• Asignaciones (=, read, cabeceras de bucles)
• Otros casos especiales (cuando es unset, exportada o señal)

✔ Empiezan por $ cuando son referenciadas. Bash interpreta el carácter $


como sustitución de la variable por su contenido

#!/bin/bash

variable=2
variable=$variable + 1
b=$variable
Reglas de sustitución de variables

✔ Los $ se interpretan en el interior de comillas dobles (partial quoting)

✔ Los $ no se interpretan en el interior de comillas simples (full quoting)

✔ Si $variable1 causa error de sintaxis, ${variable1} debería funcionar


Ejemplo de sustitución de variables
hello=”A B C”

Comando Salida Explicación


echo hello #hello (no se hace referencia a ninguna variable)

echo $hello #A B C (echo recibe A B C D, cuatro argumentos)

echo ${hello} #A B C (idéntico al anterior)

echo “$hello” #A B C (echo recibe un único argumento)

echo “${hello}” #A B C

echo '$hello' #$hello ($ se interpreta literalmente)

No es necesario declarar variables, pero existen declare y typeset. O también así:


variable1= #Declaración que inicializa a nulo
unset variable1 #Vuelta a nulo
Asignación de variables

✔ No puede haber espacios antes y después del =

vble1 =valor1 #Comando vble1 con argumento =valor1


vble1= valor1 #Comando valor1 cuya salida se asigna a la variable vble1

✔ Tipos de asignación

a=16+5 ; a=$b #Asignación normal


let a=16+5 #Asignación con let
for a in 7 8 9 10 #Cabeceras de bucles
echo -n “Dame la IP: “ ; read IP #Cláusula read
Tipos de variables

✔ Esencialmente, todas las variables son cadenas

✔ Dependiendo del contexto bash permite comparaciones y operaciones entre


ellas, siempre que sean dígitos
Argumentos de un script
./scriptname 1 2 3 4 5 6 7 8 9 10 11

✔ scriptname podrá manejarlos con las vbles:

$1,${10} Denotan cada parámetro según su posición


$* Denotan todos los parámetros separados por espacio
$@ Igual que el anterior pero cada parámetro entrecomillado
$# Número de argumentos pasados
$0 El nombre del script tal cual ha sido tecleado
basename $0 obtieen el nombre normal del fichero (sin path)
shift Comando que reasigna los argumentos perdiendo todos una posición:
$1<--$2, $2<--$3, $3<--$4, $4<--$5
Útil para recorrer los argumentos sin usar las llaves { }
Ejemplo: Script que crea una cuenta local de usuario,
usando como parámetros el usuario, contraseña y grupo

#!/bin/bash
# alta_usuario.sh

useradd $1 -s /bin/bash -g $3 -p $2 -d /home/$3/$1


cp -R /etc/skel /home/$3
mv /home/$3/skel /home/$3/$1
chown -R $1:$3 /home/$3/$1
chmod 700 /home/$3/$1

./alta_usuario.sh jsanchez2711 12345 alumnos


Entrecomillado \ “ '
➔ Entrecomillado de un carácter (Backslash \)

Anteponer un \ a un caracter dice a la shell que lo interprete literalmente. Es


similar a hacer un entrecomillado simple en un sólo carácter.

echo “\”Hello\”” #imprime “Hello”


echo “\$vble” #imprime $vble
echo “\\” #imprime \
echo 'i cant'\''t' #muestra i can´t

➔ Entrecomillado completo (comillas simples ')

No se realiza ninguna sutitución de variables ni se contemplan significados


especiales caracteres. Se toma la cadena literalmente. Excepto:
\ para poder escribir una comilla simple
echo 'I Can'\''t' #I Can't
➔ Entrecomillado parcial (comillas dobles “)

Evita el significado especial de todos los caracteres, excepto:


$ que inicia una sustitución de variable
“ que cerraría las comillas
' que abre un entrecomillado fuerte
\ que inicia entrecomillado de carácter
Ejemplos de entrecomillados
vble1=”una variable con 5 palabras”

COMMAND Esta es $vble1 #Ejecuta COMMAND con 7 argumentos


COMMAND “Esta es $vble1” #Ejecuta COMMAND con 1 argumento

vble2=””

COMMAND $vble2 $vble2 #Ejecuta COMMAND sin argumentos


COMMAND “$vble2” “$vble2” #Ejecuta COMMAND con 2 argumentos vacíos
COMMAND “$vble2 $vble2” #Ejecuta COMMAND con 1 arg (1 espacio)
Caracteres de escape

✔ Algunos comandos, como sed y echo, atribuyen significados especiales a


ciertos caracteres:

\n Nueva línea
\r Retorno de carro
\t Tabulación
\v Tabulación vertical
\b Espacio
\a Alerta (beep)
\0xx octal ASCII equivalente a 0xx

echo “\t\t\t” muestra \b\b\b literalmente


echo -e “\t\t\t” nuestra 3 tabulaciones (-e imprime caracteres de
escape)
echo $'\n' una forma de simular la opción -e
Sustitución de comandos
Con el acento grave (`) se ejecutan uno o varios comandos, y bash literalmente
pone la salida en otro contexto, como por ejemplo, asignándola a una variable,
como argumentos de un comando o como lista de en un bucle

✔ Forma clásica: Comillas invertidas


for i in `ls`

COMMAND `echo a b` 2 argumentos, a y b


COMMAND “`echo a b`” 1 argumento: “a b”
COMMAND `echo` No argumento
COMMAND “`echo`” Argumento vacío

✔ También se pueden usar $(comando)


a=$(ls -l) #Asigna el resultado de “ls -l” a la vble a
a=$(uname -m) #Asigna el resultado de uname -m a la vble a
REDIRECCIÓN DE E/S
Todo proceso abre 3 ficheros estándar:

✔ stdin (descriptor de fichero 0)


• El lugar desde el que el programa espera leer su entrada. Por
defecto es el teclado

✔ stdout (descriptor de fichero 1)


• El lugar donde el programa escribirá su salida. Por defecto es la
pantalla.

✔ stderr (descriptor de fichero 2)


• Es el lugar donde el programa escribe sus emnsajes de error. Po
defecto en la pantalla.

Estos y cualquier otro fichero pueden ser redirigidos.


Usualmente se redirigen stdout, stdin y stderr, combinados con los filtros:
find, cat, sort, grep, wc, cut
✔ Redireccionamiento de salida: De proceso a fichero
• La salida que cualquier comando genere en stdout, se puede
redireccionar a cualquier otro fichero:

ls -l > lista.txt #sobreescribe en caso de existir lista.txt


ls -l >> lista.txt #añade en caso de existir lista.txt

✔ Redireccionamiento de entrada: De fichero a proceso


• Cualquier comando que lea su entrada de stdin puede redireccionar su
entrada para que venga de otro fichero:

read a < fichero

✔ Redireccionamiento de la salida de errores


• Cualquier comando qu genere mensajes de error a stderr puede
redireccionar estos mensajes en otro fichero

ls -l 2> ls_errores
ls -l 2>> ls_errores
✔ Redireccionamiento de entrada y salida estándar

grep palabra < fichero_donde_buscar.txt > lineas_econtradas.txt

✔ Utilidades:
comando &> file #Redirige stderr y stdout
: > file #Crea un fichero vacío
: >> file #Crea un fichero vacío, o no hace nada si ya existe
Si se quiere vaciar un fichero, este método es el más eficiente (similar a touch si el
fichero no existe)

exec 3<> File #Abre el File para R/W asignándole el descriptor 3


i>&j #Redirige el descriptor i a j. Toda salida del fichero
apuntado por i se envía al fichero apuntado por j.
2>&1 Redirige los errores a stdout
TUBERÍAS
✔ Se utiliza para enlazar comandos. Aquí NO hay ficheros, se usa sólo entre
procesos.
✔ La salida de un comando se convierte en la entrada del siguiente.

cat alumnos.asc | sort | uniq | lp


Ejemplo

El fichero alums.asc contiene una línea:


12345,"Sanchez PERez ","Juan",24/11/1988,"1DA","1"

Contruir un login de usuario consistente en:


inicial_del_nombre + primer_apellido + dia_nacimiento +
mes_de_nacimiento

FILE=alums.asc

APES=`cut -f 2 -d, | cut -f2 -d\" | tr 'A-Z' 'a-z'`


NAME=`cut -f 3 -d, $FILE | cut -f2 -d\" | tr 'A-Z' 'a-z'`
FNAC=`cut -f 4 -d, $FILE | tr -d '/' | cut -c 1-4`

LOGIN=`echo "$NAME" | cut -c 1``echo "$APES" | cut -f1 -d" " `$FNAC
Exit y Exit Status
✔ exit: comando para terminar el script. Puede devolver un valor que será
entregadoa su script padre

✔ exit status: Todo comando ejecutado, al acabar devuelve un “exit status”


0 si terminó correctamente
no-cero en caso contrario

Este mecanismo se suele incorporar en las funciones y en nuestro propio script.


Si no se captura mediante asignación, se puede obtener con $?

echo hello
echo $? #Exit status 0

lalala
echo $? #devolverá no-cero, porque el comando no existe
condicionales: test, [], if/then
Operadores que evalúan la condición y devuelven 0 para true, y 1 para false

✔ test <condicional>
• Desde la linea de comandos se ejecuta /usr/bin/test, extensión de bash
• Desde un script es parte de sh-utils (no llama al binario anterior)

✔ [ <condicional>
• El corchete izquierdo es sinónimo de test, pero más eficiente.
• No tiene por qué cerrarse con ], pero generalmente ello incurre a error
por otras circunstancias ajenas al comando.

✔ [[ <condicional> ]]
• Método diferente de comparación, más intuitivo y parecido a los
lenguajes típicos. Más versátil y completo. Adaptado de ksh88
if/then
✔ Se suele combinar con alguno de las tres opciones anteriores para ejecutar
comandosen caso de que la comparación sea true o false

if test -z “$1” #True si hay argumentos


if /usr/bin/test -z “&1” #Mismo resultado, pero con “test” builtin
if [ -z “$1” ] #Funcionalmente idéntico
if [ -z “$1” #Debería funcionar, pero podría devolver error
if /usr/bin/[ -z “$1” ] #De nuevo, funcionalmente válido

✔ if/then también puede usarse con comandos directamente. En este caso más
que evaluar, simplemente devuelve su código de error.

if cmp a b &> /dev/null true si son idénticos (cmp devuelve 0)


if grep -q $USR /etc/passwd true si usuario encontrado
if [ 0 ] 0 es true
if [ 1 ] 1 es true
sintaxis común de if
if [ <condicion> ]
then
...
elif [ condicion2 ]
then
...
else
...
fi

Alternativa: (( condicion ))

✔ Ejecuta comparaciones aritméticas numéricas

#!/bin/bash
(( 4 > 2 ))
echo $? Devuelve 0, true
Operadores para testear ficheros
if [ -op ruta_del_fichero ]

-op Devuelve true si el fichero:


-e Existe
-s No tiene tamaño cero
-f Es regular
-d Es un directorio
-b Es un dispositivo de bloques(floppy, cdrom, etc.)
-c Es un dispositivo de caracteres (teclado, modem, etc.)
-p Es un tubería
-h Es un enlace simbólico (también -L)
-S Es un socket
-r Tiene permisos de lectura
-w, -x
-O Yo soy el propietario del fichero
-G Su grupo es el mismo que el mío
f1 -nt f2 f1 es más reciente que f2 (nt = newer than)
f1 -ot f2 (older than)
Comparación entre enteros (cadenas con dígitos)
if [ “$a” -eq “$b” ] es igual (equal)
if [ “$a” -ne “$b” ] no es igual (not equal)
if [ “$a” -gt “$b” ] mayor (greater than)
if [ “$a” -ge “$b” ] mayor o igual (graeter or equal)
if [ “$a” -lt “$b” ] menor (less than)
if [ “$a” -le “$b” ] menor o igual (less or equal)

Comparación entre cadenas


if [ “$a” = “$b” ] son iguales
if [ “$a” == “$b” ] son iguales
if [ “$a” != “$b” ] son diferentes
if [ “$a” \> “$b” ] mayor que, en orden alfabético ASCII, pero los
[]
necesitan código de escape
if [ “$a” \< “$b” ] menor que, en orden alfabético ASCII
-z la cadena es nula
-n la cadena no es nula
Composición de comparaciones
✔ Opción 1:
if [ exp1 -a exp2 ] #AND lógico
if [ exp1 -o exp2 ] #OR lógico

✔ Opción 2:
if [ exp1 ] && [ exp2 ] AND lógico
if [ exp1 ] || [ exp2 ] OR lógico

if [ -f /usr/bin/netscape -a -f /root/archivo.html ]; then


netscape /root/archivo.html &
fi

✔ ! niega el resultado de la comparación


If [ ! -e “$file” ]; then #si no existe el fichero
Operadores aritméticos

+ - * / Suma, resta, multiplicaciñon, división


** Potencia
% Módulo
+= Suma-incremento
-= *= /= %=

✔ Bash no entiende aritmética de punto flotante. Los decimales se interpretan


como cadenas
Operadores de bit
<< Desplazamiento hacia la izquierda
>> Desplazamiento hacia la derecha
& And
| Or
~ negación
! NOT
^ XOR

Constantes
let “decimal = 32”
let “octal = 032”
let “hexadecimal = 0x32”
let “binario = 2#1111001101”
let “base32 = 32#77”
Variables de entorno y especiales
✔ Al iniciar la shell, como todo proceso, se crea un entorno de variables.

✔ Se pueden modificar de forma permanente en /etc/profile, ~/.profile o


~/.bashrc

✔ Son visibles desde cualquier script

✔ Afectan al comportamiento de la shell y a la interfaz de usuario

✔ Espacio reservado para el entorno es limitado

✔ Se pueden cambiar con export, pero solo afectará a los procesos hijos
Algunas variables de entorno
$BASH Path del bash binario
$BASH_SUBSHELL Nivel de subshell
$EDITOR Editor por defecto
$FUNCNAME Nombre de la funciñon actual
$GROUPS Grupos del usuario actual
$HOME Home del usuario actual
$HOSTNAME
$PATH Ruta de binarios
$PWD Directorio actual
$OLDPWD Antiguo directorio
$SECONDS El número de segundos que lleva el script corriendo
$P1 Prompt principal
$P2 Prompt secundario
$PPID PID del proceso padre
$TMOUT Si no es cero, se hará logout tras ese número de segundos
$UID ID del usuario actual (el de root es cero)
Según la distribución y versión, algunas de estas variables pudieran no estar
definidas.
Algunas variables especiales
$! PID del último proceso corriendo en background
$_ Último argumento del previo comando ejecutado
$$ Pid del propio script actual
$*,$@,$1,$2, ${12}
Manipulación de cadenas
Multitud de diversas opciones para manipular cadenas

Longitud $(#cadena) expr length $cadena


Extraer Subcadenas: ${cadena:posicion} expr substr $cadena $pos
${cadena:posicion:longitud} expr substr ...
Posición de subcadena: expr match
Index: expr index
Borrar subcadena: ${cadena#subcadena}
Reemplazar: ${cadena/subcadena/reemplazo}
Reemplazar todas: ${cadena//subcadena/reemplazo}

Estas opciones son interesantes como alternativa a repetidas operaciones con


grep, sed, cut, tr, etc.
Referencias indirectas a variables

a=letra
letra=z

eval a=\$$a
echo $a #Devuelve z
for
for arg in <lista>
do
...
done

✔ Si <in list> es omitido, for usa automáticamente los parámetros pasados al


script o a la función.

✔ En <lista> puede ir cualquier lista de elementos:


for file in * ; do ...
for file in $(ls) ; do ...
for file in `ls` ; do ...

✔ Alternativas
for a in 1 2 3 4 5 6 7 8 9 10
for a in `1 step 10`
for ((a=1; a <= 10 ; a++)) #construcción similar a C
Ejemplo: En todos homes de los profesores hay que copiar el archivo /
usr/share/instituto/monitorprofe y llamarlo .monitorprofe. Si ya existe se
mantendrá, pero hay que asegurarse que la línea que define RetardoGH
sea RetardoGH=12
#!/bin/sh

archivo=/usr/share/instituto/monitorprofe

for i in `ls /home/profesor` ; do

if [ ! -f /home/profesor/$i/.monitorprofe ]; then
cp -f $archivo /home/profesor/$i/.monitorprofe
else
grep -v Retardo /home/profesor/$i/.monitorprofe > /tmp/tmpkk
echo 'RetardoGH="12"' >> /tmp/tmpkk
mv /tmp/tmpkk /home/profesor/$i/.monitorprofe
fi
chown $i:profesor /home/profesor/$i/.monitorprofe
done
while
while <condición>
do
...
done

Mientras la condición sea verdadera, se ejecuta el bloque

while [ “$a” -le $LIMIT ]; do ...

until
until <condición>
do
...
done
Mientras la condición sea falsa, se ejecuta el bloque
break y continue

✔ break: Termina el bucle. El programa sigue ejecutándose justo después del


“done” de ese bucle.

✔ Continue: Salta a la siguiente iteración del bucle. Admite como parámetro el


número de iteración.

for i in 1 2 3 4 5 6 7 8 9 10; do
if [ “$i” -eq 4 ]; then
continue 2
fi
echo -n “$i “
done
#Salida con continue 2: 1 2 3 2 3 2 3 2 3...
#Salida con continue: 1 2 3 5 6 7 8 9 10
case
case “$variable” in
“$condicion1”) ...
;;
“$condicion2”) ...
;;
* ) ...
;;
esac
ejemplo de case
Script que acepta parámetros tipo: script.sh --h --conf archivo
while [ $# -gt 0 ]; do
case “$1” in
-h|--help)
echo “Mostrar ayuda”
;;
-c|--conf)
CONF_FILE=$2
shift
;;
-d|--debug)
DEBUG=1
;;
*) echo “Parámetro no reconocido”;;
esac

shift
done
select
select variable [in list]
do
....
break
done

✔ Si [in list] es omitido, select usa automáticamente lso parámetros pasados al


script o a la función.

✔ Es un caso aislado de for


EXPRESIONES REGULARES
✔ Usadas principalmente por grep, sed y awk

* Cualquier caracter o grupo de caracteres, incluída la cadena vacía


“1133*” Coincide con 1133 seguida de cualquier cadena, incluida la vacía.
. Cualquier carácter, excepto nueva línea
? Cualquier carácter, o ninguno
^ Principio de línea (aunque también puede usarse para negar)
$ Al final de una expresión regular, indica fin de línea
Ejemplo: “^$” indica líneas vacías

Caracteres y rango de caracteres [ ]


“[xzy]” Cualquiera de estos 3 caracteres
“[c-n]” Cualquier carácter de la c a la n
“[a-z0-9]” Cualquier minúscula o dígito
“[^b-d]” Cualquier carácter que NO estén en el rango b-d
“[Yy][Ee][Ss]” Acepta YES, Yes, yes, yeS,...
FUNCIONES
✔ Dos opciones:
function nombre { nombre() {
... ...
} }
La segunda opciones es más portable

✔ Las variables locales tienen que ser declaradas con “local”. En caso
contrario son “vistas” desde fuera de la función (si la función ya se ha
ejecutado)

func () {
vble=37
}
echo “$vble” #No se imprime nada
func
echo “$vble” #imprime 37. Si fuera local no imprimiría nada
✔ Se admite la recursión
ALIAS
✔ Son simples abreviaturas para acortar comandos.
✔ Común encontrarse algunos en el script ~/.bashrc

alias rm=”rm -i” #Por defecto, rm pedirá confirmación


unalias rm

✔ Su uso se suele limitar a estos casos, ya que en los scripts no tienen la


potencia de otros recursos en principio parecidos (como las macros en C,
que permiten recursividad).
Listas lógicas con comandos
✔ Los operadores && y || no tienen por qué usarse sólo con condiciones,
también pueden admitir comandos.
✔ Son conocidas como “and list” y “or list”. Permiten ejecutar comandos
consecutivamente, con un carácter lógico.

Comando1 && comando2 && comando3


• Se ejecutan por orden. Cada uno se ejecuta si se recibe del comando
anterior un valor verdadero (cero).

[ ! -z “$1” ] && echo “Falta el argumento 1” && exit 1


Si se ha pasado un argumento, el echo no se llegará a ejecutar.

Comando1 || comando2 || comando3


• Se ejecutan por orden, a la espera que cada uno reciba del comando
anterior un valor false. Si alguno produce un verdadero, no se ejecutan los
siguientes comandos.
ARRAYS
✔ No tienen que declarase, ni son posiciones contiguas, sólo 1 dimensión

• Asignarlas posición a posición


area[11]=23
echo ${area[11]} #Para acceder al dato se usan corchetes

• Asignarlas en una sola línea


area= ( [11]=once [17]=diecisiete )

• Asignarlas tomando las posiciones por defecto (a modo de enumeración)


numeros=( cero uno dos tres )
echo ${numeros[0]} #imprimirá cero

✔ algunas operaciones (recordar que todos los datos son cadenas)


${#array[0]} #longitud del primer elemento
${#array[@]} #Número de elementos en array
${#array[@]:2} #Array completo desde el tercero al final
De forma similar hay caracteres especiales para reemplazar, eliminar, buscar, etc.
Debugging
✔ No hay comandos en bash para depurar el código.
✔ Habrá que conformarse con echo's y mensajes crípticos de error.

• Ejemplos de error

a=37
if [$a -gt 27 ]; then #Produce: [37 command not found
echo $a
fi
exit 0

#Borrar ficheros en cuyo nombre tengan un espacio


badname=`ls | grep ' '`
rm “$badname”
exit 0
En este caso sobran las comillas en rm, para que rm reciba todos los argumentos,
no solo 1. Mejor: rm *” “*
rm *\ *
Depurando con echo
✔ Una forma de activar/desactivar echo's a lo largo del código.

##/root/utils/debecho.sh (debug-echo)
##Hará echo del parámetro pasado, si se ha definido la variable DEBUG
debecho () {
if [ -z “$DEBUG” ]; then
echo “$1” >&2 #canal de errores
fi
}

✔ De esta forma se pueden poner debecho's a lo largo del código, y


activarlos/desactivarlos con solo definir o no-definir DEBUG con algún valor.
#!/bin/bash
. /root/utils/debecho.sh #similar a include en c (punto y espacio)
DEBUG=1
debecho “$variable” #si no definimos
Depurando con opciones de script
✔ Bash admite opciones para ejecutar un script. En este caso son interesantes
2 opciones:

verbose: hace echo de todas las líneas antes de ejecutarlas


xtrace: igual que el anteriro, pero con los comandos expandidas

A - Desde la línea de comandos:


bash -o verbose script.sh (abreviando: bash -v script.sh)
bash -o xtrace script.sh (abreviando: bash -x script.sh)

B - En el sha-bang:
#!/bin/bash -x

C - Activarlas/desactivarlas en el mismo código:


set -o verbose #también set -v
...
set +o verbose #desactiva la opcion (también set +v)
Comandos internos
✔ Comandos que pertenecen a Bash
✔ Son más rápidos que programas externos (Bash suele lanzar los comandos
externos en procesos hijos a través de fork)
✔ Lso comandos builtin suelen tener un comando externo del mismo nombre,
pero en realidad Bash los implementa internamente.

Hay muchos comandos internos.

I/O
echo
printf
read

Filesystem
cd
pwd
pushd, popd (a modo de pila-bookmark de directorios)
dirs (lista el contenido de la pila anterior)

variables
let <operacion_aritmética>
eval <condición_lógica>
set <asignación>
unset
export
declare, typeset, readonly
getopts (manejar argumentos de forma avanzada)

scripts
., source (Similar a #include en C)
exit
exec (ejecuta sin fork, pero fuerza un exit al acabar)

commands
true
false

control de tareas
jobs (lista las tareas ejecutándose en background y sus
identificadores, NO es tan útil como ps)
disown (Elimina una tarea)
kill (fuerza la eliminación)
fg, bg (manda una tarea a primer o segundo plano)
wait
supend (similar a control-Z)
logout
Comandos externos

Típicos
man,ls,cat
tac invierte el orden de los caracteres
rev invierte el orden de las lineas
cp,mv,rm copiar, mover, borrar ficheros o directorios
Muy común cp -f y rm -f para evitar confirmación en scripts
rmdir,mkdir borrar y crear directoriso vacíos
mkdir -p /a/b/c crea toda la ruta si no existe (p de parents)
chmod cambia permisos
chattr cambia atributos. Especialmente importante
chattr +i fichero
Hace al fichero inmutable: no puede modificarse, linkearse, borrarse, ni si quiera
por root. Este mecanismo es usado actualmente con gnome.conf para que no se
pueda hacer loguin gráfico en un equipo ni aún sabiendo la clave de root.
La solución es entrar por ssh y hacerle chattr -i
ln -s
Comandos más complejos

find
xargs
expr

Hora y Fecha
date
zdump
time
touch
at
batch
cal
sleep
usleep
hwclock, clock
Procesado de Texto

sort
tsort
uniq
cut
paste
join
head
tail
grep
look
sed
awk
wc
tr
fold
fmt
col
column
colrm
nl
...

comandos de fichero
tar
gzip
bzip2
cpio
file
which
whereis
whatis
locate, slocate
diff
cmp
basename
dirname
sum, cksum, md5sum
crypt
more, less

redes
host
traceroute
ping
whois
finger
vrfy

acceso remoto
ftp
telnet
wget
lynx
rlogin
rsh, ssh
rcp, scp
rsync
mail

Misceláneo
clear
factor
bc
dc
jot, seq
banner
lp
tee
dd
units
dialog
Comandos de Administración
✔ Usualmente son lanzados por root (Ejemplos en /etc/rc.d/ )

USUARIOS Y GRUPOS (ver add_nuevos_alumnos.sh)

users Muestra todos los usuarios logueados (como who -q)


groups Grupos al que pertenece el usuario actual
chown, chgrp Cambia propietario y grupo de un fichero
useradd Crear usuarios
userdel Borrar usuarios
usermod Modifica usuarios
groupmod Modifica grupos
id lista Ids del usuario y grupos asociados al proceso actual
who Muestra todos los usuarios logueados en el sistema
w Muestra usuariso loguedos y procesos que dependen de él
Usuarios logueados que hayan iniciado X: w | grep startx
quota Muestra cuotas de usuario o de grupo
setquota Fija una cuota de usuario o de grupo
umask Máscara de permisos por defecto al crear un fichero
logname muestra el logname. Similar a whoami
su El usuario actual pasa a ser root u otro usuario
En los intitutos “su” está eliminado, pero existe sudo
sudo Ejecuta un programa como root u otro usuario (/etc/sudoers)
sudo cp /root/secretfile /home/nando
passwd Cambia, fija y maneja contraseñas de usuario
echo “$nuevapassword” | passwd --stdin
last Lista los últimos usuarios logueados
Extracto de código de add_nuevos_alumnos.sh

PASS=12345; APES="sanchez perez"; NAME="juan"; FNAC="27/11"


GRUP="D1A"; USER=jsanchez2711

#GRUPO
if ! grep $GRUP /etc/group > kk; then
groupadd $GRUP
mkdir -p /home/aulas/$GRUP
chown -R root:$GRUP /home/aulas/$GRUP
chmod 775 /home/aulas/$GRUP
fi
#USUARIO
if [ ! -d /home/alumnos/$USER ]; then
echo -n "Creando $USER en grupo $GRUP ..."
E_PASS=`mkpasswd -S "GV" $PASS`
./alta_usuario.sh $USER $E_PASS alumnos
usermod -G $GRUP,alumnos -c "$NAME $APES" $USER
setquota $USER $ALUM_QUOTA $ALUM_QUOTA 0 0 /home
TERMINALES
tty Muestra la ruta del terminal actual
mesg Activa/desactiva la recepción de mensajes al terminal actual
wall Manda un mensaje al terminal de todos los usuariso logueados
dmesg Muestra todos los mensajes del sistema desde el arranque.
Útil combinarlo con grep para hallar dispositivos usb, etc.
dmesg -c #borra todos los mensajes tras mostrarlos
dmesg | grep USB

ESTADÍSTICAS E INFO
uname Muestra especificaciones de sistea oeprativo, núcleo, etc.
lastcomm Muestra información de comandos previos lanzados por usuarios
lastlog Muestro la fecha/hora del último loguin de cada usuario
lsof Lista ficheros abiertos
strace Herramienta para diagnosticar y depurar comandos
nmap Escáner de puertos de red
nmap 172.x.x.2 | grep ftp #21/tcp open ftp
free -m Muestra memoria y caché usada en megabytes
procinfo Extrae extensa información de /proc
lsdev lista los dispositivos
du Espacio de disco usado por archivos, directorios o discos
df Epacio usado por los sistemas de ficheros
stat Detalladas estadístics de un fichero
vmstat Estadístics de memoria virtual
netstat Información de la red
uptime tiempo que lleva el sistema corriendo
hostname nombre del host actual
hostname -s Dominio

LOGS
logger Añade el mensaje pasado a /var/log/messages
logrotate Utilidad para rotar, comprimir, borrar, etc todo lo referido a
/var/log. Configuracion en /etc/logrotate.conf
CONTROL DE TRABAJO

ps Procesos actuales y estadísticas.


ps -A | grep dnsmasq #está corriendo dnsmasq?
fuser Muestra los procesos que están accediendo a un fichero,
directorio o dispositivo. Con la opción -k los elimina.
Muy útil cuando no podemos desmontar, por ejemplo un usb,
porque está ocupa (busy error).
fuser -um /dev/sda1
#/dev/sda1 1772(nando)
kill -9 1772
pstree Procesos en estructura de árbol
top Datos de los procsos que más uso hacen de cpu
nohup Mantiene un comando ejecutándose aún después del logout
pidof Muestra el pid de un proceso
cron Programador de tareas. /etc/crontab
CONTROL DE PROCESOS Y ARRANQUE

init comando padre de todos los procesos. Determina el nivel de


ejecución del sistema:
0 : halt
1 : monousurio
2-5: multiusuario
6 : reboot
Esto está definido en /etc/inittab
runlevel Muestra el nivel de ejecución actual
halt, reboot Apaga, reinicia el equipo
shutdown shutdown -h now # lo mismo que halt
shutdown -r 12:00 # reboot a las 12

RED
ifconfig Configuración de red
iwconfig configuración de red inalámbrica
route Tabla de rutas del kernel (obtener la puerta de enlace)
chkconfig Chequea la configuración de red
tcpdump Sniffer de paquetes de red
SISTEMA DE FICHEROS
mount, umount Montar/desmontar un sistema de ficheros. /etc/fstab
sync Sincroniza posibles buffers con el dico duro. Útil ejecutarlo
para asegurarse que una copia de ficheros ha finalizado
mkswap Crea una partición swap o fichero swap
swapon, swapoff Activa/desativa un espacio swap
mke2fs ,mkntfs Crear sistemas de ficheros: ext2, ntfs
dump2fs Lista información del sistema de ficheros
hdparm Muestra o cambia parámetros del disco duro
fdisk gestor de particiones
fsck, e2fsck, debugfs Cheaquea, repara y deputa sistemas de ficheros
badblocks Busca sectores dañados en un dispositivo
mkboot Crea disco de arranque
chroot Cambia el directorio de root
mknod Crea archivos de dispositivos. Generalmente necesesario
cuando se añade nuevo hardware
mkntfs Crea sistema de ficheros ntfs
MAKEDEV Utilidad similar a mknod, más fácil de usar
tmpwach Borra ficheros no accedidos en un periodo de tiempo
BACKUP
dump, restore Crea y restaura copias de seguridad

#copia_servidor.sh 0
if [ $1 ]; then
dump $1'uf' /dev/nst0 /
dump $1'uf' /dev/nst0 /boot
dump $1'uf' /dev/nst0 /usr
dump $1'uf' /dev/nst0 /var
dump $1'uf' /dev/nst0 /home
if [ $1 = 4 ]; then
mt -f /dev/nst0 rewind
mt -f /dev/nst0 offline
fi
else
echo "se necesita un parámetro"
fi
MODULOS

modconf Utilidad interactiva para manejar los módulos


lsmod Muestro los módulos instalados en el núcleo
modprobe Carga un módulo
insmod Fuerza cargar un módulo
rmmod Fuerza desinstalar un módulo
depmod Crea archivo de depencias del módulo
modinfo Muestra información de un módulo

Forzar que se cargue un módulo:


echo 8139too >> /etc/modules

Impedir que se cargue un módulo (blacklisted):


echo ich2rom >> /etc/hotplug/blacklist
MISCELÁNEO

ldd muestra las dependencias de librerías de un ejecutable


watch Ejecuta un comando repetidamente a intervalos de tiempo
Compilación en programas c
✔ Compilar código c: (apt-get install gcc)
gcc archivo.c -o archivo_ejecutable

• archivo_ejecutable ya puede ejecutarse como un comando más

✔ Depurar errores en tiempo de ejecución

gcc -g archivo.c -o archivo_ejecutable


• La opción -g añade al ejecutable información que puede manejar el
debugger

gdb archivo_ejecutable
• Esto nos abrirá una sesión de debugger. A través de comandos como list,
run, print, podemos localizar la línea que genera el fallo en tiempo de
ejecución
Python
✔ Lenguaje GPL, orientado a objetos y de propósito general
✔ Multiplataforma, pero especialmente en Linux y Macs
✔ Muy usado en herramientas y en web por su sencillez

✔ Es interpretado ==> no hay necesidad de compilar código en Python antes


de ejecutarlo.

✔ El código (.py) es “compilado” a bytecode (*.pyc) cada vez que es ejecutado


por la máquina virtual de python.

✔ Paquetes necesarios: apt-get install python

También podría gustarte