Comprensión y aprendizaje de las secuencias de comandos de shell básicas y la resolución de problemas del sistema de archivos Linux - Parte 10


Linux Foundation lanzó la certificación LFCS ( Linux Foundation Certified Sysadmin ), una nueva iniciativa cuyo objetivo es permitir que las personas en todas partes (y en cualquier lugar) obtengan la certificación de básico a intermedio. soporte operativo para sistemas Linux, que incluye soporte de sistemas y servicios en ejecución, junto con monitoreo y análisis generales, además de una toma de decisiones inteligente cuando se trata de plantear problemas a los equipos de soporte superiores.

Vea el siguiente video que le brinda una introducción al Programa de Certificación de la Fundación Linux.

Este es el último artículo (Parte 10) de la presente serie larga de 10 tutoriales. En este artículo nos centraremos en la creación de scripts de shell básicos y la resolución de problemas de los sistemas de archivos Linux. Ambos temas son obligatorios para el examen de certificación LFCS.

Comprensión de terminales y carcasas

Primero aclaremos algunos conceptos.

  1. A shell is a program that takes commands and gives them to the operating system to be executed.
  2. A terminal is a program that allows us as end users to interact with the shell. One example of a terminal is GNOME terminal, as shown in the below image.

Cuando iniciamos un shell por primera vez, presenta un símbolo del sistema (también conocido como línea de comando), que nos dice que el shell está listo para comenzar a aceptar comandos desde su dispositivo de entrada estándar, que generalmente es el teclado.

Es posible que desee consultar otro artículo de esta serie (Usar comando para crear, editar y manipular archivos - Parte 1) para revisar algunos comandos útiles.

Linux proporciona una variedad de opciones para shells, las siguientes son las más comunes:

Bash significa Bourne Again SHell y es el shell predeterminado del proyecto GNU. Incorpora funciones útiles del shell Korn (ksh) y del shell C (csh), que ofrecen varias mejoras al mismo tiempo. Este es el shell predeterminado utilizado por las distribuciones cubiertas en la certificación LFCS, y es el shell que usaremos en este tutorial.

Bourne SHell es el shell más antiguo y, por lo tanto, ha sido el shell predeterminado de muchos sistemas operativos similares a UNIX durante muchos años.

Korn SHell es un shell de Unix que fue desarrollado por David Korn en Bell Labs a principios de la década de 1980. Es compatible con versiones anteriores del shell Bourne e incluye muchas características del shell C.

Un script de shell es nada más y nada menos que un archivo de texto convertido en un programa ejecutable que combina los comandos que ejecuta el shell uno tras otro.

Secuencias de comandos de shell básicas

Como se mencionó anteriormente, un script de shell nace como un archivo de texto sin formato. Por lo tanto, se puede crear y editar con nuestro editor de texto preferido. Es posible que desee considerar el uso de vi/m (consulte Uso del editor vi - Parte 2 de esta serie), que presenta resaltado de sintaxis para su conveniencia.

Escriba el siguiente comando para crear un archivo llamado myscript.sh y presione Entrar.

# vim myscript.sh

La primera línea de un script de shell debe ser la siguiente (también conocida como shebang ).

#!/bin/bash

le dice ” al sistema operativo el nombre del intérprete que se debe utilizar para ejecutar el texto que sigue.

Ahora es el momento de agregar nuestros comandos. Podemos aclarar el propósito de cada comando, o todo el script, agregando comentarios también. Tenga en cuenta que el shell ignora las líneas que comienzan con un signo de almohadilla # (comentarios explicativos).

#!/bin/bash
echo This is Part 10 of the 10-article series about the LFCS certification
echo Today is $(date +%Y-%m-%d)

Una vez que el script se ha escrito y guardado, debemos hacerlo ejecutable.

# chmod 755 myscript.sh

Antes de ejecutar nuestro script, necesitamos decir algunas palabras sobre /usr/local/bin:/usr/local/sbin:/usr/bin:/opt/cuda/bin:/usr/lib/jvm/variable de entorno predeterminada/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl . Si corremos

echo $PATH

desde la línea de comando, veremos el contenido de /usr/local/bin:/usr/local/sbin:/usr/bin:/opt/cuda/bin:/usr/lib/jvm/default/bin :/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl: una lista de directorios separados por dos puntos que se buscan cuando ingresamos el nombre de un programa ejecutable. Se denomina variable de entorno porque es parte del entorno del shell: un conjunto de información que está disponible para el shell y sus procesos secundarios cuando se inicia por primera vez.

Cuando escribimos un comando y presionamos Enter, el shell busca en todos los directorios listados en /usr/local/bin:/usr/local/sbin:/usr/bin:/opt/cuda/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl y ejecuta la primera instancia que se encuentra. Veamos un ejemplo,

Si hay dos archivos ejecutables con el mismo nombre, uno en /usr/local/bin y otro en /usr/bin , se ejecutará el del primer directorio. primero, mientras que el otro será ignorado.

Si no hemos guardado nuestro script dentro de uno de los directorios listados en /usr/local/bin:/usr/local/sbin:/usr/bin:/opt/cuda/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl , necesitamos agregar ./ al nombre del archivo en para ejecutarlo. De lo contrario, podemos ejecutarlo como lo haríamos con un comando normal.

# pwd
# ./myscript.sh
# cp myscript.sh ../bin
# cd ../bin
# pwd
# myscript.sh

Siempre que necesite especificar diferentes cursos de acción a tomar en un script de shell, como resultado del éxito o fracaso de un comando, utilizará la construcción if para definir tales condiciones. Su sintaxis básica es:

if CONDITION; then 
	COMMANDS;
else
	OTHER-COMMANDS 
fi

Donde CONDICIÓN puede ser una de las siguientes (aquí solo se citan las condiciones más frecuentes) y se evalúa como verdadera cuando:

  1. [ -a file ] → file exists.
  2. [ -d file ] → file exists and is a directory.
  3. [ -f file ] →file exists and is a regular file.
  4. [ -u file ] →file exists and its SUID (set user ID) bit is set.
  5. [ -g file ] →file exists and its SGID bit is set.
  6. [ -k file ] →file exists and its sticky bit is set.
  7. [ -r file ] →file exists and is readable.
  8. [ -s file ]→ file exists and is not empty.
  9. [ -w file ]→file exists and is writable.
  10. [ -x file ] is true if file exists and is executable.
  11. [ string1 = string2 ] → the strings are equal.
  12. [ string1 != string2 ] →the strings are not equal.

[int1 op int2] debe formar parte de la lista anterior, mientras que los elementos que siguen (por ejemplo, -eq -> es verdadero si int1 es igual a int2 .) debe ser una lista " hijos " de [ int1 op int2 ] donde op es uno de los siguientes operadores de comparación.

  1. -eq –> is true if int1 is equal to int2.
  2. -ne –> true if int1 is not equal to int2.
  3. -lt –> true if int1 is less than int2.
  4. -le –> true if int1 is less than or equal to int2.
  5. -gt –> true if int1 is greater than int2.
  6. -ge –> true if int1 is greater than or equal to int2.

Este bucle permite ejecutar uno o más comandos para cada valor en una lista de valores. Su sintaxis básica es:

for item in SEQUENCE; do 
		COMMANDS; 
done

Donde elemento es una variable genérica que representa cada valor en SECUENCIA durante cada iteración.

Este bucle permite ejecutar una serie de comandos repetitivos siempre que el comando de control se ejecute con un estado de salida igual a cero (con éxito). Su sintaxis básica es:

while EVALUATION_COMMAND; do 
		EXECUTE_COMMANDS; 
done

Donde EVALUATION_COMMAND puede ser cualquier comando que pueda salir con un estado de éxito ( 0 ) o error (que no sea 0) y EXECUTE_COMMANDS puede ser cualquier programa, script o construcción de shell, incluidos otros bucles anidados.

Demostraremos el uso de la construcción if y el ciclo for con el siguiente ejemplo.

Creemos un archivo con una lista de servicios que queremos supervisar de un vistazo.

# cat myservices.txt

sshd
mariadb
httpd
crond
firewalld

Nuestro script de shell debería verse así.

#!/bin/bash

# This script iterates over a list of services and
# is used to determine whether they are running or not.

for service in $(cat myservices.txt); do
    	systemctl status $service | grep --quiet "running"
    	if [ $? -eq 0 ]; then
            	echo $service "is [ACTIVE]"
    	else
            	echo $service "is [INACTIVE or NOT INSTALLED]"
    	fi
done

1). El bucle for lee el archivo myservices.txt un elemento de LIST a la vez. Ese único elemento se denota mediante la variable genérica denominada servicio. La LISTA se completa con la salida de,

# cat myservices.txt

2). El comando anterior está entre paréntesis y precedido por un signo de dólar para indicar que debe evaluarse para completar la LISTA sobre la que iteraremos.

3). Para cada elemento de LIST (es decir, cada instancia de la variable de servicio), se ejecutará el siguiente comando.

# systemctl status $service | grep --quiet "running"

Esta vez necesitamos preceder nuestra variable genérica (que representa cada elemento en LIST ) con un signo de dólar para indicar que es una variable y, por lo tanto, se debe usar su valor en cada iteración. La salida luego se canaliza a grep.

El indicador –quiet se usa para evitar que grep muestre en la pantalla las líneas donde aparece la palabra en ejecución. Cuando eso sucede, el comando anterior devuelve un estado de salida de 0 (representado por 0 en la construcción if), verificando así que el servicio se está ejecutando.

Un estado de salida diferente a 0 (lo que significa que la palabra en ejecución no se encontró en la salida de estado de systemctl ) indica que el servicio no se está ejecutando.

Podríamos ir un paso más allá y verificar la existencia de myservices.txt incluso antes de intentar ingresar al bucle for.

#!/bin/bash

# This script iterates over a list of services and
# is used to determine whether they are running or not.

if [ -f myservices.txt ]; then
    	for service in $(cat myservices.txt); do
            	systemctl status $service | grep --quiet "running"
            	if [ $? -eq 0 ]; then
                    	echo $service "is [ACTIVE]"
            	else
                    	echo $service "is [INACTIVE or NOT INSTALLED]"
            	fi
    	done
else
    	echo "myservices.txt is missing"
fi

Es posible que desee mantener una lista de hosts en un archivo de texto y usar una secuencia de comandos para determinar de vez en cuando si se puede hacer ping o no (siéntase libre de reemplazar el contenido de myhosts e intentarlo usted mismo ).

El comando read shell incorporado le dice al bucle while que lea myhosts línea por línea y asigna el contenido de cada línea a la variable host, que luego se pasa al comando ping .

#!/bin/bash

# This script is used to demonstrate the use of a while loop

while read host; do
    	ping -c 2 $host
done < myhosts

Leer también :

  1. Learn Shell Scripting: A Guide from Newbies to System Administrator
  2. 5 Shell Scripts to Learn Shell Programming

Solución de problemas del sistema de archivos

Aunque Linux es un sistema operativo muy estable, si falla por algún motivo (por ejemplo, debido a un corte de energía), uno (o más) de sus sistemas de archivos no se desmontarán correctamente y, por lo tanto, se verificará automáticamente en busca de errores cuando Linux se reinicia.

Además, cada vez que el sistema arranca durante un arranque normal, siempre comprueba la integridad de los sistemas de archivos antes de montarlos. En ambos casos, esto se realiza mediante una herramienta llamada fsck (" verificación del sistema de archivos ").

fsck no solo comprobará la integridad de los sistemas de archivos, sino que también intentará reparar los sistemas de archivos corruptos si se le indica que lo haga. Dependiendo de la gravedad del daño, fsck puede tener éxito o no; cuando lo hace, las partes recuperadas de los archivos se colocan en el directorio perdido + encontrado , ubicado en la raíz de cada sistema de archivos.

Por último, pero no menos importante, debemos tener en cuenta que también pueden ocurrir inconsistencias si intentamos quitar una unidad USB cuando el sistema operativo todavía está escribiendo en ella, e incluso pueden provocar daños en el hardware.

La sintaxis básica de fsck es la siguiente:

# fsck [options] filesystem

Para verificar un sistema de archivos con fsck, primero debemos desmontarlo.

# mount | grep sdg1
# umount /mnt
# fsck -y /dev/sdg1

Además del indicador -y , podemos usar la opción -a para reparar automáticamente los sistemas de archivos sin hacer ninguna pregunta y forzar la verificación incluso cuando el sistema de archivos parece limpio.

# fsck -af /dev/sdg1

Si solo estamos interesados u200bu200ben descubrir qué está mal (sin intentar arreglar nada por el momento) podemos ejecutar fsck con la opción -n , que generará los problemas del sistema de archivos en la salida estándar.

# fsck -n /dev/sdg1

Dependiendo de los mensajes de error en la salida de fsck, sabremos si podemos intentar resolver el problema nosotros mismos o escalarlo a los equipos de ingeniería para realizar más verificaciones en el hardware.

Resumen

Hemos llegado al final de esta serie de 10 artículos en la que hemos tratado de cubrir las competencias básicas del dominio necesarias para aprobar el examen LFCS .

Por razones obvias, no es posible cubrir todos los aspectos de estos temas en un solo tutorial, y es por eso que esperamos que estos artículos lo hayan puesto en el camino correcto para probar cosas nuevas usted mismo y continuar aprendiendo.

Si tiene alguna pregunta o comentario, siempre será bienvenido, así que no dude en escribirnos a través del formulario a continuación.