En las secuencias de comandos de shell Bash, las funciones son formas de agrupar el conjunto de instrucciones para obtener un resultado específico. Puede pensar en las funciones como un mini script. Las funciones también se denominan procedimientos y métodos en algunos lenguajes de programación. Las funciones son una excelente manera de lograr la modularidad y la reutilización.
En este artículo, explicaré cómo usar funciones en bash scripts en Linux con ejemplos. Te sentirás bastante cómodo usando las funciones de bash al final de este artículo.
Cómo definir Funciones en Bash
Hay dos cosas importantes que debe comprender al trabajar con funciones.
- Definiendo la función,
- Llamar a la función.
De manera similar a cómo crea scripts de bash y los ejecuta, debe definir la función y llamarla para que se ejecute.
Hay dos formas sintácticas de definir una función en bash. La primera forma es usar la palabra clave incorporada de bash "function"
seguido del nombre de la función. El bloque de código se escribirá dentro de llaves {}
.
function [name] {
Block of code
}
La segunda forma es crear una función sin la palabra clave "function"
. Comience con el nombre de la función seguido de corchetes.
[name](){
Block of Code
}
¿Cuál elegir? Bueno, siempre es una elección personal. Elegir uno u otro no tiene inconvenientes.
También puede escribir funciones de una sola línea que se denominan funciones compactas . En las funciones compactas, cada línea de código dentro de las llaves se separa con un punto y coma (;
) .
Inicie su terminal y escriba una pieza de función multilínea. Ahora presione la tecla de flecha hacia arriba y verá que todo lo que escribió en varias líneas se convertirá en funciones compactas.
[name](){ first_line; second_line; }
MEJORES PRÁCTICAS:
- Intente elegir cualquier sintaxis y sea coherente con ella.
- Si trabaja en un entorno colaborativo, es importante que todos mantengan el mismo estándar al programar.
Convención de nomenclatura
Cuando creas una función, tienes que darle un nombre a tu función. El nombre de la función debe ser descriptivo y tratar de evitar nombres que ya sean usados por otras funciones, variables, constantes, etc. "Caso Serpiente" es la forma preferida de nombrar la función. En el caso de la serpiente, las palabras están separadas por guiones bajos.
Eche un vistazo al siguiente ejemplo. Creé una función llamada "hello_world"
en estilo de caja de serpiente que simplemente imprimirá hello world en stdout (Terminal).
hello_world() { echo "Running Simple Hello World Function" } hello_world
Cómo llamar a una Función en Bash
Vamos a crear una función de limpieza simple llamada "log_cleanup"
. El propósito de esta función es eliminar ".log"
archivos que tienen más de 30 días.
log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs/ -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" }
La función está definida, pero ¿será eso suficiente para que la función haga su trabajo? Absolutamente no. Tienes que llamar a la función para que se ejecute la función.
Para llamar a la función, simplemente escriba el nombre de la función después de la definición de la función:
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" } # Calling the function log_cleanup
Si intenta llamar a la función antes de la definición de la función, obtendrá el siguiente error.
line 3: log_cleanup: command not found
¿Porque? Cuando ejecute el script, el código se interpretará línea por línea de arriba a abajo. Leerá la función y la cargará en el entorno bash (memoria). Pero aquí está llamando a la función antes de que el intérprete lea y cargue la función en su entorno.
Cuando llama a una función desde dentro de otra función, la definición de su función puede estar en cualquier orden excepto la primera función. Echa un vistazo a la imagen de abajo. Función func2 se llama desde func1 y func3 se llama desde func2 antes de su definición. Pero func1 se define primero y luego se llama. En el momento func1 se llama todas las definiciones de función ya están interpretadas y cargadas en el entorno.
Estado de salida y valor devuelto
Cada comando de Linux devuelve un estado de salida (0-255). Se dice que cero tiene éxito y el resto de los códigos de salida se dice que son fallas con diferentes significados. De manera similar, cuando ejecuta una función, también devuelve un estado de salida del último comando de ejecución en la función.
Déjame ejecutar la misma función de "limpieza" nuevamente. Pero he dado una ruta que no está disponible en mi máquina, por lo que find
el comando fallará. Estoy usando $?
para obtener el estado de salida dentro del script como se muestra en la imagen.
Running Cleanup On Older Logs - 30 days find: '/home/karthick/Documents/Projectss/logs': No such file or directory Cleanup Completed Exit status of function log_cleanup is ⇒ 0
El estado de salida devuelto por la función es del echo
comando que se ejecutó como el último comando dentro de la función. Este no es el comportamiento que cabría esperar.
Para superar este comportamiento, puede usar el "return"
incorporado de bash declaración.
$ type -a return
return is a shell builtin
Retorno acepta un valor entero [N] y sale de las funciones y le da el valor de retorno a su llamador (función). Antes de usar la declaración de devolución, debe comprender algunas reglas sobre cómo usar la declaración de devolución. Como se indicó anteriormente, return acepta valores enteros de 0 a 255. Una instrucción de retorno utilizará el estado de salida del último comando ejecutado si no se pasa ningún argumento (valor entero) o si el valor excede 255.
Déjame usar el retorno para arreglar el "cleanup"
comportamiento de la función. Aquí estoy usando declaraciones condicionales junto con el comando de retorno.
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "[ INFO ] - Running Cleanup On Older Logs - 30 days" if [[ -d "/home/karthick/Documents/Projectss/logs" ]] then find -name "*.log" -type f -mtime +30 -delete echo "[ SUCCESS] - Cleanup Completed" else echo "[ ERROR ] - Directory path wrong... Cleanup has not happened..." return 1 fi } # Calling the function log_cleanup echo "++ Exit status of log_cleanup function is ==> $?"
Echa un vistazo a la salida a continuación. La función devuelve código de salida 1 de la declaración de devolución.
[ INFO ] - Running Cleanup On Older Logs - 30 days
[ ERROR ] - Directory path wrong… Cleanup has not happened…
++ Exit status of log_cleanup function is ==> 1
Pasar argumentos a una Función
Similar a pasar argumentos a sus scripts bash, las funciones también aceptan argumentos. La parte confusa es que las funciones usan el mismo $1
…$9
variables especiales para acceder a los argumentos, que es lo mismo que pasar el argumento al script. Tienes que entender lo que sucede cuando usas esta variable especial dentro y fuera de la función.
cat > arg_test.sh #!/bin/bash echo "Value passed in \$1 is = $1" howdy(){ echo "value of \$1 inside function is = $1" } howdy # Function Call
Copie y ejecute el fragmento anterior para ver la diferencia. La cadena "Howdy"
se pasa como el primer argumento del script.
$ ./arg_test.sh howdy
Value passed in $1 is = howdy
value of $1 inside function is =
Desde la salida, puede ver $1
dentro de la función está imprimiendo un valor vacío porque $1
dentro de la función es diferente de $1
fuera de la función aunque comparten el mismo nombre.
Para pasar argumentos a la función, después del nombre de la función, deje un espacio y pase sus argumentos como se muestra en la imagen de abajo. A cada argumento separado por espacio se le asignará su respectiva variable $1
…$N
y puede usar esta variable dentro de la función para procesar los argumentos.
log_cleanup $1 $2 ….. $N
Como puede ver en la captura de pantalla anterior, paso el nombre del directorio y la cantidad de días como argumentos.
Alcance variable para una función
Cuando crea una variable dentro o fuera de la función, se puede acceder a ella globalmente. De forma predeterminada, las variables se crean en el ámbito global.
Eche un vistazo al siguiente ejemplo. Si intenta acceder tanto a la variable outside_function
y inside_function
, sus valores son accesibles. Esto significa que aunque la función se ejecutó y salió, la variable creada dentro de la función es accesible globalmente.
#!/bin/bash outside_function="This variable is from outside the function" func1(){ inside_function="This variable is from inside the func1" } func1 echo $outside_function echo $inside_function
En algunos lenguajes de programación, este podría no ser el comportamiento y las variables creadas dentro de la función estarán disponibles durante el tiempo de ejecución de la función. Pero en bash, el comportamiento es diferente.
Para hacer que las variables sean locales para la función, puede usar el "local"
incorporado de bash palabra clave. La palabra clave local restringirá el alcance de la variable de global a local y solo se puede acceder a la variable durante el tiempo de ejecución de la función.
#!/bin/bash outside_function="This variable is from outside the function" func1(){ local inside_function="This variable is from inside the func1" } func1 echo $outside_function echo $inside_function
Lectura sugerida:
- Secuencias de comandos de Bash:variables explicadas con ejemplos
Cuando se usa la palabra clave local, puede usar los mismos nombres de variables en diferentes funciones.
Aviso: Siempre debe intentar evitar el uso de identificadores que ya se utilizan como variables, funciones, palabras clave de bash. El ejemplo anterior se muestra solo para comprender el comportamiento.
Modularidad y Resubalidad
Las funciones de comprensión y escritura se pueden realizar en poco tiempo. Pero escribir buenas funciones lleva tiempo con una mejor comprensión del entorno. Como ya se señaló en la sección de introducción, con las funciones bash puede lograr una gran modularidad y reutilización.
Tomemos un ejemplo. Ha creado 20 scripts y en cada script ha incluido el log_cleanup
función que hemos visto en apartados anteriores para realizar tareas de limpieza. En lugar de incluir esta función en los 20 scripts, puede crear una sola definición de función e importarla en 20 scripts. De esta manera, está logrando modularidad y funciones reutilizables. Esto es similar a importar declaraciones en python, incluir sentencias en C, etc.
Echa un vistazo a la imagen de abajo. He creado dos scripts llamados script1.sh
y script2.sh
y el log_cleanup
la función se escribe en un archivo separado llamado cleanup.sh
.
Estoy importando la función ejecutando source
dominio. La source
El comando ejecutará el archivo pasado como su argumento y cargará la variable o las funciones en la sesión de bash actual. De esta manera, cuando ejecuta log_cleanup
desde otro archivo de script, la función ya está cargada en el entorno actual y es accesible.
A partir de la imagen de arriba, puede comprender cómo los argumentos son útiles. Solo hay una definición de función y, según el caso de uso, puedo modificar la función para aceptar diferentes argumentos y en diferentes scripts.
Aviso: También puede ejecutar sus scripts de shell con source
comando que ejecutará el script en el shell actual en lugar de crear un subshell para ejecutar el script.
Conclusión
En esta guía, hemos discutido sobre las funciones de Bash y cómo definir y llamar a una función en scripts con ejemplos. Para sentirse cómodo con las funciones, debe practicar las funciones con diferentes casos de uso. Si tiene alguna pregunta o comentario, no dude en hacérnoslo saber a través de la sección de comentarios a continuación.
Lectura relacionada:
- Secuencias de comandos de Bash:bucle For explicado con ejemplos
- Secuencias de comandos de Bash:ciclo while y till explicado con ejemplos
- Diferencia entre la definición de variables Bash con y sin exportación
- Comando Bash Echo explicado con ejemplos en Linux
- Tutorial de Bash Heredoc para principiantes
- Redireccionamiento de Bash explicado con ejemplos