Una de las herramientas más importantes para la mayoría de los administradores de sistemas es la automatización. Escribimos y mantenemos scripts para automatizar las tareas comunes y frecuentes que debemos realizar.
Tengo docenas de guiones, cortos y largos, que he escrito y modificado a lo largo de los años. Algunas de mis secuencias de comandos más útiles han sido realizar copias de seguridad periódicas temprano cada mañana, instalar paquetes de software actualizados con correcciones y mejoras, y actualizar de una versión de Fedora a la siguiente. Acabo de actualizar todos mis hosts y servidores personales a Fedora 34 hace unos días usando un script bastante simple.
[ También te puede interesar: Más trucos estúpidos de Bash:variables, búsqueda, descriptores de archivos y operaciones remotas]
Dos de las cosas más comunes que hago para todos mis scripts son crear una función de ayuda y una función que muestra la declaración de licencia GPL3. Me gusta incluir modos detallados o de prueba para ayudar en la determinación de problemas en mis guiones. En algunos scripts, también paso valores como un nombre de usuario, la versión de Fedora para actualizar, nombres de archivos y más.
La capacidad de usar parámetros posicionales, también conocidos como argumentos, para especificar los datos que se usarán como valores para las variables en los scripts es un método para lograr esto. Otro es el uso de opciones y argumentos de opciones. Este artículo explora estos dos métodos para obtener datos en el script y controlar la ruta de ejecución del script.
Parámetros posicionales
Bash usa una herramienta llamada parámetros posicionales para proporcionar un medio para ingresar datos en un programa Bash cuando se invoca desde la línea de comando. Hay diez parámetros posicionales que se ejecutan desde $0 hasta $9 , aunque hay formas de sortear ese límite.
Comenzando con un script simple que muestra un nombre ingresado en la pantalla. Crea un archivo llamado script1.sh
con el siguiente contenido y hacerlo ejecutable.
#!/bin/bash
echo $0
Coloqué este script en mi directorio ~/bin directory
, donde se pretende almacenar archivos ejecutables personales, como scripts. Mire su $PATH variable, que contiene /home/username/bin
como un componente. Si el ~/bin directory
directorio no existe, puede crearlo. O simplemente puede colocar este archivo donde desee y usarlo desde allí.
Luego ejecute el script sin parámetros.
[student@testvm1 ~]$ script1.sh
/home/dboth/bin/script1.sh
[student@testvm1 ~]$
El resultado de este script es el nombre del script. El $0 El parámetro está reservado y predefinido como el nombre del script en ejecución y no se puede utilizar para ningún otro propósito. Esto puede ser útil dentro de una secuencia de comandos porque no necesita pasar la secuencia de comandos con su propio nombre si lo requiere.
Así que cambia el script para usar $1 para la variable posicional y ejecútelo de nuevo:
#!/bin/bash
echo $1
Vuelva a ejecutarlo, esta vez usando un único parámetro:
[student@testvm1 ~]$ script1.sh help
help
[student@testvm1 ~]$
¿Qué sucede si el parámetro son dos palabras?
[student@testvm1 ~]$ script1.sh help me
help
[student@testvm1 ~]$
En realidad, son dos parámetros, pero puede remediarlo con comillas, como se ve aquí:
[student@testvm1 ~]$ script1.sh "help me"
help me
[student@testvm1 ~]$
Esto puede ser útil cuando se supone que la entrada es una dirección de calle o algo con varias palabras, como esto:
[student@testvm1 ~]$ script1.sh "80486 Intel St."
80486 Intel St.
[student@testvm1 ~]$
Pero hay ocasiones en las que necesita varios parámetros, como nombres o direcciones completas.
Cambie el programa para que se vea así:
#!/bin/bash
echo "Name: $1"
echo "Street: $2"
echo "City: $3"
echo "State/Province/Territory: $4"
echo "Zip/Postal code: $5"
Y ejecútelo usando los parámetros como se muestra:
[student@testvm1 ~]$ script1.sh "David Both" "80486 Intel St." Raleigh NC XXXXX
Name: David Both
Street: 80486 Intel St.
City: Raleigh
State/Province/Territory: NC
Zip/Postal code: XXXXX
Por supuesto, hay muchas formas de usar los parámetros posicionales una vez que se han asignado los valores, pero este pequeño programa facilita ver lo que está sucediendo. También facilita la experimentación de forma segura.
Intente poner los parámetros en un orden diferente para ver cómo funciona. Estos parámetros son posicionales, y esa es una consideración clave. Debe considerar cuántos parámetros se necesitan, cómo los recuerda el usuario y en qué orden colocarlos.
Necesita una forma de hacer que el orden de los parámetros sea irrelevante y todavía necesita una forma de modificar la ruta de ejecución.
Opciones
Puede hacer esas dos cosas usando las opciones de la línea de comandos.
Encuentro que incluso los programas Bash simples deberían tener algún tipo de función de ayuda, incluso si es bastante rudimentario. Muchos de los programas de shell de Bash que escribo se usan con la frecuencia suficiente como para olvidar la sintaxis exacta del comando que necesito ejecutar. Algunos son tan complejos que necesito revisar las opciones y los argumentos necesarios, aunque los uso con frecuencia.
Tener una función de ayuda integrada le permite ver esas cosas sin tener que recurrir a inspeccionar el código en sí. Una buena y completa instalación de ayuda es también una parte de la documentación del programa.
Acerca de las funciones
Las funciones de shell son listas de declaraciones del programa Bash almacenadas en el entorno del shell y se pueden ejecutar como cualquier otro comando escribiendo su nombre en la línea de comando. Las funciones de shell también pueden conocerse como procedimientos o subrutinas, según el otro lenguaje de programación que esté utilizando.
Las funciones se llaman en sus scripts o desde la CLI usando sus nombres, tal como lo haría con cualquier otro comando. En un programa CLI o un script, los comandos de la función se ejecutan cuando se los llama. Luego, la secuencia del flujo del programa regresa a la entidad que llama y se ejecuta la siguiente serie de instrucciones del programa en esa entidad.
La sintaxis de una función es:
FunctionName(){sentencias de programa}
Cree una función simple en la CLI. La función se almacena en el entorno de shell para la instancia de shell en la que se crea. Vas a crear una función llamada hw , que significa Hola mundo . Ingrese el siguiente código en la CLI y presione Enter . Luego ingrese hw como lo haría con cualquier otro comando de shell.
[student@testvm1 ~]$ hw(){ echo "Hi there kiddo"; }
[student@testvm1 ~]$ hw
Hi there kiddo
[student@testvm1 ~]$
Ok, estoy un poco cansado del estándar "¡Hola mundo!" Normalmente empiezo con. Ahora enumere todas las funciones definidas actualmente. Hay muchos de ellos, así que solo he mostrado el nuevo hw función. Cuando se llama desde la línea de comandos o dentro de un programa, una función realiza su tarea programada. Luego sale, devolviendo el control a la entidad que llama, la línea de comando o la siguiente declaración del programa Bash en un script después de la declaración de llamada.
[student@testvm1 ~]$ declare -f | less
<snip>
hw ()
{
echo "Hi there kiddo"
}
<snip>
Ahora elimine esa función porque ya no la necesita. Puedes hacerlo con unset
comando, así:
[student@testvm1 ~]$ unset -f hw ; hw
bash: hw: command not found
[student@testvm1 ~]$
La secuencia de comandos hello.sh
Cree un nuevo script de shell Bash, ~/bin/hello.sh
y hacerlo ejecutable. Agregue el siguiente contenido, manteniéndolo básico para comenzar:
#!/bin/bash
echo "hello world!"
Ejecútelo para verificar que imprime "¡Hola mundo!".
[dboth@david ~]$ hello.sh
hello world!
[dboth@david ~]$
Lo sé, no puedo evitarlo, así que volví a "¡Hola, mundo!".
Creando la función de ayuda
Agregue la ayuda función que se muestra a continuación al código del programa hello. Coloque la ayuda función entre las dos declaraciones que ya tiene. Esta ayuda La función mostrará una breve descripción del programa, un diagrama de sintaxis y una breve descripción de cada opción disponible. También agrega una llamada a la ayuda función para probarlo y algunas líneas de comentarios que proporcionan una demarcación visual entre las funciones y la parte principal del programa.
El programa ahora se ve así.
#!/bin/bash
############################################################
# Help #
############################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
############################################################
############################################################
# Main program #
############################################################
############################################################
Help
echo "Hello world!"
Las opciones descritas en esta ayuda La función puede ser típica en los programas que escribo, aunque todavía no está presente en el código. Ejecute el programa para probarlo.
[student@testvm1 ~]$ hello.sh
Add a description of the script functions here.
Syntax: scriptTemplate [-g|h|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
Hello world!
[student@testvm1 ~]$
Como no ha agregado ninguna lógica para mostrar la ayuda cuando lo desee, el programa siempre mostrará la ayuda. Sin embargo, sabe que la función funciona correctamente, por lo que puede agregar algo de lógica solo para mostrar la ayuda cuando usa un -h
opción en la invocación de la línea de comando del programa.
Opciones de manejo
La capacidad de un script Bash para manejar opciones de línea de comando como -h
para mostrar la ayuda le brinda algunas capacidades poderosas para dirigir el programa y modificar lo que hace. En el caso de su -h
opción, quiere que el programa imprima el texto de ayuda en la sesión del terminal y luego salga sin ejecutar el resto del programa. La capacidad de procesar las opciones ingresadas en la línea de comando se puede agregar al script Bash usando el while
comando junto con getops
y case
comandos.
Los getops
El comando lee todas y cada una de las opciones especificadas en la línea de comando y crea una lista de esas opciones. El while
El comando recorre la lista de opciones configurando la variable $options para cada uno en el siguiente código. El case
instrucción se utiliza para evaluar cada opción a su vez y ejecutar las declaraciones en la estrofa correspondiente. El while
continuará evaluando la lista de opciones hasta que se hayan procesado todas o hasta que se encuentre una declaración de salida, que finaliza el programa.
Asegúrese de eliminar la ayuda llamada de función justo antes del echo "¡Hola mundo!" declaración para que el cuerpo principal del programa ahora se vea así.
############################################################
############################################################
# Main program #
############################################################
############################################################
############################################################
# Process the input options. Add options as needed. #
############################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
esac
done
echo "Hello world!"
Observe el punto y coma doble al final de la declaración de salida en la opción de caso para -h
. Esto es necesario para cada opción. Agregue a esta declaración de caso para delinear el final de cada opción.
Las pruebas ahora son un poco más complejas. Debe probar su programa con varias opciones diferentes, y sin opciones, para ver cómo responde. Primero, verifique para asegurarse de que sin opciones imprima "¡Hola mundo!" como debe ser.
[student@testvm1 ~]$ hello.sh
Hello world!
Eso funciona, así que ahora prueba la lógica que muestra el texto de ayuda.
[student@testvm1 ~]$ hello.sh -h
Add a description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
Eso funciona como se esperaba, así que ahora intente algunas pruebas para ver qué sucede cuando ingresa algunas opciones inesperadas.
[student@testvm1 ~]$ hello.sh -x
Hello world!
[student@testvm1 ~]$ hello.sh -q
Hello world!
[student@testvm1 ~]$ hello.sh -lkjsahdf
Add a description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
[student@testvm1 ~]$
Manejo de opciones no válidas
El programa simplemente ignora las opciones para las que no ha creado respuestas específicas sin generar ningún error. Aunque en la última entrada con el -lkjsahdf
opciones, porque hay una "h" en la lista, el programa la reconoció e imprimió el texto de ayuda. Las pruebas han demostrado que una cosa que falta es la capacidad de manejar entradas incorrectas y finalizar el programa si se detecta alguna.
Puede agregar otra estrofa de caso a la declaración de caso que coincidirá con cualquier opción para la que no haya una coincidencia explícita. Este caso general coincidirá con cualquier cosa para la que no haya proporcionado una coincidencia específica. El caso declaración ahora se ve así.
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # Invalid option
echo "Error: Invalid option"
exit;;
esac
done
Este fragmento de código merece una explicación sobre cómo funciona. Parece complejo pero es bastante fácil de entender. El mientras – hecho La estructura define un ciclo que se ejecuta una vez para cada opción en la getopts – opción estructura. El ":h" string —que requiere las comillas— enumera las posibles opciones de entrada que serán evaluadas por case – esac estructura. Cada opción enumerada debe tener una estrofa correspondiente en la declaración del caso. En este caso, son dos. Uno es el h) estrofa que llama al procedimiento de ayuda. Una vez que finaliza el procedimiento de ayuda, la ejecución vuelve a la siguiente instrucción del programa, exit;; que sale del programa sin ejecutar más código aunque exista alguno. El bucle de procesamiento de opciones también finaliza, por lo que no se verificarán opciones adicionales.
Observe la combinación general de \? como la última estrofa en la declaración del caso. Si se ingresa alguna opción que no se reconoce, esta estrofa imprime un breve mensaje de error y sale del programa.
Cualquier caso específico adicional debe preceder al último resumen. Me gusta colocar las estrofas de los casos en orden alfabético, pero habrá circunstancias en las que querrá asegurarse de que un caso en particular se procese antes que otros. La declaración de caso es sensible a la secuencia, así que tenga esto en cuenta cuando construya la suya.
La última declaración de cada estrofa en la construcción de caso debe terminar con el doble punto y coma (;;
), que se utiliza para marcar explícitamente el final de cada estrofa. Esto permite que los programadores a los que les gusta usar punto y coma explícitos al final de cada declaración en lugar de implícitos continúen haciéndolo para cada declaración dentro de cada estrofa de caso.
Vuelva a probar el programa con las mismas opciones que antes y vea cómo funciona ahora.
El script Bash ahora se ve así.
#!/bin/bash
############################################################
# Help #
############################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
############################################################
############################################################
# Main program #
############################################################
############################################################
############################################################
# Process the input options. Add options as needed. #
############################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # Invalid option
echo "Error: Invalid option"
exit;;
esac
done
echo "hello world!"
Asegúrese de probar esta versión de su programa muy a fondo. Use la entrada aleatoria y vea qué sucede. También debe intentar probar opciones válidas e inválidas sin usar el guión (-
) delante.
Uso de opciones para ingresar datos
Primero, agregue una variable e inicialícela. Agregue las dos líneas que se muestran en negrita en el segmento del programa que se muestra a continuación. Esto inicializa el $Name variable a "mundo" por defecto.
<snip>
############################################################
############################################################
# Main program #
############################################################
############################################################
# Set variables
Name="world"
############################################################
# Process the input options. Add options as needed. #
<snip>
Cambia la última línea del programa, el echo
comando, a esto.
echo "hello $Name!"
Agregue la lógica para ingresar un nombre en un momento, pero primero pruebe el programa nuevamente. El resultado debería ser exactamente el mismo que antes.
[dboth@david ~]$ hello.sh
hello world!
[dboth@david ~]$
# Get the options
while getopts ":hn:" option; do
case $option in
h) # display Help
Help
exit;;
n) # Enter a name
Name=$OPTARG;;
\?) # Invalid option
echo "Error: Invalid option"
exit;;
esac
done
$OPTARG es siempre el nombre de la variable utilizada para cada nuevo argumento de opción, sin importar cuántos haya. Debe asignar el valor en $OPTARG a un nombre de variable que se usará en el resto del programa. Esta nueva estrofa no tiene una declaración de salida. Esto cambia el flujo del programa para que después de procesar todas las opciones válidas en la declaración del caso, la ejecución avance a la siguiente declaración después de la construcción del caso.
Pruebe el programa revisado.
[dboth@david ~]$ hello.sh
hello world!
[dboth@david ~]$ hello.sh -n LinuxGeek46
hello LinuxGeek46!
[dboth@david ~]$ hello.sh -n "David Both"
hello David Both!
[dboth@david ~]$
El programa completo se ve así.
#!/bin/bash
############################################################
# Help #
############################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
############################################################
############################################################
# Main program #
############################################################
############################################################
# Set variables
Name="world"
############################################################
# Process the input options. Add options as needed. #
############################################################
# Get the options
while getopts ":hn:" option; do
case $option in
h) # display Help
Help
exit;;
n) # Enter a name
Name=$OPTARG;;
\?) # Invalid option
echo "Error: Invalid option"
exit;;
esac
done
echo "hello $Name!"
Asegúrese de probar la función de ayuda y cómo reacciona el programa ante entradas no válidas para verificar que su capacidad para procesarlas no se haya visto comprometida. Si todo funciona como debería, entonces ha aprendido con éxito cómo usar opciones y argumentos de opciones.
[ Obtenga este libro electrónico gratuito:Administrar sus clústeres de Kubernetes para principiantes. ]
Resumir
En este artículo, usó parámetros posicionales para ingresar datos en el programa Bash durante la invocación desde la línea de comando y usó opciones para dirigir el flujo del programa, así como para ingresar datos en el programa. Agregó una función de ayuda y la capacidad de procesar las opciones de la línea de comandos para mostrar la ayuda de forma selectiva. Y agregó un argumento opcional que permite ingresar un nombre en la línea de comando.
Este pequeño programa de prueba está diseñado para ser simple, por lo que puede experimentar fácilmente con él para probar este método de entrada por su cuenta. Como ejercicio, revise el programa para tomar un nombre y un apellido. Intente ingresar las opciones de nombre y apellido en orden inverso para ver qué sucede.
Recursos
- Cómo programar con Bash:sintaxis y herramientas
- Cómo programar con Bash:operadores lógicos y expansiones de shell
- Cómo programar con Bash:Bucles