Con el fin de hacer nuestro sistema (o servidor) más flexible. Aunque podemos hacer muchas cosas con estas técnicas. Es de gran utilidad poder ejecutar un script justo antes de la ejecución de cualquier orden de Bash y que, justo cuando esta orden termine, podamos ejecutar cualquier otra cosa. Esto nos abre las puertas, por ejemplo a notificaciones de inicio/finalización, logging, monitorización y muchas más posibilidades que veremos en futuros posts. Cosas que podremos hacer tanto en el ámbito local, como en servidores de forma muy sencilla.
Aunque otros intérpretes, como ksh, tcsh, zsh y algunos más tienen facilidades para estas tareas. Vamos a hacerlo en bash, ¡porque somos unos valientes! Porque se instala por defecto con muchas distribuciones y porque es el que me he encontrado con más frecuencia.
Tabla de contenidos
Ejecutar algo cuando termina un comando
Cuando un comando se ha ejecutado y Bash nos vuelve a pedir una nueva orden, justo antes de darnos el control, y para mostrar el prompt (ese texto que suele ser usuario@host /directorio/actual y termina en un dólar o una almohadilla), Bash, ejecutará lo que contenga la variable PROMPT_COMMAND, ya sea una función, un alias, o la ejecución de un programa. Vamos a hacer una prueba:
Incluso si sólo pulsamos enter, como se vuelve a generar el prompt, justo antes nos mostrará la fecha (porque el comando a ejecutar es date)
Como ejemplo práctico, vamos a hacer un pequeño script que nos notificará cuando alguna partición de nuestro disco duro llegue a un punto crítico, en este caso, vamos a revisar todas las particiones de /dev/sdb y avisar al usuario cuando alguna de estas sobrepase el 90% (opciones que podremos configurar luego), para ello, vamos a crear un script llamado critp.sh con lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/bin/sh PARTITION_PATTERN="/dev/sdb*" WARNING_PERCENT=90 __RED='\033[1;31m' __YELLOW='\033[1;33m' __NC='\033[0m' # Color end function space_notifier() { local OLDIFS=$IFS IFS=$'\n' local STATUS=($(df -h $PARTITION_PATTERN | awk 'NR > 1')) IFS=$' \n\t\r' for st in "${STATUS[@]}"; do local _ST=($st) local _PERCENT=$(echo ${_ST[4]}| tr -d '%') if (("$_PERCENT">"$WARNING_PERCENT")); then echo -e $__RED"El dispositivo "$__YELLOW"${_ST[0]}"$__RED" está al ${_ST[4]}$ fi done 2>/dev/null IFS=$OLDIFS } PROMPT_COMMAND="space_notifier" |
Y lo cargaremos de la siguiente manera:
Con esto, cada vez que pulsemos enter o finalice un comando, veremos el conjunto de dispositivos que ha alcanzado ese porcentaje de espacio:
Una buena idea sería también notificar sólo a veces, tal vez con una probabilidad del 50%. Para que no siempre esté calculando ni nos sintamos abrumados por los mensajes de notificación. Para ello, podemos dejar el script así:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/bin/sh PARTITION_PATTERN="/dev/sdb*" WARNING_PERCENT=90 PROBABILITY=50 __RED='\033[1;31m' __YELLOW='\033[1;33m' __NC='\033[0m' # Color end function space_notifier() { if (($(($RANDOM%100))<$PROBABILITY)); then return fi local OLDIFS=$IFS IFS=$'\n' local STATUS=($(df -h $PARTITION_PATTERN | awk 'NR > 1')) IFS=$' \n\t\r' for st in "${STATUS[@]}"; do local _ST=($st) local _PERCENT=$(echo ${_ST[4]}| tr -d '%') if (("$_PERCENT">"$WARNING_PERCENT")); then echo -e $__RED"El dispositivo "$__YELLOW"${_ST[0]}"$__RED" está al ${_ST[4]}$ fi done 2>/dev/null IFS=$OLDIFS } PROMPT_COMMAND="space_notifier" |
Ya tenemos lo básico. Aunque estaría muy bien conocer información sobre el comando que se acaba de ejecutar y que, por supuesto, tenemos a nuestra disposición como es el propio comando ejecutado y su estado de salida. Más adelante podremos saber si se ha ejecutado realmente un comando, porque claro, cuando pulsas enter, vuelve a llamarse a la función. Ahora mismo, está muy bien si queremos realizar tareas de mantenimiento, notificar al usuario si está mal de espacio en disco, etc. Como el siguiente ejemplo que servirá para notificar al usuario cuando termine una determinada tarea. Suponemos que estamos en un entorno gráfico, así que avisaremos con zenity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/bin/bash function notify() { NOTIFY=1 } function pcom() { local _PIPESTATUS=( ${PIPESTATUS[@]} ) if [ -n "$NOTIFY" ]; then local OLDIFS=$IFS IFS=' ' local STATUS="${_PIPESTATUS[@]}" IFS=$'\n' local HIST=($(HISTTIMEFORMAT= history 1 | awk '{ print $1"\n"substr($0, index($0,$2)) }')) IFS=$OLDIFS zenity --info --text "$(echo -e "COMANDO FINALIZADO: ${HIST[1]}\n ESTADO: $STATUS")" fi unset NOTIFY } PROMPT_COMMAND="pcom" |
Ahora, cargaremos el archivo con source. Y podremos ejecutar cualquier comando con normalidad, aunque, cuando vayamos a hacer algo que vaya para largo podremos hacer lo siguiente:
De esta forma, cuando termine la ejecución de sleep 100, o de cualquier otra cosa que creamos que va a tardar mucho, recibiremos un mensaje parecido a este:
Este script tiene algunas cosas curiosas. Para hallar el estado de la ejecución de las órdenes, utilizo PIPESTATUS. Esta variable, si el comando es sencillo, devolverá sólo un valor, haciendo lo mismo que $?. Pero cuando hemos llamado varios comandos unidos por una pipe o tubería, nos va a devolver el estado de todos los comandos ejecutados. Eso sí, como PIPESTATUS se actualiza tras cada cosa que ejecutamos, lo primero que haremos nada más entrar en la función será guardar su valor en otra variable, y así nos aseguramos de no perderlo.
Y esto está muy bien cuando estamos haciendo varias cosas y se nos puede ir la cabeza con una tarea. Nos puede servir para cuando estemos creando o restaurando un dump de base de datos, cuando estemos haciendo una copia de archivos (local o remota), o estemos realizando alguna tarea de cálculo intenso. Tan solo tenemos que llamar antes de la tarea en cuestión a notify y ya se encargará él de todo. Podemos extender la funcionalidad de notify, incluso aprovechar lo que voy a contar a continuación para hacerlo más potente (te adelanto que en unos días publicaré un script mucho más completo).
Ejecutar algo justo antes de llamar al comando
Para tener control total sobre los comandos ejecutados es interesante poder ejecutar código antes de la ejecución de los comandos. Esto, principalmente nos ayuda a depurar nuestros scripts, porque sabremos en qué orden se ejecuta cada cosa, pero también puede ser una buena herramienta de control, gran ayuda para hacer una visualización interactiva de comandos o, para saber lo que ejecutan nuestras visitas o los comandos que se ejecutan en un servidor además de muchas otras utilidades.
Como ejemplo, empezaremos con algo básico, simplemente haciendo echo antes y después de una llamada. Y, para dar un valor añadido, ya que somos capaces de ejecutar algo antes de hacer cualquier llamada, podremos detectar cuando simplemente se pulsa enter. Ya que, cuando pulsamos enter, la primera función, precmd, no se va a ejecutar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash function postcmd() { if [ "${#COMANDOS[@]}" -gt 1 ]; then HISTORY=$(HISTTIMEFORMAT= history 1) echo "COMANDO EJECUTADO: "${HISTORY:7} fi; COMANDOS=(); } function precmd() { COMANDOS+=("$BASH_COMMAND"); if [[ "$BASH_COMMAND" != "$PROMPT_COMMAND" ]]; then echo "INICIA EJECUCIÓN: "$BASH_COMMAND fi } PROMPT_COMMAND="postcmd" trap 'precmd' debug |
Trabajando un poco en este código podremos ser capaces, por ejemplo de guardar un log de todo lo que los usuarios ejecutan, simplemente introduciendo:
1 | logger $BASH_COMMAND |
En lugar del echo «INICIA EJECUCION». Así podemos hacer que el sistema sea totalmente transparente al usuario. Además, para completar el registro podremos incluir otra función:
1 2 3 4 5 | function errcmd() { echo "ERROR EJECUTANDO: $BASH_COMMAND en linea $LINENO Codigo de error: $?" } trap 'errcmd' err |
Que vinculamos a cualquier error. Es decir, cancelación de ejecución o que el código de salida de lo que sea que hayamos llamado no sea 0. Por supuesto, podríamos ayudarnos de más traps como int (para Control+C), quit (para Control+\), term (para cuando se mata el proceso), etc.
Bueno, y, hagamos algo interesante como evitar que el usuario ejecute cosas que no queremos que ejecute:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | shopt -s extdebug function denyaccess () { if [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ]; then return fi local this_command=`HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ $ if [ "shopt -u extdebug" == "$this_command" ]; then return 0 elif [[ "$this_command" =~ ping ]]; then return 0 fi echo "ACCESO DENEGADO para: $this_command" return 1 } trap 'denyaccess' DEBUG |
En este caso, haremos return 0, sólo cuando ejecutemos shopt -u extdebug y el comando ping. Mostrando el texto «ACCESO DENEGADO» si queremos ejecutar cualquier otra cosa. Esto en la práctica no vale de nada, tendríamos que introducir muchas restricciones o tal vez denegar (return 1) ciertas palabras, manteniendo el return 0 por defecto. Pero nos da una idea de cómo funciona.
Gracias a la opción extdebug, esta función es capaz de denegar la ejecución de la orden que hemos llamado en función del valor de retorno de la función denyaccess().
En este caso, el argumento -s de shopt, activa (set) esta capacidad. Del mismo modo, cuando utilizamos -u, la desactiva, y por eso esa orden está permitida, porque es un programa de ejemplo.
Para todo lo demás, incluso nos podemos servir de expresiones regulares para Bash, o incluso la llamada a una función.
Y, para terminar, vamos a hacer sustituciones de órdenes dentro de un comando. O lo que es lo mismo, cambiar el comando que vamos a ejecutar. Podríamos afectar a cualquier parte de la orden ejecutada, aunque para hacer un sencillo ejemplo, vamos a cambiar las llamadas a sudo por gksudo, así vemos un bonito entorno gráfico y será más llevadero para el usuario:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/bin/bash shopt -s extdebug function changesudo() { if [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ]; then return fi local this_command=`HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ ]*/$ if [ "shopt -u extdebug" == "$this_command" ]; then return 0 fi eval ${this_command/sudo/gksudo} return 1 } trap 'changesudo' DEBUG |
Incorporar a nivel de sistema estos scripts
Los scripts que hagamos utilizando estas técnicas podemos cargarlos a nivel de usuario, introduciendo:
1 | source script.sh |
en el archivo ~/.bashrc o a nivel de sistema añadiendo esa línea en /etc/profile , /etc/bash.bashrc , o, mejor aún, en un nuevo archivo dentro de /etc/profile.d/
En las próximas semanas quiero publicar algunos ejemplos en los que veremos, aún más, la potencia de estas acciones.
Pingback: Bash: ¿Cómo ejecutar código antes y después de cada comando? Logging, monitorización, notificaciones y mucho más | PlanetaLibre /
Pingback: Bash: ¿Cómo ejecutar código antes y después de cada comando? Logging, monitorización, notificaciones y mucho más – Poesía Binaria – ProyectoTicTac /
Awesome and interesting article. Great things you’ve always shared with us. Thanks. Just continue composing this kind of post.
The website is looking bit flashy and it catches the visitors eyes. Design is pretty simple and a good user friendly interface.
Your dedication to showcasing the biggest web slots is truly commendable. Thank you. สล็อตเว็บใหญ่
I just idea it might be a plan to post incase any other person was having issues inquiring about yet I am somewhat uncertain in the event that I am permitted to put names and addresses on here. pasar123 gacor
Wow what a Great Information about World Day its incredibly charming instructive post. an obligation of appreciation is all together for the post. 먹튀검증
On this page, you’ll see my profile, please read this data. 먹튀검증
This topic resonates with me. It’s time for manufacturers to step up and improve slot durability. เว็บสล็อตแตกง่าย
I propose only great alongside legitimate information, subsequently picture it: European travel booking platform
On this page, you’ll see my profile, please read this data. แหล่งรวมสล็อตทุกค่าย
In this specific article, you will see a synopsis, fulfill peruse this post. เว็บสล็อตโรม่า
It is particularly conventional, however investigate the tips amid this street number. เกมป๊อกเด้งออนไลน์
So it is intriguing and great composed and see what they think about other individuals. 대구맛집
This is exceptionally engaging, however , it is vital that will mouse tap on the association: 안전놀이터
This is a brilliant blog! I’m very happy with the comments!..
These sites are extremely required, you can take in a great deal. รัก นะ ภาษา จีน
Magnificent dispatch! I am to be sure getting well-suited to over this data, is genuinely neighborly my amigo. In like manner awesome blog here among a significant number of the exorbitant data you gain. Hold up the advantageous procedure you are doing here. ประวัติ ภาษาจีน
I am scanning for and I need to post a comment that «The substance of your post is magnificent» Great work! ที่เที่ยวประเทศไทย
I need to seek destinations with important data on given point and give them to educator our feeling and the article. ประวัติ นัก ร้อง ลูกทุ่ง
I no uncertainty esteeming each and every bit of it. It is an amazing site and superior to anything normal give. I need to grateful. Marvelous work! Every one of you complete an unfathomable blog, and have some extraordinary substance. Keep doing stunning. ปลา สวยงาม ที่ นิยม เลี้ยง ใน ไทย
These you will then observe the most vital thing, the application gives you a site an effective critical web page: นักแสดงใน มูนไนท์
It is great, yet take a gander at the data at this address. เกมผีเล่นกับเพื่อน
I am scanning for and I need to post a comment that «The substance of your post is magnificent» Great work! สูตรน้ำผัดไทย เข้มข้น
I am searching for and I want to post a remark that «The substance of your post is magnificent» Great work! หนังแนวผจญภัยในป่า
An obligation of appreciation is all together for the better than average blog. It was amazingly useful for me. I m playful I found this blog. Thankful to you for offering to us,I too reliably increase some new helpful learning from your post. อาหารจาน หลัก ไทย
This is such a great resource that you are providing and you give it away for free. I love seeing blog that understand the value of providing a quality resource for free. تصليح طباخات
This is essential, however it’s important to enable you to make a beeline for it weblink: concierge doctor naples
thanks this is good blog.
This blog website is pretty cool! How was it made !
El texto que has proporcionado es un tutorial sobre cómo ejecutar scripts antes y después de comandos de Bash, lo que te permite realizar acciones automatizadas o de control antes y después de la ejecución de los comandos. Aquí hay un resumen de los puntos principales que se cubren en el tutorial:
To run code before and after each command, you can utilize shell scripting or shell function in your shell configuration file (e.g., .bashrc, .zshrc, etc.). Below is an example of how you can achieve this in Bash
Additionally, the theme includes a blockquote element styled from the Journal admin Typography Style, allowing users to edit font settings, line-height, margin, padding, and the border on the left.
Even the mass of the throat, but the laughter of the lacinia is invested in the vulputate pain. Curabitur pharetra, pure a commodore dignissim, wisdom no time but, and varius no urn at the bow.
The integration of advanced typography styles and optional fluid columns allows for flexible and dynamic layouts that adapt well to different screen sizes and resolutions.
The incorporation of advanced typography styles adds a level of sophistication to the content, enhancing readability and aesthetic appeal.
It’s intriguing to see the emphasis on enhancing system flexibility through the integration of pre and post-execution scripts in Bash.
The emphasis on a flat frequency response and tight low end in the preset underscores the importance of accurate audio monitoring in the studio environment.
With its blend of strategy and deduction, Wordle offers a refreshing change of pace from other puzzle games.
The flexibility to edit font settings, line-height, margin, padding, and even add borders allows for tailored design choices.
Authors have the freedom to create unlimited blog posts, displayed in Grid or List views, complemented by the renowned Items per Row feature for customizable presentation
Convertidor Mp3 is an indispensable tool for music lovers and digital enthusiasts alike. With its intuitive interface and lightning-fast conversion capabilities, this converter simplifies the process of transforming audio files into the popular MP3 format.
You can adjust the functions to suit your specific needs, such as implementing logging, monitoring, notifications, etc.
These are just a few examples of how you can incorporate pre-execution and post-execution scripts into your Bash environment to enhance flexibility and automation.
The blog content showcases the versatility of the platform, enabling authors to express themselves creatively while providing an engaging reading experience for visitors.
The blockquote element, styled from the Journal admin Typography Style, allows for customization of font settings, line-height, margin, padding, and border. This flexibility enables users to tailor the appearance of blockquotes to match their website’s design aesthetic.
From sophisticated typography styles to customizable layouts, it provides a versatile platform for expressing your ideas and engaging your audience.
Sebagai Guru Besar, Prof. Erniati diharapkan akan memimpin dengan teladan dan memberikan inspirasi bagi para mahasiswa, staf, dan rekan sejawatnya.
Casinos are the playgrounds of Lady Luck. 로즈카지노
Let’s embrace the versatility of Bash for these tasks!
Heya i’m for the primary time here. I came across this board and I in finding It truly useful & it helped me out much. I’m hoping to provide something again and help others such as you aided me.
Trading
Can you crack the code and guess the secret word in today’s edition of Wordle? Wordle nyt
ufa789 เว็บแทงบอลที่ใหญ่ และการเงินมั่นคงที่สุด สล็อตออนไลน์ ไม่มีขั้นต่ำ ใช้ทุนน้อย เล่นได้ทุกเกม
สล็อต ufa789 ผู้ให้บริการสปอร์ตออนไลน์ และคาสิโนเต็มรูปแบบ เล่นเพลินเกินห้ามใจ ทำกำไรได้ทุกวัน