# ¡Domina Shell Scripting paso a paso! 🚀🔥

---

**Por:** @[Rossana Suarez](@roxsross)

¿Alguna vez has querido automatizar tareas en tu sistema Linux, pero no sabías por dónde empezar? Si la respuesta es sí, ¡este tutorial de **Shell Scripting** es para ti! Hoy aprenderás a crear tu primer script en Bash y cómo sacarle el máximo provecho a este poderoso lenguaje de scripts. 🎯

Ya sea que estés empezando en el mundo de la programación o quieras profundizar en la automatización de sistemas, te guiaré a través de cada paso con ejemplos prácticos y fáciles de seguir.

### ¡Es hora de encender motores y dominar Bash! ⚡

Linux cuenta con varios intérpretes de comandos (shells), como **zsh**, **tcsh**, **ksh**, entre otros. Pero hoy nos enfocaremos en **Bash**, uno de los más populares y versátiles. A través de esta guía, no solo entenderás cómo funciona Bash, sino que crearás scripts que te facilitarán la vida. 💡

---

## 1\. ¿Qué es el **Shebang** en un script? 🔥

El **Shebang** es el primer paso esencial para cualquier script en Bash. Define el intérprete que usará el sistema para ejecutar el script. Se escribe de la siguiente manera:

```bash
#!/bin/bash
```

El símbolo `#!` indica al sistema que debe ejecutar el script con el intérprete especificado (en este caso, Bash). Si incluyes el símbolo `#` al inicio de cualquier línea (excepto el Shebang), esta será tratada como un **comentario**.

```bash
#!/bin/bash
# Este es un comentario
pwd
whoami
```

### 💡 Tip:

Aunque puedes escribir múltiples comandos en una sola línea, separándolos con punto y coma (`;`), es mejor escribirlos en líneas separadas para mantener tu script legible.

---

## 2\. Configurar permisos del script 🛡️

Después de escribir tu script, debes darle permisos de ejecución. Esto se hace con el comando **chmod**:

```bash
chmod +x ./mi_script.sh
```

Ahora podrás ejecutarlo simplemente con:

```bash
./mi_script.sh
```

---

## 3\. Tu primer script en Bash 🎉

El comando más básico en Bash para mostrar texto es **echo**. Vamos a crear un simple script que muestre el directorio actual y el usuario logueado:

```bash
#!/bin/bash
echo "El directorio actual es:"
pwd
echo "El usuario logueado es:"
whoami
```

Guarda tu archivo, dale permisos de ejecución y ejecútalo. ¡Felicidades, acabas de escribir tu primer script en Bash! 🎊

---

## 4\. Uso de variables 🛠️

Las **variables** en Bash te permiten almacenar datos que podrás reutilizar a lo largo de tu script. Existen dos tipos de variables:

### 4.1 Variables de entorno 🌍

Las variables de entorno son definidas por el sistema y se pueden utilizar para obtener información clave, como el directorio de inicio del usuario:

```bash
#!/bin/bash
echo "El directorio de inicio es: $HOME"
```

### 4.2 Variables de usuario 👤

Puedes definir tus propias variables para personalizar el comportamiento del script:

```bash
#!/bin/bash
nombre="Juan"
echo "Hola, $nombre. ¡Bienvenido!"
```

---

## 5\. Sustitución de comandos ⚙️

Puedes almacenar el resultado de un comando en una variable utilizando la **sustitución de comandos**. Existen dos formas de hacerlo:

```bash
mi_directorio=`pwd`
# O también
mi_directorio=$(pwd)
echo "Estás en: $mi_directorio"
```

---

## 6\. Operaciones matemáticas 🧮

Bash también permite realizar cálculos matemáticos básicos utilizando la sintaxis `$(())`. Por ejemplo:

```bash
#!/bin/bash
resultado=$((5 + 5))
echo "El resultado es: $resultado"
```

---

## 7\. Condicional **if-then** ⚖️

Los scripts suelen incluir condiciones para ejecutar diferentes acciones dependiendo de si una operación tiene éxito o falla. Aquí tienes la estructura básica:

```bash
#!/bin/bash
if whoami; then
  echo "¡El comando whoami fue exitoso!"
fi
```

### 7.1 Verificar si un usuario existe 🔍

Un uso común de los condicionales es buscar un usuario en el archivo `/etc/passwd`:

```bash
#!/bin/bash
usuario="miusuario"
if grep $usuario /etc/passwd; then
  echo "El usuario $usuario existe."
else
  echo "El usuario $usuario no existe."
fi
```

---

## 8\. Condicional **if-then-else** 🧭

Si deseas ejecutar una acción cuando la condición **no** se cumple, puedes usar la sentencia **else**:

```bash
#!/bin/bash
numero=15
if [ $numero -gt 10 ]; then
  echo "$numero es mayor que 10"
else
  echo "$numero es menor o igual a 10"
fi
```

---

## 9\. Combinar pruebas ⚡

Puedes combinar varias condiciones utilizando los operadores **AND** (`&&`) o **OR** (`||`):

```bash
#!/bin/bash
if [ -d /home ] && [ -n "$nombre" ]; then
  echo "El directorio y el nombre existen."
fi
```

---

## 10\. Comparaciones numéricas 🔢

Las comparaciones numéricas te permiten comparar valores numéricos utilizando las siguientes operaciones:

* `-eq`: Igual a
    
* `-ne`: No igual a
    
* `-lt`: Menor que
    
* `-gt`: Mayor que
    

---

## 11\. Comparaciones de cadenas 📜

Para comparar cadenas de texto, puedes usar:

```bash
#!/bin/bash
cadena1="hola"
cadena2="adios"
if [ "$cadena1" = "$cadena2" ]; then
  echo "Las cadenas son iguales"
else
  echo "Las cadenas son diferentes"
fi
```

---

## 12\. Comparaciones de archivos 📁

Por último, puedes realizar comparaciones de archivos para verificar si existen, si son directorios, o si tienen permisos específicos:

```bash
#!/bin/bash
archivo="/home/miarchivo.txt"
if [ -f $archivo ]; then
  echo "El archivo existe"
fi
```

---

## Tips y Trucos 🛠️✨

### Activar el modo **debug** en Bash 🐛

A veces, cuando escribimos scripts, es útil poder ver lo que sucede "detrás de las escenas", especialmente para encontrar errores o entender cómo se ejecutan los comandos. **Bash** ofrece un modo de depuración muy útil que puedes activar y desactivar fácilmente.

* Para **activar** el modo de depuración y ver todos los comandos ejecutados, utiliza el comando `set -x`.
    
* Para **desactivar** el modo de depuración y volver a la ejecución normal, usa `set +x`.
    

### Ejemplo:

```bash
#!/bin/bash

# Habilitar modo de depuración
set -x

echo "Este es un mensaje de depuración"
pwd
whoami

# Desactivar modo de depuración
set +x

echo "Este es un mensaje sin depuración"
```

Al ejecutar este script, verás que los comandos ejecutados después de `set -x` aparecerán en la terminal con todos sus detalles, mientras que los comandos después de `set +x` se ejecutarán de manera normal sin mostrar esa información adicional.

Este truco es especialmente útil cuando estás solucionando problemas o depurando scripts complejos. ¡Prueba activarlo y verás cómo te ayuda a entender mejor lo que hace tu script! 🚀

---

## **Ejemplo de Shell Scripting para DevOps: Despliegue básico de una aplicación**

### Descripción:

Este script simula el proceso de despliegue de una aplicación web en un servidor. Realiza tareas como verificar si Docker está instalado, crear una imagen Docker, ejecutar un contenedor, y limpiar recursos después de una actualización.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Si necesitas instalar docker visita la pagina oficial <a target="_blank" rel="noopener noreferrer nofollow" href="https://docs.docker.com/engine/install/" style="pointer-events: none">https://docs.docker.com/engine/install/</a></div>
</div>

### **Script:** `deploy`[`.sh`](http://app.sh)

```bash
#!/bin/bash

# Variables
APP_NAME="mi_demo"
DOCKER_IMAGE="mi_demo:v1"
DOCKER_CONTAINER="mi_demo_app"
DOCKERFILE_PATH="./Dockerfile"
LOG_FILE="/var/log/${APP_NAME}_deployment.log"
PORT=80

# Función para registrar mensajes
log_message() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# Función para manejar errores
handle_error() {
    log_message "ERROR: $1"
    exit 1
}

# Función para verificar si Docker está instalado
check_docker_installed() {
    if ! command -v docker &> /dev/null; then
        handle_error "Docker no está instalado. Por favor, instala Docker para continuar."
    else
        log_message "Docker está instalado. Continuando..."
    fi
}

# Función para construir la imagen Docker
build_docker_image() {
    log_message "Construyendo la imagen Docker..."
    if docker build -t "$DOCKER_IMAGE" -f "$DOCKERFILE_PATH" .; then
        log_message "Imagen Docker construida exitosamente."
    else
        handle_error "Error al construir la imagen Docker."
    fi
}

# Función para ejecutar el contenedor Docker
run_docker_container() {
    log_message "Iniciando el contenedor Docker..."
    if docker run -d --name "$DOCKER_CONTAINER" -p "$PORT:80" "$DOCKER_IMAGE"; then
        log_message "El contenedor $DOCKER_CONTAINER se está ejecutando."
    else
        handle_error "Error al iniciar el contenedor."
    fi
}

# Función para detener y eliminar contenedores antiguos
cleanup_old_containers() {
    log_message "Limpiando contenedores antiguos..."
    if docker ps -a | grep -q "$DOCKER_CONTAINER"; then
        if docker stop "$DOCKER_CONTAINER" && docker rm "$DOCKER_CONTAINER"; then
            log_message "Contenedores antiguos eliminados."
        else
            handle_error "Error al eliminar contenedores antiguos."
        fi
    else
        log_message "No se encontraron contenedores antiguos."
    fi
}

# Función para verificar el estado de la aplicación
check_application_status() {
    log_message "Verificando el estado de la aplicación..."
    local max_attempts=5
    local attempt=1
    while [ $attempt -le $max_attempts ]; do
        if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$PORT" | grep -q "200"; then
            log_message "La aplicación está respondiendo correctamente."
            return 0
        fi
        log_message "Intento $attempt: La aplicación aún no responde. Esperando 5 segundos..."
        sleep 5
        ((attempt++))
    done
    handle_error "La aplicación no respondió después de $max_attempts intentos."
}

# Función principal
deploy_application() {
    log_message "=== Iniciando despliegue de la aplicación $APP_NAME ==="
    
    check_docker_installed
    cleanup_old_containers
    build_docker_image
    run_docker_container
    check_application_status
    
    log_message "Despliegue completado exitosamente. La aplicación está disponible en http://localhost:$PORT"
}

# Crear directorio de logs si no existe
mkdir -p "$(dirname "$LOG_FILE")"

# Ejecutar el despliegue
deploy_application
```

---

### **¿Cómo ejecutar el script?**

1. Crea el archivo `deploy`[`.sh`](http://app.sh) y guarda el contenido anterior en él.
    
2. Asegúrate de que el archivo tenga permisos de ejecución:
    
    ```bash
    chmod +x deploy.sh
    ```
    
3. Ejecuta el script en tu servidor:
    
    ```bash
    ./deploy.sh
    ```
    

---

### **Este ejemplo es ideal para principiantes en DevOps porque:**

* **Introduces conceptos clave como contenedores Docker**.
    
* **Automatizas tareas básicas**, como la creación de imágenes y la gestión de contenedores.
    
* **Simula un flujo de trabajo de despliegue**, una de las tareas más comunes en DevOps.
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">¿Te gustaría agregar más funciones o seguir con ejemplos más avanzados?</div>
</div>

## ¡Recursos!

Aprende los COMANDOS de LINUX mientras juegas

* OverTheWire Por niveles y desde cero. [https://overthewire.org/wargames/](https://overthewire.org/wargames/)
    
* Linux Survival Supera diferentes retos online. [https://linuxsurvival.com/](https://linuxsurvival.com/)
    
* VIM Adventures Juego de acertijos. [https://vim-adventures.com/](https://vim-adventures.com/)
    
* Aprende a manejar una de las herramientas más utilizadas en programación. La terminal de línea de comandos. [https://github.com/jlevy/the-art-of-command-line](https://github.com/jlevy/the-art-of-command-line)
    
* Bootcamp devops by Roxs [https://bootcamp.295devops.com/bash-scripting/l1](https://bootcamp.295devops.com/bash-scripting/l1)
    

## ¡Conclusión! 🚀

Con este tutorial, has dado los primeros pasos hacia el dominio del **Shell Scripting en Bash**. Desde ejecutar comandos básicos hasta usar variables, condiciones y comparaciones, ahora tienes una base sólida para comenzar a automatizar tareas y ser más eficiente en tu entorno Linux. 💻🔥

¡Sigue practicando y pronto te convertirás en un maestro del Shell Scripting! ¿Estás listo para seguir explorando el mundo de Bash? 😉
