Bash Scripting – el “arma” secreta de los holgazanes

Introducción

Este es el último artículo de esta serie que hemos publicado, Aquí presentaremos un concepto llamado scripting.

Esta será una breve introducción al Bash scripting (secuencias de comandos). Hay mucho más que puedes hacer, pero mi objetivo aquí es ayudarte a comenzar y darte lo suficiente para que puedas hacer un trabajo útil.

Esta sección reúne mucho de lo que aprendimos en artículos anteriores (los verás referidos a menudo). Si algunas de estas cosas realmente no tienen sentido, es posible que debas revisar los artículos anteriores y actualizar tu memoria.

¿Qué es?

Una secuencia de comandos Bash en términos informáticos es similar a un guion en términos teatrales. Es un documento que indica qué decir y qué hacer. Aquí, en lugar de que una persona lea y actúe el guion, la computadora lo lee y actúa (o ejecuta).

Un script Bash nos permite definir una serie de acciones que la computadora realizará sin que tengamos que ingresar los comandos nosotros mismos. Si una tarea en particular se realiza con frecuencia, o es repetitiva, un script puede ser una herramienta útil.

Una secuencia de comandos Bash es interpretada (leída y aplicada) por algo llamado intérprete. Hay varios intérpretes en un sistema Linux típico, pero hemos estado aprendiendo la shell Bash, así que presentaremos los scripts de bash aquí.

Cualquier cosa que puedas ejecutar en la línea de comando puedes colocarla en un script y se comportarán exactamente igual. De igual manera, cualquier cosa que puedas poner en un script, puedes ejecutarla en la línea de comandos y nuevamente funcionará exactamente igual.

Es importante comprender la declaración anterior al crear scripts. Al probar diferentes partes de tu script, a medida que lo construyes, a menudo es más fácil ejecutar sus comandos directamente en la línea de comandos.

Un script es solo un archivo de texto sin formato y puede tener cualquier nombre que desees. Los creas de la misma manera que lo harías con cualquier otro archivo de texto, con un simple editor de texto antiguo (como VI, que vimos en este artículo).

Un simple ejemplo

A continuación, se muestra un script simple. Te recomiendo que crees un archivo similar y lo ejecutes para tener una idea de cómo funcionan. Este script imprimirá un mensaje en la pantalla (usando un programa llamado echo) y luego nos dará una lista de lo que está en nuestro directorio actual.

echo <mensaje>

Vamos a desglosarlo:

  • Línea 1 – Comencemos por echar un vistazo a nuestro script. Linux es un sistema sin extensión, por lo que no es necesario que los scripts tengan una extensión .sh. Sin embargo, es común ponérselas para que sean fáciles de identificar.
  • Línea 2 – La primera línea de un script siempre debe ser esta línea. Esta línea identifica qué intérprete debe usarse. Los primeros dos caracteres se conocen como shebang. Después de eso (importante, sin espacios) es la ruta hacia el intérprete.
  • Líneas 3 y 4 – Todo lo que sigue a un # es un comentario. El intérprete no ejecutará esto, solo está aquí para nuestro beneficio. Es una buena práctica incluir tu nombre y la fecha en que escribiste el script, así como una descripción rápida de una línea de lo que hace el script
  • Línea 6 – Usaremos un programa llamado echo. Simplemente imprimirá lo que coloques después, como argumentos de línea de comandos, en la pantalla. Útil para imprimir mensajes.
  • Línea 7 – El siguiente paso de nuestro script es imprimir el contenido de nuestro directorio actual.
  • Línea 9 – Un script debe tener el permiso de ejecución antes de poder ejecutarse. Aquí solo estoy demostrando que el archivo tiene los permisos correctos.
  • Línea 12 – Ahora ejecutamos el script. Explicaré por qué necesitamos el ./ un poco más abajo.
  • Líneas 13 y 14 – El resultado de correr (o ejecutar) nuestro script.

Uf. Aquí se cubrieron muchos puntos importantes con bastante rapidez. Ahora echemos un vistazo a ellos con más detalle.

Puntos importantes

shebang

La primera línea de un script debe indicarle al sistema qué intérprete se debe usar en este archivo. Es importante que esta sea la primera línea del script. También es importante que no haya espacios. Los dos primeros caracteres #! (shebang) le dice al sistema que directamente después será una ruta hacia el intérprete que se utilizará. Si no sabemos dónde está ubicado nuestro intérprete, entonces podemos usar un programa llamado which para averiguar.

which <programa>

Si dejamos esta línea, entonces nuestro script Bash aún puede funcionar. La mayoría de los shells (bash incluido) asumirán que son el intérprete si no se especifica uno.

Sin embargo, es una buena práctica incluir siempre al intérprete. Más adelante, tu u otra persona pueden ejecutar tu script en condiciones en las que bash no sea el shell actualmente en uso y esto podría conducir a resultados indeseables.

El nombre

Linux es un sistema sin extensión. Eso significa que podemos llamar a nuestro script como queramos y no afectará su ejecución de ninguna manera. Si bien es típico poner una extensión .sh en nuestros scripts, esto es solo por conveniencia y no es obligatorio. Podríamos nombrar nuestro script arriba simplemente myscript o incluso myscript.jpg y todavía se ejecutaría muy felizmente.

Comentarios

Un comentario es solo una nota en el script que no se ejecuta, simplemente está ahí para tu beneficio. Los comentarios son fáciles de poner, todo lo que necesitas hacer es colocar un símbolo de numeral (#) y luego cualquier cosa que consideres un comentario. Un comentario puede ser una línea completa o al final de una línea.

Es una práctica común incluir un comentario en la parte superior de un script con una breve descripción de lo que hace el script y también quién lo escribió y cuándo. Estas son solo cosas básicas que las personas a menudo desean saber sobre un script.

Para el resto del script, no es necesario comentar cada línea. La mayoría de las líneas explicarán por sí mismas lo que hacen. Solo coloca comentarios para líneas importantes o para explicar un comando en particular cuya operación puede no ser inmediatamente obvia.

¿Porqué el ./ ?

Linux está configurado tal cual, en gran parte por razones lógicas. Esta peculiaridad en realidad hace que el sistema sea un poco más seguro para nosotros. Primero un poco de conocimiento de fondo.

Cuando escribimos un comando en la línea de comandos, el sistema se ejecuta a través de una serie preestablecida de directorios, buscando el programa que especificamos. Podemos encontrar estos directorios observando una variable particular llamada RUTA.

El sistema buscará en el primer directorio y, si encuentra el programa, lo ejecutará; de lo contrario, comprobará el segundo directorio, etc. Los directorios están separados por dos puntos (:).

El sistema no buscará en ningún directorio aparte de estos, ni siquiera buscará en su directorio actual. Sin embargo, podemos anular este comportamiento al proporcionar una ruta.

Cuando lo hacemos, el sistema dice efectivamente: “Ah, me has dicho dónde buscar para encontrar el script, así que ignoraré la RUTA e iré directamente a la ubicación que has especificado”.

Recordarás que en el artículo 2 (Navegación básica) que un punto (.) Representa nuestro directorio actual, así que cuando decimos ./myscript.sh, en realidad, le estamos diciendo al sistema que busque en nuestro directorio actual para encontrar el script.

También podríamos haber usado una ruta absoluta (/home/cesar/linuxtutorialwork/myscript.sh) y habría funcionado exactamente igual, o una ruta relativa si no estamos actualmente en el mismo directorio que el script (./linuxtutorialwork/myscript.sh).

Si fuera posible ejecutar scripts en tu directorio actual sin este mecanismo, sería fácil, por ejemplo, que alguien creara un script malicioso en un directorio particular y lo nombrara ls o algo similar. La gente lo ejecutaría inadvertidamente si quisieran ver qué había en ese directorio.

Permisos

Un script debe tener el permiso de ejecución antes de que podamos ejecutarlo (incluso si somos el propietario del archivo). Por razones de seguridad, no tiene permiso de ejecución de forma predeterminada, por lo que debes agregarlo. Un buen comando para ejecutar para garantizar que tu script esté configurado correctamente es chmod 755 <script>.

Variables

Una variable es un contenedor para una simple pieza de datos. Son útiles si necesitamos resolver algo en particular y luego usarlo más adelante. Las variables son fáciles de establecer y consultar, pero tienen una sintaxis específica que se debe seguir exactamente para que funcionen.

  • Cuando establecemos una variable, especificamos su nombre, seguido directamente por un signo igual (=) seguido directamente por el valor. (Por lo tanto, no hay espacios a ambos lados del signo =).
  • Cuando nos referimos a una variable, debemos colocar un signo de dólar ($) antes del nombre de la variable.

Un simple ejemplo.

Argumentos de línea de comandos y más

Cuando ejecutamos un script, hay varias variables que se configuran automáticamente para nosotros. Éstas son algunas de ellas:

  • $0: el nombre del script.
  • $1 – $9 – Cualquier argumento de línea de comandos dado al script. $1 es el primer argumento, $2 el segundo y así sucesivamente.
  • $# – Cuántos argumentos de línea de comando se le dieron al script.
  • $* – Todos los argumentos de la línea de comandos.

Hay otras variables, pero estas deberían ser suficientes por ahora.

Acento

También es posible guardar la salida de un comando en una variable y el mecanismo que usamos para este el acento () (Ten en cuenta que es un acento invertido, no una comilla simple.

Un script de copia de seguridad de muestra

Ahora pongamos lo que hemos aprendido hasta ahora en un script que realmente hace algo útil.

Mantengo todos mis proyectos en directorios separados dentro de un directorio llamado projects en mi directorio de inicio. Regularmente hago una copia de seguridad de estos proyectos y los guardo en carpetas con fecha dentro de un directorio llamado projectbackups también en mi directorio de inicio.

Notarás que he usado rutas relativas en el script anterior. Al hacer esto, he hecho que el script sea más genérico. Si uno de mis compañeros de trabajo quisiera usarlo, podría darles una copia y funcionaría igual de bien para ellos sin modificaciones.

Siempre debes pensar en hacer que tus scripts sean flexibles y genéricos para que otros usuarios puedan usarlos fácilmente o adaptarlos a situaciones similares. Cuanto más reutilizables sean tus scripts, más tiempo los usarás, menos trabajo tienes que hacer :)

Sentencias if

Entonces, el script de respaldo anterior me hace la vida un poco más fácil, pero ¿qué pasa si me equivoco? El script puede mostrar mensajes de error. En el siguiente ejemplo, presentaré las sentencias if. Solo las mencionaré brevemente. Deberías poder calcular su uso a partir del ejemplo y las notas a continuación.

Vamos a desglosarlo:

  • Línea 6 – Nuestra primera sentencia if. El formato es importante. Observa dónde están los espacios, ya que son necesarios para que funcione correctamente. En esta declaración, preguntamos si el número de argumentos ($ #) no es igual a (! =) Uno.
  • Línea 8 – Si no, entonces el script no se ha invocado correctamente. Imprime un mensaje explicando cómo debe usarse.
  • Línea 9 – Debido a que el script no se ha invocado correctamente, deseamos salir del script antes de continuar.
  • En la línea 10 Para indicar el final de una sentencia if, tenemos una sola línea que tiene fi (si está al revés).
  • Línea 11 – Las sentencias if pueden probar muchas cosas diferentes. Aquí el signo de exclamación (!) Significa que no, la -d significa 'la ruta existe y es un directorio'. Entonces la línea se lee como 'Si el directorio dado no existe'
  • Línea 22 – Es posible pedirle al usuario una entrada. El comando que usamos para eso es read. read toma un solo argumento, que es la variable para almacenar la respuesta.
  • Línea 23 – Veamos cómo respondió el usuario y actúa en consecuencia.

Truco

Notarás que ciertas líneas están sangradas en el código anterior. Esto no es necesario, pero generalmente se considera una buena práctica, ya que hace que el código sea mucho más fácil de leer.

Truco

Las declaraciones if utilizan un comando llamado test. Si deseas conocer todas las diferentes comparaciones que puedes realizar, echa un vistazo a la página del manual para test.

Resumen

Lo que aprendimos

#!

Shebang. Indica con qué intérprete se debe ejecutar un script.

echo

Imprime un mensaje en la pantalla.

which

Te dice el camino a un programa en particular.

$

Colocado antes de un nombre de variable cuando nos referimos a su valor.

`

Se usa para guardar la salida de un programa en una variable.

date

Imprime la fecha.

if [ ] then else fi

Realiza lógica condicional básica.

Conceptos importantes

Comportamiento igual

Cualquier cosa que puedas hacer en la línea de comandos se puede hacer en un script y se comportará exactamente igual.

Formato

Las secuencias de comandos Bash son particularmente exigentes cuando se trata de formato. Asegúrate de que los espacios se colocan donde se necesitan y no se colocan cuando no se necesitan.

Practicando lo aprendido

Automaticemos:

Para resolver estas actividades, deberá reunir tus habilidades y conocimientos de esta este articulo y todos los artículos anteriores.

  • En primer lugar, piensa en escribir tu propio script de copia de seguridad. Puedes hacerlo tan simple o complejo como quieras. Tal vez comiences con uno muy simple y mejore progresivamente.
  • Ahora observa si puedes escribir un script que te dará un informe sobre un directorio dado. Las cosas sobre las que podría informar incluyen
    • ¿Cuántos archivos hay en el directorio?
    • ¿Cuántos directorios hay en el directorio?
    • ¿Cuál es el archivo más grande?
    • Cualquier otra cosa que se te ocurra.