Hola a todos Esta es una traducción del Libro de preparación del examen RedHat RHCE. En mi opinión, es muy accesible sobre los conceptos básicos de bash.
Los scripts de Shell son una ciencia en sí mismos. Sin entrar en detalles de todo lo que sucede "bajo el capó", aprenderá cómo usar los elementos básicos para escribir sus propios scripts y analizar lo que sucede en los scripts de shell de terceros.

Comprender los elementos básicos de los scripts de shell
De hecho, un script de shell es una lista de comandos que se ejecutan secuencialmente, así como cierta lógica que permite que el código se ejecute solo bajo ciertas condiciones.
Para comprender los scripts de shell complejos, se recomienda comenzar con scripts básicos.
El siguiente es un script muy simple:
Contiene varios elementos que deben usarse en todos los scripts. Para empezar, hay shebang: esta es la línea #! / Bin / bash. Cuando el script se inicia desde el shell principal, abre un subshell en el que se ejecutan los comandos especificados en el script.
Estos comandos se pueden interpretar de varias maneras. Para entender exactamente cómo deben ser interpretados, se usa shebang. En el ejemplo anterior, shebang deja en claro que el script debe ser ejecutado por el shell bash.
También se pueden indicar otras conchas. Por ejemplo, si su script contiene código Perl, shebang debería ser #! / Usr / bin / perl. Comenzar un script con shebang es una buena práctica; si se omite, el código del script será ejecutado por el mismo shell que se utiliza para ejecutar el script.
Inmediatamente después del shebang, hay una parte que explica de qué trata el guión. Algunas líneas de comentarios al comienzo de cada escenario son una buena idea. En un guión corto, a menudo es obvio lo que hace, pero a medida que el guión se alarga, y a medida que más personas se involucran en escribirlo y apoyarlo, se vuelve menos claro lo que los autores intentan hacer.
Para evitar esta situación, asegúrese de agregar líneas de comentarios que comiencen con cada carácter #. Los comentarios pueden estar no solo en las primeras líneas, sino también al comienzo de cada subsección del guión. ¡Esto sin duda ayudará si lees tu guión en unos pocos meses!
También puede comentar no solo las subsecciones, sino también las líneas individuales.
No importa en qué posición se use, todo, desde el carácter # hasta el final de la línea, es un comentario.
Después del bloque de comentarios, se encuentra el cuerpo del script. En el ejemplo anterior, estos son varios comandos que se ejecutan secuencialmente. El cuerpo del script de shell puede aumentar a medida que se desarrolla.
Al final del script, incluí la declaración de
salida 0 . La declaración de salida le dice al shell principal si el script fue exitoso. El estado de salida del último comando en el script es el estado de salida del script en sí, a menos que se use la
salida 0 al final del script.
Es útil saber que puede trabajar con
exit para decirle al shell principal cómo fueron las cosas.
Introducido en el shell principal, el echo $? le permite consultar el estado de salida del último script en ejecución.
Después de crear el script, asegúrese de que se pueda ejecutar. La forma más común de hacer esto es aplicarle un bit de ejecución. Entonces, si el nombre del archivo de script es hola, use el
comando chmod + x ./hello para hacerlo ejecutable.
El script también se puede ejecutar como argumento para el comando bash. En este caso, ingrese
bash ./hello para ejecutar el script de saludo. Si el script se ejecuta como un argumento para el comando bash, el archivo de script no tiene que ser ejecutable.
De hecho, puede almacenar el script en cualquier lugar, pero si lo va a almacenar en un directorio que no está incluido en la variable $ PATH, debe ejecutarlo con ./ delante del nombre del script.
Escriba
./hello para ejecutar el script o póngalo en el directorio estándar que se incluye en la variable $ PATH, por ejemplo, / usr / local / bin.
También puede colocar el script en el directorio / bin, luego de lo cual simplemente ingrese el nombre del archivo en cualquier parte del sistema de archivos y el script se ejecutará.
EjemploUsando
vi / bin / datetime, cree un archivo llamado datetime en el directorio / bin. Pegue este contenido en el archivo creado:
Después de guardar el archivo, ingrese
chmod + x / bin / datetime para dar permiso al archivo para que se ejecute. Por ejemplo, cambie a su directorio de inicio usando el
comando cd ~ y simplemente ingrese
datetime .
Vaya, por ejemplo, al directorio de inicio cd ~ e ingrese datetime.
[root@localhost ~]
Usar variables y entradas
los scripts de bash son mucho más que una simple lista de comandos que se ejecutan secuencialmente. Una de las cosas buenas de los scripts es que pueden trabajar con variables y entradas para hacer que el script sea flexible. En esta sección aprenderá a trabajar con ellos.
Usando parámetros posicionales
Al ejecutar el script, puede usar los argumentos. Un argumento es todo lo que pones detrás de un comando de script. Los argumentos se pueden usar para hacer que el script sea más flexible. Toma el comando
useradd lisa . En este ejemplo, el comando es
useradd , y su argumento,
lisa , indica lo que hay que hacer.
Como resultado de dicho comando, se debe crear un usuario llamado lisa.
En el script, el primer argumento es
$ 1 , el segundo argumento es
$ 2, y así sucesivamente. El Listado 1 muestra cómo se pueden usar los argumentos. Intente ejecutar este código especificando cualquier nombre de usuario como parámetro.
Listado 1
Los parámetros significan la entrada de datos antes de ejecutar el script. En este caso, especifiqué
lisa ,
lori y
bob como parámetros después del nombre del script de argumento:
[root@server1 ~]
Si trató de ejecutar el código de muestra, puede notar que su contenido no es perfecto. Si utiliza tres argumentos al ejecutar el script del Listado 1, funcionará bien. Si usa solo dos argumentos, el tercero se genera sin el valor $ 3.
Si usa cuatro argumentos, el cuarto valor (que se almacenará en $ 4) nunca se mostrará. Por lo tanto, si desea utilizar argumentos, es mejor que utilice un enfoque más flexible.
Listado 2
El Listado 2 muestra dos nuevos elementos que se relacionan con los argumentos:- $ # Es un contador que muestra cuántos argumentos se usaron al ejecutar el script.
- $ @ Es una lista de todos los argumentos que se usaron al ejecutar el script.
Para enumerar los argumentos que se usaron al ejecutar este script, se usa el bucle
for . En
for loops, las instrucciones se ejecutan siempre que la condición sea verdadera. En este escenario, la condición
para i en $ @ significa "para cada argumento". Cada vez que el script pasa por el ciclo, el valor de la variable
$ @ se asigna a la variable
$ i .
Entonces, siempre que haya argumentos, el cuerpo del script se ejecuta.
El cuerpo del bucle for siempre comienza con
do y cierra
done , y los comandos que se ejecutarán se enumeran entre estas dos palabras clave. Por lo tanto, el script de muestra usará
echo para mostrar el valor de cada argumento y se detendrá cuando no haya más argumentos disponibles.
Probemos el script en el Listado 2 en este ejemplo:- Escriba vi argumento para crear el archivo de argumento y copie el contenido del script en el Listado 2 a este archivo.
- Guarde el archivo y hágalo ejecutable.
- Ejecute el comando ./argument abc . Verá que se muestran tres líneas.
- Ejecute el comando ./argument abcdef . Verá que además de abc, también se mostrará de f.
Variables
Una variable es una etiqueta que se usa para indicar un lugar específico en la memoria que contiene un valor específico. Las variables pueden definirse estáticamente usando NAME = value o dinámicamente. Hay dos soluciones para definir dinámicamente una variable:
- Utilice la palabra clave read en un script para solicitar datos del usuario que ejecuta el script.
- Use la sustitución de comandos para usar el resultado del comando y asignarlo a una variable. Por ejemplo, la fecha del comando +% d-% m-% y muestra la fecha actual en el formato día-mes-año. Para hacer esto en un script, puede usar HOY = $ (fecha +% d-% m-% a) . Para sustituir comandos, solo necesita poner el comando cuyo resultado desea utilizar entre paréntesis.
En la sección anterior sobre parámetros posicionales, aprendió cómo asignar argumentos a variables cuando ejecuta un script. En algunos casos, puede ser más eficiente solicitar información cuando encuentra que falta algo sustancial. El siguiente script muestra cómo hacer esto.
Listado 3. Script de muestra usando el comando de
lectura
En el script del Listado 3, el operador
if ... then ... else ... fi se usa para probar la existencia del argumento
$ 1 . Esto se hace usando
test (test es un comando separado). El comando de prueba se puede escribir de dos maneras *:
prueba o
[...] . En el ejemplo, la línea
if [-z $ 1] ... se ejecuta para ver la prueba (verificar)
-z $ 1 .
*
- en realidad tres fuentes (traductor aprox.)-z prueba comprueba si existe
$ 1 o no. En otras palabras, la línea
if [-z $ 1] verifica si
$ 1 está vacío, lo que significa que no se proporcionaron argumentos cuando se ejecutó este script. Si es así, se ejecutan los comandos después de la instrucción
then .
Tenga en cuenta que al escribir el comando de
prueba entre corchetes, es importante usar espacios después del corchete de apertura y antes del corchete de cierre, sin espacios el comando no funcionará.
Tenga en cuenta que la instrucción
then sigue inmediatamente a la
prueba . Esto es posible porque se usa un punto y coma (;). El punto y coma es un separador de comandos y puede reemplazar una nueva línea en un script.
La instrucción
then ejecuta dos comandos: el comando
echo , que muestra el mensaje en la pantalla, y el comando de
lectura .
El comando de
lectura detiene el script para que la entrada del usuario pueda procesarse y almacenarse en la variable TEXT. Por lo tanto,
leer TEXTO coloca todas las entradas del usuario en la variable TEXTO, que se utilizará más adelante en el script.
La siguiente parte está representada por la
instrucción else . Los comandos después de la
instrucción else se ejecutan en todos los demás casos, lo que en este caso significa "de lo contrario, si se proporcionó el argumento". Si es así, se determina la variable TEXTO y
se le asigna el valor actual de
$ 1 .
Observe cómo se define la variable: inmediatamente después del nombre de la variable hay un signo = seguido de $ 1. Tenga en cuenta que nunca debe usar espacios al definir variables.
Luego, las condiciones si se cierran utilizando el operador
fi . Después de que se complete la condición if, sabe con certeza que la variable TEXT está definida y tiene un valor. La penúltima línea del script lee el valor de la variable TEXT y asigna este valor a STDOUT usando el comando
echo . Tenga en cuenta que para solicitar el valor actual de una variable, se refiere al nombre de la variable, comenzando con el signo $ delante de ella.
Puede practicar el uso de este ejemplo cuando trabaje con entrada.- Abra el editor y cree un archivo llamado texto. Ingrese el contenido del código en el Listado 3 en este archivo.
- Escriba el archivo en el disco y ejecute chmod + x text para hacerlo ejecutable.
- Ejecute el script ejecutando ./text y sin argumentos adicionales. Verá que pide entrada.
- Ejecute el script usando " hola " como argumento (./text hola). El resultado mostrará "ha ingresado el texto hola" en STDOUT.
Usando condiciones y bucles
Como ya ha visto, las declaraciones condicionales se pueden usar en un script. Estas declaraciones condicionales se ejecutan solo si se cumple una determinada condición.
Hay varias declaraciones condicionales y bucles en bash que a menudo se usan.
- if ... then ... else : se usa para ejecutar código si se cumple una determinada condición
- for : se utiliza para ejecutar comandos para un rango de valores
- while : se usa para ejecutar código si se cumple una determinada condición
- antes : se usa para ejecutar código hasta que se cumpla una determinada condición
- case : se utiliza para evaluar un número limitado de valores específicos
si entonces más
La
construcción if then else es común para evaluar condiciones específicas. Ya has visto un ejemplo con él. Esta declaración condicional a menudo se usa con el comando de
prueba . Este comando le permite verificar muchas cosas: por ejemplo, no solo si existe un archivo, sino también comparar archivos, comparar enteros y mucho más.
Puede obtener más información sobre la prueba en la referencia con el comando man test.
La construcción básica de
if es
if ... entonces ... fi .
Compara una condición, como se muestra en el siguiente ejemplo:
if [ -z $1 ] then echo no value provided fi
En el Listado 3, viste cómo puedes evaluar dos condiciones, incluyendo
otra cosa en una expresión. El Listado 4 muestra cómo evaluar varias condiciones de
if a
else . Esto es útil si necesita verificar muchos valores diferentes.
Tenga en cuenta que este ejemplo también utiliza varios comandos de
prueba .
Listado 4 . Ejemplo con
if then else
|| y &&
En lugar de escribir
declaraciones completas
if ..., puede usar los operadores lógicos
|| así como
&& .
|| es un "OR" lógico y ejecutará la segunda parte de la declaración solo si la primera parte no es verdadera;
&& es un "Y" lógico y ejecutará la segunda parte de la declaración solo si la primera parte es verdadera.
Considere estas dos líneas: [ -z $1 ] && echo no argument provided
ping -c 1 8.8.8.8 2>/dev/null || echo node is not available
El primer ejemplo verifica si
$ 1 está vacío. Si esta verificación es correcta (lo que básicamente significa que el comando termina con el código de salida 0), se ejecuta el segundo comando.
En el segundo ejemplo, el comando
ping se usa para verificar la disponibilidad del host.
Este ejemplo utiliza un "OR" lógico para mostrar el texto "el nodo no está disponible" en el caso de una falla del comando
ping .
Encontrará eso a menudo, en lugar de la
sentencia if condicional,
&& y
|| . En el ejercicio a continuación, puede practicar el uso de declaraciones condicionales usando
if ... then ... else o
&& y
|| .
Ejercicio Usando
if ... entonces ... elseEn este ejercicio, trabajará en un script que verifica qué es un archivo y qué es un directorio.
- Inicie el editor y cree un script llamado filechk.
- Copie el contenido del Listado 4 en este script.
- Ejecute un par de pruebas con él, como ./filechk / etc / hosts , ./filechck / usr , ./filechk archivo no existente .
Para bucle
El bucle
for es una excelente solución para procesar rangos de datos. En el Listado 5, puede ver el primer ejemplo con
for , donde el rango se determina y procesa mientras hay valores sin procesar en este rango.
Listado 5
Un ciclo
for siempre comienza con la palabra clave for, seguido de una condición que debe verificarse. Esto es seguido por la palabra clave
do , seguida de comandos que deben ejecutarse, si la condición es verdadera, el ciclo termina usando la palabra clave
done .
En el ejemplo del Listado 5, puede ver que la condición es un rango de números entre paréntesis asignados a la variable COUNTER.
Una pequeña explicacionDentro
((...)) se calculan las expresiones aritméticas y se devuelve su resultado. Por ejemplo, en el caso más simple, la construcción a = $ ((5 + 3)) asignará a la variable “a” el valor de la expresión “5 + 3” u 8. Además, los paréntesis dobles permiten trabajar con variables en el estilo del lenguaje C.
Primero, la variable se inicializa a 100, y siempre que el valor sea mayor que 1, se resta 1 en cada iteración. Mientras la condición sea verdadera, el valor de la variable $ COUNTER se muestra con el comando
echo .
En el Listado 6, puede ver una de mis frases favoritas con
for . El rango se define esta vez como una secuencia de números, comenzando desde 100 y llegando a 104.
Listado 6 for i in {100..104}; do ping –c 1 192.168.4.$i >/dev/null && echo 192.168.4.$i is up; done
Observe cómo se determina el rango: primero especifique el primer número, luego dos puntos e indique el último número en el rango. Además, con
for i in, para cada uno de estos números,
se asigna la variable
i . Cada uno de estos números se asigna a la variable
i y luego se ejecuta el comando
ping , donde la opción
-c 1 garantiza que solo se envíe una solicitud.
El resultado del comando
ping no se tiene en cuenta, por lo que su salida se redirige a / dev / null. Según el estado de salida del comando
ping , se ejecuta una parte de la expresión
&& . Por lo tanto, si el host está disponible, se muestra una línea que indica que se está ejecutando.
Comprender mientras y hasta
Si la instrucción for de la que acaba de leer es útil para trabajar con rangos de elementos, entonces la instrucción
while es útil cuando desea realizar un seguimiento de algo como la accesibilidad del proceso. También hay una instrucción
hasta , que se ejecuta siempre que la condición que se verifica sea falsa. En el Listado 7, puede leer cómo
se usa
while para monitorear la actividad del proceso.
Nota No entendí lo que hace este script. En mi caso, se usa CentOS 7 y por defecto no hay monitor, aunque el script dice explícitamente: uso: monitor <processname>
En algún lugar durante media hora busqué en Google el programa de monitor para CetOS, pero no lo encontré. Y, en general, no está claro qué monitor lateral está aquí si se usa ps aux. En cualquier caso, no entendí lo que hace este script. Una gran solicitud para ayudar a resolver este problema es ajustar el texto o la secuencia de comandos.
Listado 7
El script en el Listado 7 consta de dos partes. Primero, hay un
ciclo while . En segundo lugar, hay que hacer todo cuando el
ciclo while ya no se evalúa como verdadero.
El núcleo del
ciclo while es el comando
ps , que tiene un valor de
$ 1 .
Tenga en cuenta el uso de
grep -v grep , que excluye las líneas que contienen el
comando grep del resultado. Recuerde que el comando
ps incluirá todos los procesos en ejecución, incluido el
comando grep , al que se pasa la salida del
comando ps . Esto puede conducir a una coincidencia de falsos positivos.
La salida del comando
ps aux se redirige a / dev / tty11. Esto le permite leer los resultados de tty11 más adelante, si es necesario, pero no se muestran de forma predeterminada.
Las instrucciones while son seguidas por los comandos que deben ejecutarse si la condición que se verifica es verdadera. En este caso, es el comando sleep 5 , que detiene la ejecución del script durante 5 segundos.Mientras la condición de la instrucción while sea verdadera, el bucle continúa ejecutándose. Si la condición es falsa (lo que en este caso significa que el proceso ya no está disponible), el ciclo se detiene y los comandos que siguen pueden ejecutarse.Debe estar familiarizado con todos estos comandos, excepto el último. En la línea mail -s "proceso $ 1 ha parado" root <. El mensaje se envía al usuario root mediante el sistema de correo interno, que se ejecuta en Linux * de forma predeterminada. Comando de correotoma como primer argumento el asunto del mensaje especificado con la opción -s .* - al menos en CentOS funciona por defecto. (en. traductor)Preste atención a <. Al final del equipo.Por lo general, cuando se usa el comando de correo en modo interactivo, se abre un editor en el que puede escribir el cuerpo del mensaje. Este editor está cerrado, proporcionando una línea que solo tiene un punto. En este comando, se proporciona un punto redirigiendo STDIN. Esto permite que el mensaje se procese sin ningún requisito adicional para la actividad del usuario.Ciclo mientras que - el opuesto del ciclo hasta que , un ejemplo del cual se muestra en el Listado 8.hasta que comienza una iteración que dura hasta que la condición se vuelve verdadera.En el Listado 8, se usa para filtrar la salida del comando de los usuarios por la aparición de $ 1 , que será el nombre de usuario. Hasta que este comando sea correcto, la iteración continúa. Cuando se encuentra el nombre de usuario en la salida del usuario, la iteración se cierra y, después del ciclo hasta, se ejecuta el resto de los comandos.Listado 8
Entendiendo el caso
El último bucle de iteración importante es el caso *. La declaración del caso se usa para evaluar una serie de valores esperados. En particular, las declaraciones de casos son importantes en los scripts de inicio de Linux, que en versiones anteriores se usaban para iniciar servicios.* - ¿es un ciclo?En la declaración de caso, usted define cada argumento concreto que espera, seguido del comando que se ejecutará si se utilizó ese argumento.En el Listado 9, puede ver la declaración del caso , que se utilizó en una versión anterior para ejecutar casi cualquier servicio.Listado 9 case "$1" in start) start;; stop) rm -f $lockfile stop;; restart) restart;; reload) reload;; status) status ;; *) echo "Usage: $0 (start|stop|restart|reload|status)" ;; esac
El estuche tiene varias características. Primero viene la línea - caso en secuencia . Esto es seguido por una lista de todos los valores posibles que deben evaluarse. Cada elemento está cerrado con un corchete ) .Esto es seguido por una lista de comandos que se ejecutarán si se utilizó un argumento específico. La lista de comandos se cierra con un punto y coma doble; se puede usar inmediatamente después del último comando y se puede usar en una línea separada.También tenga en cuenta que *) se aplica a todos los demás parámetros no especificados anteriormente. Este es un operador que lo abarca todo.El bucle de iteración de caso termina con la instrucción esac .Tenga en cuenta que las secuencias en el caso se ejecutan en orden. Cuando se realiza la primera coincidencia, la declaración del caso no evaluará nada.Como parte de la evaluación, se pueden usar plantillas similares a la plantilla. Esto se muestra en *) una secuencia que coincide con todo. Pero también puede usar secuencias como inicio | Inicio | INICIO) para que coincidan con otro caso .Depuración de scripts en Bash
Cuando el script no hace lo que espera, es útil hacer alguna depuración. Para comenzar, intente ejecutarlo como argumento para el comando bash -x . Esto le mostrará línea por línea lo que el script está tratando de hacer, así como errores específicos si no funciona como debería.El Listado 10 muestra un ejemplo de uso de bash -x , donde inmediatamente queda claro que el comando grep no sabe lo que debe hacer, porque falta un argumento para su operación. [root@server1 ~]
Para resumir
En este artículo, aprendiste a escribir scripts de shell. Has visto algunos ejemplos y ahora estás familiarizado con algunos de los elementos básicos necesarios para crear un script exitoso.