Ya hemos visto cómo trabajar en Linux, tanto con la CLI como con la GUI. También hemos visto la gestión de procesos, que como sabes son conjuntos de tareas lanzadas a través de comandos o programas.
En nuestra introducción al curso vimos que el código en Linux está almacenado en archivos. De hecho, estudiando la terminal vimos que incluso el stdin, stdout y stderr se gestionan como tal, y que podemos redireccionarlos a verdaderos archivos. Por ejemplo, el comando ‘cat some_file.txt > some_file_copy.txt’ nos generará una copia del archivo some_file.txt, ya que estamos redirigiendo el stdout para que en lugar de salir por la consola salga por un fichero.
Teniendo esto en cuenta, es fundamental poder trabajar con archivos en Linux. Evidentemente, estos conocimientos nos servirán también para realizar algunas de las tareas cotidianas para las que utilizamos un sistema operativo: navegar, crear ficheros, copiarlos y renombrarlos, gestionar directorios…
El filesystem de Linux
Hace unos días hablamos ya del sistema de archivos de Linux. Se trata de una estructura jerarquizada que nos permite organizar nuestros documentos. Pero cobra particular importancia cuando sabemos que en Linux “todo es un archivo”.
El sistema de archivos empieza en el directorio raíz (root directory), representado por una barra /. Recuerda que este no es el mismo directorio que el de la raíz del usuario (root user) ni el de cualquiera de los usuarios, al que podemos acceder con el shortcut ~.
Linux incluye implementaciones de sistemas de archivos propios de otros sistemas operativos, como ntfs, vfat y exfat (Windows) o hfs y hfs+ (MacOS). Pero también es compatible con diferentes sistemas de archivos nativos, como ext3, ext4, squashfs o btrfs. De hecho, no es raro que encontremos varios sistemas de archivos diferentes en la misma máquina, lo que suele ocurrir en diferentes particiones.
Las particiones de Linux
Utilizamos particiones para organizar el contenido de un disco, evitar que se saturen piezas clave del sistema y que se propague una eventual corrupción de datos o brecha de seguridad.
El punto de montaje (mount point)
Antes de utilizar un sistema de archivos necesitamos montarlo en el árbol de sistemas de archivos. Para ello utilizamos un punto de montaje, que no es más que un directorio. Habitualmente estos directorios están vacíos, ya que de tener contenido no podremos acceder al mismo hasta que no desmontemos el filesystem (fs) adicional.
Para montar un sistema de archivos utilizamos el comando mount y para desmontarlo se utiliza umount. Ambos son comandos reservados al root user.
En ocasiones puede que nos interese que el punto de montaje esté disponible de forma automática desde que hemos arrancado el sistema. Para estos casos deberemos editar el archivo /etc/fstab (file system table).
Podemos comprobar los fs montados ejecutando el comando mount sin argumentos, o bien obtener información detallada de los discos montados con el comando df -Th (disk free). Nos encontraremos con filesystems de tipo tmpfs. Como su nombre indica, no se trata de fs reales, sino de partes de la memoria del sistema utilizadas a modo de sistema de archivos. En adelante nos referiremos a ellos también como pseudo-filesystems, para hacer referencia a que no están albergados en un dispositivo físico de forma permanente.
Los Network Filesystems (NFS)
Cuando necesitamos que diferentes dispositivos accedan al mismo sistema de archivos utilizamos sistemas de archivos en red (NFS). El sistema de archivos compartido utilizará un cliente de NFS que se conectará a la red (puede implicar Internet o no) hasta llegar al servidor de NFS, conectado directamente al sistema de archivos compartido.
Servidor NFS
Este servidor funciona utilizando daemons para gestionar sus procesos, y el archivo /etc/exports para establecer los permisos y directorios abiertos. Una vez configurado este archivo deberemos actualizar el nfs con el comando exportfs -av o bien reiniciarlo con sudo systemctl restart nfs. Para arrancarlo a mano lanzaremos sudo systemctl start nfs y para que se inicie automáticamente al arrancar la máquina utilizaremos sudo systemctl enable nfs.
Cliente NFS
Para conectarnos a un servidor NFS, en el cliente editaremos el archivo fs/fstab, como hacíamos con los discos locales, o bien utilizaremos el comando mount de nuevo.
La estructura de un sistema de archivos
En la introducción a Linux vimos ya las características esenciales del sistema de archivos, así como algunos de sus directorios más importantes. Revisemos este contenido.
Normalmente disponemos de una carpeta /root que representa el directorio raíz del usuario principal. El resto de usuarios tienen sus directorios en un directorio /home, que puede utilizar particiones internas o externas (NFS) del disco.
Este directorio /home, que alberga los directorios asignados a cada usuario, puede compartimentarse. Por ejemplo, en una empresa cada usuario podría tener su carpeta base dentro de la carpeta de su departamento. A su vez, todos los departamentos estarían incluidos en /home.
A continuación veremos los directorios principales de un sistema de archivos Linux, así como sus contenidos y funcionalidades.
/bin
Contiene archivos binarios ejecutables, que se utilizan principalmente durante el arrancado o bien al ejecutar los comandos esenciales que necesitan todos los usuarios del sistema.
/sbin
También incluye archivos binarios, pero en esta ocasión están relacionados con la administración del sistema y no con el arranque o la ejecución de comandos básicos.
/usr/bin y /usr/sbin
Incluyen archivos binarios que no son imprescindibles para arrancar o administrar el sistema, o al menos no lo son para todos los usuarios. En distribuciones modernas se vinculan a las carpetas /bin y /sbin, ya que no es necesario hacer esta distinción.
/boot
Contiene los archivos esenciales para inicializar el sistema. Cada kernel instalado en el sistema debe contener al menos los siguientes archivos:
- vmlinuz - Contiene el kernel comprimido, necesario para iniciar el sistema.
- initramfs - Contiene el sistema de archivos de la ram, también necesario para el arranque.
- config - Es un archivo de configuración del kernel.
- System.map - contiene la tabla simbólica del kernel. Como el anterior, se utiliza solo para depurar.
En esta carpeta también encontramos el GRUB (Grand Unified Bootloader)
/dev
La carpeta /dev (device nodes) incluye pseudo-archivos (archivos virtuales, que existen solo en memoria) que gestionan los dispositivos (salvo aquellos de red). Estos pseudo-archivos se van creando dinámicamente, cada vez que el sistema descubre un nuevo dispositivo.
/etc
Incluye archivos de configuración y algunos scripts ejecutables. Dado que afectan a todo el sistema, solo el súper usuario puede modificarlos.
/lib
Contiene binarios necesarios para los programas principales contenidos en /bin y /sbin. /lib32 contiene binarios de 32 bits, mientras que /lib64 contiene sus versiones para sistemas de 64 bits.
/media /run /mnt
/media contiene dispositivos que se pueden conectar y desconectar, como CDs y USBs. Se trata de un punto de montaje para este tipo de dispositivos extraíbles. En distribuciones recientes, estos dispositivos pueden montarse en /run en lugar de en /media.
/mnt es un punto de montaje para fs alternativos, habitualmente NFS.
/opt
Contiene paquetes de software opcionales
/proc
Esta carpeta incorpora un pseudo-filesystem (es decir, un sistema de archivos virtual, que no corresponde a ningún dispositivo físico). Se trata de archivos virtuales, que reflejan el estado del kernel. Los diferentes procesos están representados en sus propios directorios, dentro de la ruta /proc.
/srv
Gestiona la información entregada por el sistema
/sys
Es un pseudo-filesystem que ofrece información sobre el sistema y el estado del hardware.
/tmp
Contiene archivos temporales, que se eliminarán al reiniciar el sistema.
/usr
Contiene aplicaciones, utilidades e información a la que pueden acceder diferentes usuarios del sistema. A su vez, se estructura en otros directorios que ya hemos analizado.
/var
El directorio /var (variable) contiene archivos cuyo contenido y peso variará a lo largo de la ejecución del sistema, como los archivos temporales o la caché.
¿Cómo trabajar con los archivos en Linux?
Ahora que sabemos qué es un filesystem y cómo montarlo y desmontarlo, así como la jerarquía estándar de un sistema Linux, podemos entrar a conocer las formas en las que podemos trabajar con nuestros archivos.
Algunos comandos de interés son:
- file - explica el tipo de archivo.
- diff - compara ficheros y directorios. Algunas opciones interesantes son:
- -c nos ofrece contexto (algunas líneas previas de contenido).
- -r compara recursivamente para analizar subdirectorios.
- -w ignora espacios en blanco y tabulaciones
- -q muestra tan solo si los archivos difieren o no.
- cmp - compara archivos binarios.
Tipos de archivos en Linux
Linux no confía en las extensiones de los archivos para determinar cuál es su contenido. Aunque utilicemos terminaciones como .txt, .pdf, .png, .js, etc, en realidad un archivo terminado en .txt podría ser ejecutable o contener una imagen sin problema.
Para conocer ante qué tipo de archivo nos encontramos, debemos utilizar el comando file.
Cómo aprovechar diff para crear parches en nuestro código
Si queremos distribuir un parche para nuestro código, es más eficiente hacerlo compartiendo solo los cambios entre la versión anterior y posterior que compartiendo el fichero entero.
Gracias al comando diff podemos obtener archivos con parches:
diff -Nur originalfile newfile > patchfile
Posteriormente podremos aplicar el parche a nuestro código:
patch -p1 < patchfile
En el caso de que solo queramos parchear un archivo específico, podemos hacerlo con el siguiente comando:
patch originalfile patchfile
Básicamente, esta forma de utilizar diff nos permite adoptar prácticas similares a las que utilizaríamos con git.
Métodos de compresión
Linux incluye diversos métodos de compresión de archivos, como gzip, bzip2, xz, zip o tar.
- gzip es la herramienta utilizada tradicionalmente en Linux, gracias a su buena compresión y su gran velocidad.
- bzip2 tiene una sintaxis similar a gzip y, aunque tarda más en comprimir, también obtiene ficheros más pequeños. Se deprecó a favor de xz.
- xz es el sucesor de bzip2, y genera archivos mejor comprimidos. Es idóneo, por tanto, para archivos de gran tamaño. Se trata de la solución más eficiente de Linux, por lo que se utiliza para distribuir ficheros del kernel. Cada vez es más utilizado.
- zip. No suele utilizarse en Linux, pero sí para traer ficheros de otros sistemas operativos. También es legacy, ya que no tiene ventajas a nivel de eficiencia ni velocidad.
- tar (tape archive) permite la compresión simultánea a la creación del archivo y la descompresión simultánea a su lectura.
Comandos para archivos comprimidos
Ten en cuenta que al trabajar con archivos comprimidos no podremos utilizar la mayoría de los comandos básicos de Linux. En estos casos podemos hacer uso de variantes como zcat, zless, zgrep o zdiff, xzcat, xzless, xzdiff, etc.
Cómo gestionar backups en Linux
Ya vimos que podíamos utilizar el comando cp para copiar ficheros y directorios, lo cual nos permite sincronizar o hacer copias de seguridad. Pero también existe el comando rsync, que funciona más eficientemente al copiar solo los cambios existentes, obviando los archivos que no hayan cambiado.
El programa Disk-to-Disk (dd)
El programa dd nos permite hacer copias de un disco en otro (¡eso sí, sobreescribiéndolo!). Es útil para copiar una partición o disco entero, pero es peligroso utilizarlo sin conocimientos.
La edición de textos con Linux
Probablemente, cuando trabajes con Linux utilices tu IDE de confianza para escribir código (como Visual Studio Code) y algún paquete de ofimática cuando necesites formatear texto (Libre Office o las herramientas de Google). Sin embargo, habrá momentos en que solo necesitarás cambiar unas líneas de un archivo. Por ejemplo, para corregir la configuración de una aplicación o corregir algún error menor. O es posible que tu tarea no requiera de un programa avanzado o una interfaz gráfica.
Para estos casos, Linux pone a nuestra disposición una serie de opciones. Algunas están pensadas para tareas sencillas, mientras que otras incluyen funcionalidades muy avanzadas.
Creación de archivos
En este curso ya hemos visto dos formas diferentes de crear archivos en Linux:
- Con el comando touch.
- O bien dirigiendo un stream a un nuevo archivo: echo > new-file.txt
Una forma menos intuitiva de crear un archivo es mediante el comando cat, combinándolo con la redirección de streams:
cat << STOP > new_file
hello
world!
STOP
nano y gedit
Los editores de texto más sencillos de utilizar en Linux son nano y gedit. El primero se utiliza desde la consola, mientras que el segundo tiene su propia interfaz gráfica, que es similar al bloc de notas de Windows.
Para utilizar nano debemos insertar el comando nano seguido del nombre del archivo a editar. Si este no existe, se creará para nosotros. El propio editor cuenta con una interfaz en la que nos ofrecerá algunos de sus comandos y shortcuts, incluyendo la opción de ayuda.
vi y vim
vi y vim (vi iMproved) son editores potentes incluidos prácticamente en cualquier distribución Linux. Se trata de un editor manipulable desde el teclado, con cierta curva de aprendizaje.
El comando vimtutor nos ofrece un tutorial que cubre los elementos básicos para poder trabajar con este programa, que tiene diferentes modos de funcionamiento. Dependiendo del modo en el que estemos trabajando, cada tecla o comando hará una función:
- Modo command. Es el modo inicial, y permite insertar comandos mediante el teclado.
- Modo insert. Se accede pulsando i, y permite insertar texto en un archivo. Para salir se debe pulsar esc, lo que nos devolverá al modo command.
- Modo line. Se excede pulsando :, y nos permite utilizar comandos de edición.
Algunas de las prestaciones de vi y vim incluyen la búsqueda de texto e incluso la ejecución de comandos de shell desde el propio editor, ya que podemos entrar en modo shell con la tecla !.
Principales comandos en vim
- vi file_name - abre el archivo indicado en el editor.
- :r file_name - lee el archivo y lo inserta en la posición actual.
- :w - escribe en el archivo. Tiene modificadores para escribir o sobreescribir en otros archivos.
- :q - sale del programa. Tiene modificadores para salir sin guardar.
- 😡 y :wq - sale del programa, guardando los cambios.
Recuerda que el cursor en vim se mueve con las teclas h-j-k-l, y también con otras como w o $.
emacs
Se trata de otro editor avanzado, que no funciona mediante “modos”, sino mediante opciones que se pueden lanzar con las teclas ctrl y meta (Alt o Esc). El comando Ctrl-h ofrece ayuda y si a continuación pulsamos t entraremos en el tutorial.
Uso de cat (concatenate) y echo para editar textos
Ya hemos visto que el comando cat nos permite imprimir en consola el contenido de un archivo. Pero también podemos utilizarlo para crear archivos si redirigimos su output a un nuevo archivo:
- cat file1 file2 > newfile - Combina el contenido de los archivos y lo guarda en el nuevo archivo.
- cat file >> existingfile - adjunta el contenido del archivo a otro ya existente.
- cat > file - guarda el input posterior hasta que se haga ctrl-d.
- cat >> file - adjunta el input posterior hasta que se haga ctrl-d.
- cat << STOP > newfile - introduce el texto en el nuevo archivo hasta que se escriba STOP.
- cat > newfile << EOF - forma alternativa del comando anterior.
Estas estrategias se pueden utilizar también con el comando echo.
Editando archivos con sed (stream editor) y awk
El comando sed nos permite modificar los contenidos de un stream, normalmente ubicándolos en un nuevo archivo. Su sintaxis básica es la siguiente:
- sed -e comando <archivo> - ejecuta uno o varios comandos de edición.
- sed -f <script> <archivo> - ejecuta un script que contenga comandos de sed sobre un archivo.
- echo “Hello, world!” | sed s/Hello/Goodbye/ - sustituye patrones.
awk es otro útil comando cuando tenemos que trabajar con archivos. nos permite lanzar comandos directamente o bien cargar un script. Suele utilizarse para trabajar con columnas y filas.
Otros comandos de utilidad para manipular archivos
Linux pone a nuestra disposición otros comandos de utilidad para manipular archivos:
- sort - ordena las líneas de un archivo.
- uniq - elimina líneas repetidas consecutivas (para evitar esta limitación se puede lanzar con sort o directamente lanzar sort -u. Con -c cuenta el número de ocurrencias).
- paste - combina cada línea de un archivo con cada línea de otro archivo.
- join - cumple la misma misión que paste, pero combinando los campos si se repiten y organizando no por orden de línea sino por el campo común (como un JOIN de SQL).
- split - separa un archivo en varios archivos con determinado número de líneas máximas (1000 por defecto).
- tr - traduce series de caracteres en otros caracteres (translate).
- tee - toma el output de un programa y lo lleva a un archivo mientras sale por el stdout.
- wc - cuenta palabras, líneas o caracteres.
- cut - extrae columnas de un archivo tabulado
Buscando texto con grep
El comando grep nos permite buscar expresiones regulares en archivos. Además, admite opciones para personalizar la búsqueda a realizar.
Resumen
- Linux trabaja siempre con archivos. Estos se organizan en un sistema jerarquizado y estandarizado.
- Además, podemos incluir sistemas de archivos adicionales, que pueden provenir de particiones del disco, de dispositivos extraíbles o de redes (cableadas o inalámbricas). También contamos con sistemas de archivos virtuales o pseudo-filesystems.
- Además de utilizar los comandos básicos para gestionar archivos. Linux nos provee de herramientas para hacer copias de seguridad y versiones, así como para comprimir nuestros archivos.
Comandos y shortcuts
- mount - establece un punto de montaje para un sistema de archivos.
- umount - desmonta el sistema de archivos.
- sudo start/restart/enable nfs - gestiona el Network Filesystem.
- exportsfs -av - actualiza los directorios y permisos expuestos en el NFS.
- diff - compara ficheros y directorios.
- cmp - compara archivos binarios.
- file - explica el tipo de archivo.
- diff -Nur originalfile newfile > patchfile - crea un parche.
- patch originalfile patchfile - aplica el parche a un archivo.
- patch -p1 < patchfile - aplica el parche al directorio.
- rsync -r source_file_or_dir target-machine:target_file_or_dir.
- gzip, bzip2, xz, zip, tar - aplican métodos de compresión.
- dd - crea eficientemente copias de grandes archivos, directorios o particiones.
- nano - abre el editor de texto nano.
- sed - manipula streams
- awk - manipula datos
- sort - ordena las líneas de un archivo.
- uniq - elimina líneas repetidas consecutivas (para evitar esta limitación se puede lanzar con sort o directamente lanzar sort -u. Con -c cuenta el número de ocurrencias).
- paste - combina cada línea de un archivo con cada línea de otro archivo.
- join - cumple la misma misión que paste, pero combinando los campos si se repiten y organizando no por orden de línea sino por el campo común (como un JOIN de SQL).
- split - separa un archivo en varios archivos con determinado número de líneas máximas (1000 por defecto).
- grep - busca expresiones regulares.
- tr - traduce series de caracteres en otros caracteres (translate).
- tee - toma el output de un programa y lo lleva a un archivo mientras sale por el stdout.
- wc - cuenta palabras, líneas o caracteres.
- cut - extrae columnas de un archivo tabulado