Práctica 2 - Línea de Comandos II#

Continuamos con el trabajo que hemos hecho en la práctica 1, profundizando un poco más en el manejo de la línea de órdenes. En esta ocasión veremos cómo agrupar comandos para crear scripts y así automatizar tareas. También cómo utilizar unas técnicas muy potentes para agrupar funcionalidad entre comandos como son las redirecciones y las tuberías. Finalmente, veremos como instalar nuevos programas utilizando el gestor de paquetes de Debian.

Scripts#

Una de las características más importantes de la línea de comandos es que todo lo que se hace sobre ella se puede almacenar en un archivo y ejecutarlo tantas veces como se quiera. La propia línea de órdenes acepta como entrada todo un lenguaje de programación (con sus sentencias if, bucles for etc.), lo que permite automatizar tareas a todos los niveles. A estos programas que contienen un conjunto de órdenes que se ejecuta de una vez se les conoce como scripts.

Vamos a ver cómo crear scripts muy sencillos desde el terminal.

Editando archivos con nano#

Para crear un archivo nuevo, simplemente tienes que pasar la ruta dónde quieras almacenarlo. Por ejemplo:

nano my-file.txt

Puedes escribir texto y, cuando quieras, puedes salvarlo a disco utilizando Ctrl o. Pedirá confirmación sobre el nombre de archivo, que será el mismo que has dado, y aceptas con Enter. Con ello, el archivo quedará almacenado.

Para salir del editor, sólo tienes que usar Ctrl x. Si no guardaste, te pedirá si quieres salir sin guardar o guardar los cambios actuales.

Nota

Con Ctrl g puedes ver todos los atajos de teclado que permite nano. En particular, son interesantes Ctrl k y Ctrl u que permiten cortar y pegar una línea, respectivamente.

Editando archivos con gedit#

También hay editores de texto plano gráficos como gedit. Puedes lanzarlo desde el terminal simplemente utilizando el comando gedit.

Advertencia

Aunque los editores gráficos son más fáciles de usar, te recomendamos que te habitúes a utilizar editores como nano ya que son editores que están presentes en muchos hardware de red como routers de los cuales no dispondrás de interfaz gráfica. Además, suele ser mucho más rápido editar pequeños cambios con este tipo de herramientas que con las alternativas gráficas.

Ejercicio: crea un script#

Ahora que sabes cómo crear un archivo de texto, puedes crear scripts y ejecutarlos. Por ejemplo, crea el archivo /home/alumno/my-script.sh con el siguiente contenido:

#!/bin/bash

echo "-- Deployer v1.0 --"

# First, create all directories
mkdir dir1 dir2 dir3

# Then, copy myself into these directories
cp /home/alumno/my-script.sh dir1
cp /home/alumno/my-script.sh dir2
cp /home/alumno/my-script.sh dir3

echo "-- All done! --"

El script es bastante sencillo de entender. Algunas cuestiones nuevas son:

  • La línea #!/bin/bash que siempre se pone al principio se conoce como shebang. Esa primera línea tiene que empezar con #! seguida del intérprete que quieras utilizar. En este ejemplo, usamos Bash.

  • El comando echo sirve para imprimir cadenas de caracteres por la salida estándar.

  • Las líneas que empiezan con # se consideran comentarios, por lo que el intérprete las ignora.

Para ejecutar el nuevo script puedes hacer:

bash /home/alumno/my-script.sh

También es muy común darle permisos de ejecución:

chmod +x /home/alumno/my-script.sh

y, posteriormente, ya se puede lanzar únicamente dado la ruta al script:

/home/alumno/my-script.sh

O si estás en /home/alumno:

./my-script.sh

Nota

Como ejercicio, crea un script que borre todo lo que este script genera.

Buscando con grep y find#

Una de las tareas más recurrentes es buscar en los archivos y directorios. grep es un comando muy potente para buscar patrones en contenido de archivos. find, por su parte, es un comando para encontrar archivos y directorios cuyo nombre satisfaga un patrón determinado.

La estructura principal de grep es:

grep [OPTIONS] PATTERN [FILE FILE ...]

El argumento PATTERN es la cadena que quieras buscar. Esta cadena puede ser simplemente una palabra o incluso una expresión regular la cual nos permite definir patrones genéricos. Veamos algunos ejemplos sencillos:

grep auto /etc/network/interfaces
grep -i AuTo /etc/network/interfaces
grep -i AuTo --color /etc/network/interfaces
grep -i AuTo --color -H /etc/network/interfaces
grep -i AuTo --color -RH /etc/network

Por su parte, la estructura principal de find es:

find [STARTING-POINT] [OPTIONS]

Donde STARTING-POINT es la ruta desde donde se tiene que empezar a buscar archivos. En OPTIONS tienes todo tipo de filtros por lo que puedes afinar nuestra búsqueda (por nombre, por tamaño, por tipo, etc.). Estos son algunos ejemplos:

find
find /usr/bin
find /usr/bin -type f
find /usr/bin -type f -perm 755
find /usr/bin -type f -perm 755 -size +100k
find /usr/bin -type f -perm 755 -size +100k -mtime +100

Redirecciones#

Como hemos dicho, los comandos son programas. Y los programas, al ejecutarse, crean procesos de ejecución. En un sistema GNU/Linux, un proceso tiene 3 puntos por los cuales puede comunicarse con el exterior. Por defecto, a todo proceso se le asigna estos descriptores de archivo:

../_images/redirection.drawio.png

Figura 2 Descriptores de archivo por defecto de un comando.#

  • stdin o entrada estándar, por donde el comando puede recibir información. Por defecto, la entrada estándar es el teclado.

  • stdout o salida estándar, por donde el comando produce su salida. Por defecto, la salida estándar es la propia línea de órdenes.

  • stderr o salida de error estándar, por donde el comando puede emitir mensajes de error o de depuración. Por defecto, también es la propia línea de comandos.

Nota

La salida estándar y la de error se separan, fundamentalmente, para distinguir qué partes deben ser tomadas como puramente salidas del comando de los mensajes de error. Esto es muy importante cuando utilizamos redirección o tuberías.

En GNU/Linux, es posible cambiar a los sitios que apuntan estos descriptores de archivo de los comandos. Para ello, se utilizan los siguientes operadores:

  • cmd > file.txt: redirige la salida del comando cmd en el fichero file.txt.

    • Si el fichero no existe, se crea.

    • Si el fichero existe, se reescribe completamente.

    cat /etc/fstab > my-fstab.txt
    echo "Hello!" > greetings
    echo "World!" > greetings
    

    Nota

    Existe un fichero especial a donde va a parar todo lo que no se quiere almacenar: /dev/null. Es muy común redirigir la salida de comandos a este fichero para ignorar la misma.

  • cmd >> file.txt: redirige la salida del comando cmd en el fichero file.txt.

    • Si el fichero no existe, se crea.

    • Si el fichero existe, la salida se añade al final del archivo.

    cat /etc/fstab > my-fstab.txt
    echo "# this goes at the end!" >> my-fstab.txt
    
  • cmd < file.txt: redirige la entrada estándar del comando cmd de forma que file.txt sea su entrada y no el teclado.

    cat < /etc/fstab
    

Ejercicios#

  1. Almacena en el archivo libs.txt los archivos (de forma recursiva) que terminen por .so desde el directorio /usr/lib.

    Solución
    find /usr/lib -type f -name *.so > libs.txt
    cat libs.txt
    
  2. Añade al final del mismo archivo aquellos que terminen en .a.

    Solución
    find /usr/lib -type f -name *.a >> libs.txt
    cat libs.txt
    

Nota

Por simplicidad, no se menciona cómo manipular la salida de error, pero también es posible redirigirla como los otros dos.

Tuberías#

Las tuberías son, probablemente, la característica más atractiva de un entorno de línea de órdenes en GNU/Linux. Proporciona la capacidad de realizar tareas no triviales de una forma sencilla, simple y clara.

El concepto parte de lo que se ha visto en redireccionamiento, donde se vio que todos los comandos tenían una entrada y una salida que se podía manipular. El operador de tubería (denotado con la barra vertical |) conecta la salida de un comando con la entrada de otro. De esta forma, se pueden unir comandos que realizan diferentes tareas para realizar, en global, una tarea más compleja.

Nota

La filosofía UNIX está detrás de las tuberías: se proporcionan muchos programas que hacen cosas específicas para luego componerlos entre ellos y crear funcionalidad avanzada.

Por ejemplo:

find /usr/lib -name *.so -type f | less
cat /etc/passwd | grep 100 --color
grep -Hiw network /usr/share/common-licenses/* | cut -f 1 -d ":" | sort -u

Ejercicios#

  • Descarga el fichero de Don Quijote en texto plano y cuenta el número de palabras que contiene. Puedes usar el comando wc para contarlas.

  • ¿Sabrías hacer todo el proceso, incluso descargar el archivo, con varios comandos en cadena?

    Solución
    wget -q https://uclm-esi.github.io/redes1-lab/assets/quijote.txt -O - | wc -w
    

Permisos de administrador#

Como ya habrás comprobado, hay muchos elementos del sistema de archivos a los cuales no puedes acceder por faltar de permisos. Por ejemplo:

$ cat /var/log/messages
cat: /var/log/messages: Permission denied

Como ya vimos en la sección de permisos, es necesario que tengas los permisos adecuados para acceder a un archivo para poder realizar la operación de escritura, lectura o ejecución. Sin embargo, también hay otro tipo de acciones que, por seguridad, están reservadas a usuarios que tengan permisos de administración. Algunas de estas operaciones son:

  • Añadir usuarios o grupos.

  • Cambiar las claves de otros usuarios.

  • Instalar programas nuevos en el sistema.

  • Acceso a bajo nivel de las interfaces de red.

En nuestra máquina virtual, el usuario alumno viene configurado de forma que pueda ejecutar comandos como usuario administrador cuando lo necesite. Para ello, se usa el comando sudo y, a continuación, el comando que se quiera ejecutar. Por ejemplo:

sudo cat /var/log/messages

Sistemas de paquetes#

Si hay algún aspecto que caracteriza a una distribución de GNU/Linux es el sistema de paquetes que utiliza. Una distribucicón se basa en recolectar software que hay disponible como software libre o código abierto, agruparlo y confirgurarlo de forma que los usuarios puedan acceder a ellos de una forma rápida y sencilla. El sistema de paquetes es el componente con el que los usuarios pueden gestionar los programas que instalan.

En Debian, los diferentes sistemas de paquetes se basan en un formato muy determinado: los paquetes Debian. Estos paquetes, empaquetados en archivos .deb, contienen normalmente software ya compilado y listo para usar, además de información extra como dependencias de otros programas, autor del programa, etc.

dpkg#

Los paquetes Debian pueden instalarse directamente con el comando dpkg. Sin embargo, no puedes instalarlos como usuario normal, sino que tienes que tener permisos de administrador:

sudo dpkg -i <path/to/file.deb>

Advertencia

Si el paquete tiene dependencias dpkg no las resolverá y no tratará de instalarlas. Para hacer eso, debes usar apt como veremos después.

También se puede eliminar un paquete como:

sudo dpkg -r <package-name>

Nota

El nombre de paquete es diferente al nombre del fichero .deb. Por ejemplo: el paquete myapp-1.0.deb seguramente tenga el nombre de paquete como myapp.

Y algunas opciones interesantes para listar los paquetes del sistema y los ficheros que contine un paquete:

dpkg -l
dpkg -L <package-name>

apt#

En un nivel superior de gestión de paquetes se encuentra apt. Esta herramienta, que utiliza dpkg por debajo, proporciona una mayor funcionalidad ya que:

  • Resuelve dependencias entre paquetes, instalando todo lo que sea necesario.

  • Accede a repositorios remotos. apt puede conectarse a un «store» de aplicaciones para descargarlas e instalarlas automáticamente.

  • Búsqueda de paquetes en base a diferentes criterios (contenido, descripción, tipo, etc.)

Las formas de utilizar apt más comunes son:

sudo apt update
sudo apt search <pattern>
sudo apt show <package-name>
sudo apt install <package-name>
sudo apt remove <package-name>
sudo apt purge <package-name>
sudo apt upgrade
sudo apt full-upgrade

Ejercicios#

  • Descarga el paquete redes1 e instálalo usando dpkg. ¿Qué archivos tiene? ¿Puedes usar alguno? Finalmente, bórralo usando dpkg.

    Solución
    dpkg -L redes1
    

    Se puede ejecutar redes1 y sale un mensaje.

  • Instala los paquetes sl y tree utilizando apt. ¿Qué es lo que hacen según su descripción? Desinstala los paquetes completamente.

    Solución
    sudo apt update
    sudo apt install tree sl
    apt show tree
    apt show sl
    sudo apt purge tree sl