Desde conceptos básicos hasta técnicas avanzadas de automatización
variable="valor"
echo $variable
export VARIABLE="valor"
env
echo "texto"
printf "Formato" argumentos
read variable
read -s -p "Prompt: " variable
comando > archivo
comando >> archivo
comando 2> archivo
comando &> archivo
comando1 | comando2
comando < archivo
comando << "EOF"
texto
EOF
for archivo in *.txt; do
mv "$archivo" "${archivo%.txt}.bak"
done
find . -name "*.log" -exec rm {} \;
find /ruta -type f -mtime +30 -exec gzip {} \;
rsync -avz --delete origen/ destino/
parallel -j 4 convert {} -resize 800x600 {.}_resized.jpg ::: *.jpg
sed -i 's/foo/bar/g' archivo
awk '{print $1}' archivo
sort archivo | uniq -c | sort -nr
cut -d: -f1 /etc/passwd
join -t: -1 3 -2 3 archivo1 archivo2
# Mover miles de archivos eficientemente
find /origen -type f -name "*.dat" -print0 | xargs -0 -I {} mv {} /destino/
# Procesar archivos en lotes de 100
ls *.log | split -l 100 -d - logs_
for lote in logs_*; do
while read archivo; do
process_file "$archivo"
done < "$lote"
done
# Renombrar archivos con contador
count=1
for archivo in *.jpg; do
mv "$archivo" "foto_$(printf "%04d" $count).jpg"
((count++))
done
grep -E "pattern" archivo
sed -E 's/([0-9]{3})/\1-/g' archivo
awk '/^[A-Z]/ {print}' archivo
[[ $var =~ ^[0-9]+$ ]] && echo "Es número"
# Extraer direcciones IP de logs
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" access.log | sort | uniq -c | sort -nr
if [[ condición ]]; then
comandos
elif [[ condición ]]; then
comandos
else
comandos
fi
case $variable in
patrón1) comandos ;;
patrón2) comandos ;;
*) comandos_default ;;
esac
for item in lista; do
comandos
done
while [[ condición ]]; do
comandos
done
until [[ condición ]]; do
comandos
done
function nombre_funcion {
comandos
return valor
}
nombre_funcion() {
comandos
return valor
}
local variable="valor"
set -e
set -o pipefail
trap 'cleanup_function' EXIT
if ! comando; then
echo "Falló comando" >&2
exit 1
fi
array=(elemento1 elemento2 elemento3)
echo "${array[1]}"
echo "${array[@]}"
echo "${#array[@]}"
declare -A dict
dict[key]="value"
crontab -e
# Ejemplo de entrada crontab
0 3 * * * /ruta/script.sh > /ruta/log.log 2>&1
@reboot /ruta/script.sh
anacron -t /etc/anacrontab -d
# /etc/systemd/system/mitarea.timer
[Unit]
Description=Ejecutar mi tarea diariamente
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
systemctl enable --now mitarea.timer
# Script de backup con rotación
BACKUP_DIR="/backups"
MAX_BACKUPS=30
DATE=$(date +%Y%m%d_%H%M%S)
# Crear nuevo backup
tar -czf "$BACKUP_DIR/backup_$DATE.tar.gz" /datos
# Rotar backups antiguos
ls -t "$BACKUP_DIR"/backup_*.tar.gz | tail -n +$((MAX_BACKUPS + 1)) | xargs rm -f
# Monitoreo de servicio con reinicio automático
SERVICE="nginx"
MAX_RESTARTS=3
LOG_FILE="/var/log/service_monitor.log"
if ! systemctl is-active --quiet "$SERVICE"; then
echo "$(date) - $SERVICE caído" >> "$LOG_FILE"
systemctl restart "$SERVICE"
echo "$(date) - $SERVICE reiniciado" >> "$LOG_FILE"
fi
#!/bin/bash
# Script de build básico
set -e # Fallar en cualquier error
# Instalar dependencias
apt-get update
apt-get install -y build-essential
# Ejecutar tests
if ! make test; then
echo "Tests fallaron" >&2
exit 1
fi
# Crear artefacto
make package
# Subir artefacto
scp package.tar.gz deploy@server:/releases/
#!/bin/bash
# Script de despliegue
APP_DIR="/var/www/myapp"
BACKUP_DIR="/backups/myapp"
RELEASE=$(date +%Y%m%d_%H%M%S)
# Crear directorio de release
mkdir -p "$APP_DIR/releases/$RELEASE"
tar -xzf package.tar.gz -C "$APP_DIR/releases/$RELEASE"
# Backup de la versión actual
if [ -L "$APP_DIR/current" ]; then
cp -a "$APP_DIR/current" "$BACKUP_DIR/$RELEASE"
fi
# Cambiar symlink a nueva versión
ln -sfn "$APP_DIR/releases/$RELEASE" "$APP_DIR/current"
# Reiniciar servicios
systemctl restart myapp
#!/bin/bash
# Git post-receive hook para despliegue automático
while read oldrev newrev refname; do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "$branch" = "main" ]; then
# Pull en el servidor
unset GIT_DIR
cd /var/www/myapp || exit
git pull origin main
make install
fi
done
#!/bin/bash
# Pipeline CI/CD completo
# Variables
PROJECT="myapp"
VERSION=$(git describe --tags)
ARTIFACT="$PROJECT-$VERSION.tar.gz"
# Fases
build() {
make clean
make all
}
test() {
make test
make lint
}
package() {
tar -czf "$ARTIFACT" bin/
}
deploy() {
scp "$ARTIFACT" deploy@prod:/releases/
ssh deploy@prod "/opt/scripts/deploy.sh $ARTIFACT"
}
# Ejecutar pipeline
build && test && package && deploy || exit 1
iptables -L
iptables -L -n -v
iptables -F
iptables -P INPUT DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#!/bin/bash
# Script completo de firewall
# Resetear reglas
iptables -F
iptables -X
iptables -Z
# Políticas por defecto
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Permitir localhost
iptables -A INPUT -i lo -j ACCEPT
# Permitir conexiones establecidas
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Servicios permitidos
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS
# Protección básica
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 30 -j DROP
iptables -A INPUT -m state --state INVALID -j DROP
# Logging
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: "
iptables -A LOGGING -j DROP
iptables-save > /etc/iptables.rules
iptables-restore < /etc/iptables.rules
# Para hacerlas persistentes en reboot (Debian/Ubuntu)
apt install iptables-persistent
netfilter-persistent save
ps aux --sort=-%cpu | head
ps aux --sort=-%mem | head
top -b -n 1 | head -20
nice -n 10 comando
renice 15 -p PID
kill -9 PID
pkill -f "patron"
timeout 10s comando_largo
#!/bin/bash
# Monitoreo de procesos
THRESHOLD_CPU=90
THRESHOLD_MEM=80
LOG_FILE="/var/log/process_monitor.log"
# Obtener procesos problemáticos
PS_OUTPUT=$(ps -eo pid,%cpu,%mem,cmd --sort=-%cpu | awk -v cpu="$THRESHOLD_CPU" -v mem="$THRESHOLD_MEM" '
NR>1 && ($2 > cpu || $3 > mem) {print $0}'
)
if [[ -n "$PS_OUTPUT" ]]; then
echo "$(date) - Procesos excediendo umbrales:" >> "$LOG_FILE"
echo "$PS_OUTPUT" >> "$LOG_FILE"
# Opcional: enviar alerta por email
echo "$PS_OUTPUT" | mail -s "Alerta de procesos" admin@example.com
fi
ip a
ss -tulnp
traceroute ejemplo.com
mtr ejemplo.com
ip addr add 192.168.1.100/24 dev eth0
ip route add default via 192.168.1.1
nmcli connection show
#!/bin/bash
# Configuración de red avanzada
INTERFACE="eth0"
IP_ADDR="192.168.1.100"
NETMASK="24"
GATEWAY="192.168.1.1"
DNS_SERVERS="8.8.8.8 8.8.4.4"
# Configurar IP estática
ip addr flush dev "$INTERFACE"
ip addr add "$IP_ADDR/$NETMASK" dev "$INTERFACE"
ip link set dev "$INTERFACE" up
# Configurar gateway
ip route replace default via "$GATEWAY" dev "$INTERFACE"
# Configurar DNS
echo "nameserver ${DNS_SERVERS// /$'\nnameserver '}" > /etc/resolv.conf
# Verificar conexión
if ! ping -c 1 "$GATEWAY"; then
echo "Error configurando red" >&2
exit 1
fi
last
lastb
grep "Failed password" /var/log/auth.log
find / -type f -perm -4000 -o -perm -2000 -ls
#!/bin/bash
# Script de auditoría de seguridad
AUDIT_DIR="/var/log/audit"
REPORT="$AUDIT_DIR/security_report_$(date +%Y%m%d).txt"
mkdir -p "$AUDIT_DIR"
{
echo "=== Reporte de Seguridad $(date) ==="
echo -e "\nUsuarios con shell:"
grep -v "/nologin$\|/false$" /etc/passwd
echo -e "\nUsuarios con sudo:"
grep -Po '^sudo.+:\K.*$' /etc/group | tr ',' '\n'
echo -e "\nArchivos SUID/SGID:"
find / -type f -perm -4000 -o -perm -2000 2>/dev/null
echo -e "\nConexiones de red activas:"
ss -tulnp
echo -e "\nIntentos fallidos de login recientes:"
lastb | head -20
} > "$REPORT"
chmod 600 "$REPORT"
#!/bin/bash
# Encabezado recomendado para scripts
set -euo pipefail
IFS=$'\n\t'
# Variables en mayúsculas, locales en funciones
readonly CONFIG_FILE="/etc/miapp.conf"
# Manejo de errores
trap 'cleanup' EXIT ERR
# Funciones antes del flujo principal
validate_config() {
local config_file="$1"
[[ -f "$config_file" ]] || { echo "Archivo no existe: $config_file" >&2; return 1; }
}
# Documentación
usage() {
echo "Uso: ${0##*/} [opciones] argumentos"
echo "Descripción breve del script"
}
# Procesar argumentos
while getopts ":hv" opt; do
case "$opt" in
h) usage; exit 0 ;;
v) VERBOSE=true ;;
\?) echo "Opción inválida: -$OPTARG" >&2; exit 1 ;;
esac
done
shift $((OPTIND-1))
# Flujo principal
main() {
validate_config "$CONFIG_FILE"
# Resto del código...
}
main "$@"
set -euo pipefail
para manejo estricto de errores[[ ]]
en lugar de [ ]
para testsshellcheck
logger
para system-wide)