3 Power Tips + 1 Power Link I8

Resumen: En esta entrega, un ejemplo del poder que tienen la subshells de bash, como solucionar problemas de SELinux con podman, y el uso de la herramienta yq para procesar archivos yaml. Finalmente un link a una entrevista a Linux Torvalds.

Nota: En los ejemplos de comandos el prompt del usuario no privilegiado es "$", mientras que el del superusuario es "#"

Power Tip #1: Crear entornos de bash efímeros usando subshells

Una subshell es una copia del proceso de la shell actual. Una manera de crear una subshell es usando (), lo cual sirve para personalizar el entorno de bash de manera reversible. Por ejemplo, podemos cambiar de directorio y la variable de entorno C (POSIX) para que muestre los mensajes de salida y de error en inglés:

$ echo "$LANG"
es_AR.UTF-8
$ pwd
/home/sergio

Ahora creamos una subshell:

$ (LANG=C; echo "La variable LANG cambia a  $LANG"; cd /algun_dir || cd /tmp ; echo "el directorio actual es $PWD";  myscript.sh)
La variable LANG cambia a  C
-bash: cd: /algun_dir: No such file or directory
el directorio actual es /tmp
-bash: myscript.sh: command not found

Al terminar la subshell, volvemos a la shell madre y tanto el directorio de trabajo como la variable LANG, vuelven a sus valores predeterminados:

$ pwd
/home/sergio
$ echo "$LANG"
es_AR.UTF-8

Power Tip #2: Identificar y solucionar problemas de SELinux al usar volúmenes.

Supongamos que necesitamos probar una configuración en un contenedor:

$ podman run  --name mynginx  -d -v $HOME/sandbox/nginx.conf:/etc/nginx/nginx.conf --pull=never docker.io/library/nginx@sha256:553f64aecdc31b5bf944521731cd70e35da4faed96b2b7548a3d8e2598c52a42

Ahora bien: ¿Qué sucede si el contenedor en realidad, falla al arrancar como lo muestran los logs?:

$ podman logs mynginx 
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/11/24 20:09:21 [emerg] 1#1: open() "/etc/nginx/nginx.conf" failed (13: Permission denied)
nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (13: Permission denied)

Si estás tentado a desactivar SELinux, te recomiendo enfáticamente que leas ¿SELinux? Nah, dejalo en Disabled. Lo que ocurre es que no hay ninguna regla que permita que el contenedor acceda al contexto del archivo nginx.conf del host.

Contexto del archivo:

$ ls -Z  $HOME/sandbox/nginx.conf
unconfined_u:object_r:user_home_t:s0 /home/sergio/sandbox/nginx.conf

Este problema se soluciona fácilmente:

podman stop mynginx
podman rm mynginx
podman run  --name mynginx  -d -v $HOME/sandbox/nginx.conf:/etc/nginx/nginx.conf:Z --pull=never docker.io/library/nginx@sha256:553f64aecdc31b5bf944521731cd70e35da4faed96b2b7548a3d8e2598c52a42

Y ahora el contenedor arrancará sin inconvenientes:

podman ps
CONTAINER ID  IMAGE                                                                                            COMMAND               CREATED         STATUS         PORTS       NAMES
a29c08eda1b1  docker.io/library/nginx@sha256:553f64aecdc31b5bf944521731cd70e35da4faed96b2b7548a3d8e2598c52a42  nginx -g daemon o...  12 seconds ago  Up 12 seconds              mynginx
podman logs mynginx 
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/11/24 21:16:10 [notice] 1#1: using the "epoll" event method
2025/11/24 21:16:10 [notice] 1#1: nginx/1.29.3
2025/11/24 21:16:10y [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19) 
2025/11/24 21:16:10 [notice] 1#1: OS: Linux 4.18.0-553.84.1.el8_10.x86_64
2025/11/24 21:16:10 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 262144:262144
2025/11/24 21:16:10 [notice] 1#1: start worker processes
2025/11/24 21:16:10 [notice] 1#1: start worker process 28
2025/11/24 21:16:10 [notice] 1#1: start worker process 29

Ahora bien, la opción :Z no es mágica, para tener una aproximación a lo que hace veamos el contexto del archivo $HOME/sandbox/nginx.conf:

$ ls -Z  $HOME/sandbox/nginx.conf
system_u:object_r:container_file_t:s0:c369,c839 /home/sergio/sandbox/nginx.conf
Campo Antes Después Comentario
Usuario (SELinux) unconfined_u system_u Pasa de ser un usuario sin restricciones a un usuario gestionado por el sistema
Rol (SELinux) object_r object_r Se mantiene sin cambios
Asignación basada en tipos user_home_t container_file_t Cambia a un tipo de asignación en la cual los contenedores pueden escribir
Rango (SElinux) s0 s0:c369,c839 Este cambio implica que solamente podrá utilizarlo de manera exclusiva un único contenedor

Power Tip #3: Filtrar un archivo de template en formato yaml de Zabbix sin instalar absolutamente nada

Solamente necesitamos podman, en el siguiente ejemplo estamos filtrando todos los triggers estáticos con nivel de severidad HIGH o DISASTER:

podman run --rm -v "${PWD}":/workdir:Z mikefarah/yq  '.zabbix_export.templates[].items[].triggers[] | select(.priority == "HIGH" or .priority == "DISASTER")| {"Trigger": .name}' template_db_mssql_agent2.yaml
Trigger: 'MSSQL: Percentage of the buffer cache efficiency is low'
Trigger: 'MSSQL: Page life expectancy is low'
Trigger: 'MSSQL: Percentage of work tables available from the work table cache is low'
Trigger: 'MSSQL: Service is unavailable'

Fuentes y más recursos

El enlace de esta edición apunta a una entrevista a Linux Torvalds que gira en torno a la evolución del hardware, la IA y su impacto en el Linux y el kernel: Linus Torvalds — Talks about AI Hype, GPU Power, and Linux’s Future . En la actualidad cuestiones como el vibe coding plantean debates importantes, no solamente en Linux sino en el ámbito IT en general.

3 Power Tips + 1 Power Link I7

Resumen: Tips para bash, KDE Plasma y el uso del shell para cambiar entre ambientes de desarrollo. Además, en el Power Link, un artículo de Aaron P. MacSween, en el que discute el uso de AI scraping de sitios web usados de manera no consensuada para entrenar Modelos Extensos de Lenguaje (LLMs).

Power Tip #1: Agrupación de comandos en bash

El shell bash permite agrupar comandos, una funcionalidad tan sencilla como potente, por ejemplo:

{ dnf -y upgrade && systemctl restart httpd mariadb php-fpm ; } || echo "The final status is unsuccessful 🙁"

De esta manera si algunos de los dos comandos falla, mostrará un mensaje de error unificado.

Power Tip #2: Uso de cuadros de diálogos nativos de KDE Plasma en Firefox

Para hacerlo hay que abrir la url about:config y luego setear la preferencia widget.use-xdg-desktop-portal.file-picker en 1.

Set preferences on Firefox

Esto se basa en el uso de XDG Portals que es un elemento de la arquitectura de entornos gráficos. Ellos proporcionan sandboxing, funcionalidad en entornos Wayland y lo que nos interesa en este caso: coherencia en la interfaz del usuario.

Antes 🤐 Después 😎️
Set preferences on Firefox Before and After of setting file picker

Ah... usar la variable de entorno MOZ_USE_XDG_PORTAL no es la manera recomendada, más allá de lo que diga cierto chatbot...

Power Tip #3: [Flask + Linux]: Entornos Seguros usando solo la Shell

Problema Común

Ejecutar una app Flask con DEBUG=True en producción expone trazas de errores, rutas internas y detalles del stack que pueden ser explotados. Un sysadmin o devops con experiencia sabe que una práctica profesional es externalizar la configuración y usar el sistema operativo como interruptor de entorno.

Solución Basada en Linux + Flask

Usá la variable de entorno de Linux FLASK_ENV para alternar entre una configuración segura de Producción (config_prod.py) y una configuración orientada a Desarrollo (config_dev.py).

Archivo Ajuste Crítico Enfoque Operacional
config_dev.py DEBUG = True Enfoque en depuración y agilidad.
config_prod.py DEBUG = False
SECRET_KEY = os.environ.get('PROD_KEY')
Prioridad a la Seguridad y la Gestión de Secretos mediante la shell de Linux.

Fragmento de app.py

import os
from flask import Flask
# Se importan las clases para un código robusto:
from config_dev import DevelopmentConfig 
from config_prod import ProductionConfig

app = Flask(__name__)

if os.environ.get('FLASK_ENV') == 'production':
    # Entorno PROD: Carga DEBUG=False
    app.config.from_object(ProductionConfig) 
else:
    # Entorno DEV: Carga DEBUG=True por defecto
    app.config.from_object(DevelopmentConfig) 

Control desde la Terminal

Entorno Deseado Comando Linux Resultado
Producción export FLASK_ENV=production; python app.py * Debug mode: off (Modo seguro activado por el shell de Linux).
Desarrollo unset FLASK_ENV; python app.py * Debug mode: on (La variable se borra, volviendo al modo de depuración).

✅ Conclusión:

Este patrón convierte tu shell de Linux en un switch seguro de entorno para tu app Flask.

Preguntas de repaso

  1. Seguridad y DevOps (Power Tip #3): ¿Cuál es el riesgo principal de ejecutar una aplicación Flask con DEBUG=True en producción, y cómo permite la variable de entorno de Linux FLASK_ENV que el administrador (sysadmin o devops con experiencia) cambie de manera segura a la configuración de producción (config_prod.py) usando solo un comando en la shell?
  2. Eficiencia en Bash (Power Tip #1): En el ejemplo de agrupación de comandos, ¿cuál es el propósito de encerrar las sentencias de actualización (dnf -y upgrade) y de reinicio de servicios (systemctl restart ...) entre llaves {}, y qué rol juega el operador lógico || en caso de que alguna de estas operaciones falle?
  3. Experiencia de Usuario (Power Tip #2): Si un usuario de KDE Plasma desea que Firefox utilice los cuadros de diálogo nativos del escritorio en lugar de los predeterminados del navegador, ¿qué URL debe abrir y a qué valor debe establecer la preferencia widget.use-xdg-desktop-portal.file-picker?

AI scrapers request commented scripts. ¿Hasta qué punto una actividad es considerada benigina cuando se entrenan LLMs? Y muchas cuestiones para pensar...

3 Power Tips + 1 Power Link I6

Resumen: Tips para KDE Plasma, manejo de directorios temporales e información detallada sobre podman. Además, un link a un post en el cual un líder de ingenería recomienda pasar de Docker a Podman.

Power Tip #1 Reiniciar KDE Plasma sin cerrar sesión

kquitapp6 plasmashell ; plasmashell --replace >/tmp/plasma.log 2>&1 & disown -h

Power Tip #2 Crea un sandbox con limpieza automática usando tmpfiles.d

Podemos tener un directorio al cual usamos como sandbox, por ejemplo para:

  • Descarga de archivos
  • Volcar Logs y dumps temporarios
  • Scripts, código... y cualquier cosa que queremos probar.... por un tiempo.

Pero la idea es que no queremos que esos archivos se almacenen de manera indefinida... entonces:

cat << EOF >  ~/.config/user-tmpfiles.d/user-sandbox.conf 
> d %h/sandbox - - - 7d
> d %h/sandbox/ephemeral - - - 10m
> EOF

Una idea tentadora es usar un directorio como /tmp. Pero no es buena práctica usar ese directorio como sandbox. Luego de crear ese archivo, hay que ejecutar: systemd-tmpfiles --create --user que creará los directorios en las rutas especificadas. El servicio systemd-tmpfiles-clean eliminará periódicamente los archivos más viejos de 7 días del directorio ~/sandbox. El contenido de ~/sandbox/ephermeral en cambio, no se borrará automáticamente excepto que creemos una unit de tipo timer. Sin embargo se puede hacer manualmente mediante systemd-tmpfiles --clean --user. Como siempre entender por qué hacés lo que hacés es fundamental, los manpages son siempre aliados a tener en cuenta aun en pleno hype de la AI.

A propósito... el comando en el PowerTip #1 podría haber usado el directorio del sandbox en lugar de /tmp....

Power Tip #3 Revisar espacios y objetos de manera detallada en Podman

podman system df -v

De esta manera obtenemos información muy útil sobre las imágenes, contenedores y volúmenes que tenemos.

Espacio ocupado por podman

Entrevista a Guido van Rossum, creador de Python, en la cual trata entre temas sobre AI

3 Power Tips + 1 Power Link I5

Resumen: Tips para containers, uso de digests y análisis de seguridad de imágenes y obtener información de imágenes remotas. Además, un link a un post en el cual un líder de ingenería recomienda pasar de Docker a Podman.

Power Tip #1 Etiquetar las imágenes con digest en producción

❌ Mala práctica, apuntar a un tag:

podman run -d --name pass_git localhost/passteiner-ubi9:1

Esta es una mala práctica porque:

  • Es mutable, puede apuntar a otro build
  • También es un error confiar ciegamente usar latest, hoy puede apuntar a una versión, mañana a otra
  • Dificulta el debugging al no saber exactamente qué versión usás

✅ Buena práctica:

podman run -d --name pass-git --pull=never \
  localhost/passteiner-ubi9@sha256:3ca1e63acb24d88fde5e86eb1f476ba69eb740cd43590c37f3a964b5a19f001

Ventajas:

  • Totalmente reproducible y auditable.

  • Evitás actualizaciones sorpresa.

  • Ideal para ambientes de producción, CI/CD, y entornos donde la confiabilidad importa.

Power Tip #2 Examinar vulnerabilidades en imágenes de contenedores

La abstración con que nos proporcionan los contenedores, tal vez nos den una falsa sensación de seguridad, sin embargo, con trivy se pueden escanear en una imagen vulnerabilades por ejemplo:

trivy image docker.io/bitnami/wordpress

Debajo podemos ver un resumen:

Resumen del reporte realizado por trivy

Power Tip #3 Examinar imágenes de contenedores sin necesidad "pullearlas"

skopeo inspect docker://docker.io/ollama/ollama \
  | jq '{Digest: .Digest, Labels: .Labels, UltimaCapa: .Layers[-1]}'
{
  "Digest": "sha256:a5409cb903d30f9cd67e9f430dd336ddc9274e16fd78f75b675c42065991b4fd",
  "Labels": {
    "org.opencontainers.image.ref.name": "ubuntu",
    "org.opencontainers.image.version": "24.04"
  },
  "UltimaCapa": "sha256:45fafbfc0e267e3b61858ae5cb28ff739d901d85e1b60ee62db5dad64ae7c0d5"
}

De esta manera obtenemos:

  • El Digest de la imagen (identificador único inmutable).
  • En qué distro base y versión se construyó la imagen (ubuntu:24.04).
  • El Digest de la última capa, que representa el último cambio al sistema de archivos durante el proceso de build.

El digest de la última capa representa el último cambio al sistema de archivos en el proceso de construcción de la imagen.

Why I Ditched Docker for Podman And You Should Too

Gestión de Contraseñas Usando Contenedores Podman (Update 2025)

En 2023, publiqué un post sobre cómo usar pass con un contenedor Git administrado por Podman. Esa guía fue muy útil como demo inicial, pero desde entonces cambiaron algunas cosas: nuevas versiones de Podman, la aparición de Quadlet, la deprecación de podman generate systemd, y la conveniencia de usar imágenes más estables.

Este post es una actualización 2025 del artículo original, incorporando:

  • Imagen base UBI9 minimal (más liviana y con soporte extendido). Esta imagen, desarrollada por Red Hat, es de tamaño relativamente pequeño, usa una versión reduccida de dnf, llamada microdnf con soporte de módulos y usa software de repositorios - también - de Red Hat.
  • Rootless limpio con UserNS=keep-id.
  • Quadlet para integrar con systemd --user.
  • Volúmenes persistentes para no perder datos ni claves al actualizar la imagen.
  • Endurecimiento SSH (solo claves públicas, nada de contraseñas).

1. Construcción de la imagen

Dockerfile (Dockerfile):

FROM registry.access.redhat.com/ubi9/ubi-minimal

RUN microdnf -y install openssh-server git shadow-utils \
    && microdnf clean all \
    && useradd -ms /bin/bash git \
    && chsh -s /usr/bin/git-shell git

EXPOSE 2222
CMD ["/usr/sbin/sshd", "-D", "-e"]

Construcción:

podman build -t localhost/passteiner-ubi9:1 .

2. Crear volúmenes persistentes

podman volume create git-home
podman volume create ssh-etc

VHOME=$(podman volume inspect -f '{{.Mountpoint}}' git-home)
mkdir -p "$VHOME/.ssh" "$VHOME/.password-store"
cp ~/.ssh/id_ed25519.pub "$VHOME/.ssh/authorized_keys"
chmod 700 "$VHOME/.ssh"
chmod 600 "$VHOME/.ssh/authorized_keys"

Repositorio bare:

podman unshare chown -R 1000:1000 "$VHOME"
podman run --rm -v git-home:/home/git localhost/passteiner-ubi9:1 \
  git init --bare /home/git/.password-store

3. Quadlet (systemd integration)

Archivo ~/.config/containers/systemd/pass_git.container:

[Unit]
Description=pass git over SSH (podman quadlet)
Wants=network-online.target
After=network-online.target

[Container]
Image=containers-storage:localhost/passteiner-ubi9:1
Pull=never

ContainerName=pass_git
Network=pasta
PublishPort=60003:2222

Volume=git-home:/home/git:Z,U
Volume=ssh-etc:/etc/ssh:Z

UserNS=keep-id
LogDriver=journald
Exec=/usr/sbin/sshd -D -e -p 2222 -o PidFile=/tmp/sshd.pid

[Service]
Restart=on-failure

[Install]
WantedBy=default.target

Activación:

systemctl --user daemon-reload
systemctl --user enable --now pass_git.service

4. Probar conexión SSH

ssh -p 60003 git@<IP_DEL_HOST> \
  -o PreferredAuthentications=publickey \
  -o PasswordAuthentication=no \
  'git --version && echo OK'

Debe autenticar con tu clave pública y responder git version ....


5. Probar pass con git

Inicializar pass en tu host y configurar el remoto:

export PASSWORD_STORE_DIR=~/.local/share/pass
pass init "tu_clave_gpg"
cd "$PASSWORD_STORE_DIR"
git remote add origin ssh://git@<IP_DEL_HOST>:60003/home/git/.password-store
git push origin master

Y luego:

pass git push
pass git pull

Diferencias clave respecto al artículo original

  • Imagen: antes Fedora, ahora UBI9 minimal (más estable, soporte hasta 2032).
  • Systemd: antes podman generate systemd, ahora Quadlet (futuro estándar, más limpio).
  • Rootless: antes root dentro del contenedor, ahora UserNS=keep-id.
  • Volúmenes: ahora explícitos (git-home, ssh-etc), evitando pérdidas de datos.
  • Seguridad SSH: solo claves, sin password, PidFile movido a /tmp.

Conclusión

Este enfoque actualizado:

  • Evita perder el repositorio y las claves al recrear el contenedor.
  • Asegura compatibilidad a futuro con Podman + systemd.
  • Se apoya en una base más segura (UBI9 minimal).

👉 Si ya usás el setup original, podés migrar en pocas horas y quedarte tranquilo de que tu gestor de contraseñas pass seguirá funcionando a largo plazo.

3 Power Tips + 1 Power Link I4

Resumen: Tips para curl, ollama y KDE Plasma. Y un link acerca de cómo las organizaciones están usando el open source y el upskilling para responder a las demandas laborales impulsadas por IA

Power Tip #1

Obtener un json con información de diagnóstico a partir de curl. Por ejemplo: una solicitud que devuelva el código de respuesta http, la versión del protocolo http`, la dirección ip, el tiempo de transferencia hasta el primer byte recibido y el tiempo total de la operación completa*:

curl -Ls -o /dev/null -w '{"code":%{response_code},"http":"%{http_version}","ip":"%{remote_ip}","ttfb":%{time_starttransfer},"total":%{time_total}}\n'   https://fast.com | jq

Ejemplo de curl obteniendo json con información de diagnóstico

Power Tip #2

En el PT 2 anterior mostramos como usar un LLM offline. Aquí tenemos un script para bajar e instalar ollama:

#! /usr/bin/bash
cd /tmp || exit 1
curl -LO https://ollama.com/download/ollama-linux-amd64.tgz
sudo tar -C /usr/local -xzf ollama-linux-amd64.tgz
sudo useradd -r -s /bin/false -U -m -d /usr/local/share/ollama ollama
sudo usermod -a -G ollama "$(whoami)"
sudo tee  /etc/systemd/system/ollama.service << 'EOF'
[Unit]
Description=Ollama Service
After=network-online.target

[Service]
ExecStart=/usr/local/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3
Environment="PATH=$PATH

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now ollama

Y ya está listo ollama para usar. 😉

Power Tip #3

Configurar klipper en Plasma para que al copiar una url llame a una acción. A diferencia de lo que ocurre en otros entornos o sistemas operativos, el Portapapeles de Plasma no sirve solamente para cortar/copiar y pegar. Sino que puede realizar tareas que hacen más sencillas las tareas tanto para usuarios finales como para usuarios administradores y/o desarrolladores. Los fundamentos de este Power Tip son:

  1. Una expresión regular, por ejemplo: ^(https?://[^ \t\r\n"'<>]+)$
  2. Una acción comando, por ejemplo: konsole --new-tab -e bash -lc 'curl -I -L -- "%1"; exec "${SHELL:-/bin/bash}" -i'

Dentro de la configuración del Portapapeles (klipper), se pueden realizar esos y otros ajustes.

Configurar una acción en Klipper

Luego al copiar una URL, podemos usar un menú emergente que dispare la acción (en este de acuerdo al ejemplo arriba mencionado el comando curl en konsole). 💪

Configurar una acción en Klipper

2025 State of Tech Talent Report

3 Power Tips + 1 Power Link I3

En esta edición, tips para bash scripting, gestión de paquetes con dnf, y LLM en tu máquina. 😉 Y un link sobre como se refieren los medios de comunicación a la IA.

Power Tip #1

Self-logging script con exec (script con logging incorporado)

#!/bin/bash
LOG_DIR="$HOME/logs"
mkdir -p "$LOG_DIR"
LOG="$LOG_DIR/$(basename "$0")_$(date +%Y%m%d-%H%M%S)_$$.log"
exec > >(tee -a "$LOG") 2>&1
ping -c10 9.9.9.9

La línea exec > >(tee -a "$LOG") 2>&1 sirve para que toda la salida del script también vaya el archivo determinado por la variable $LOG. Comentario: En general 2>&1 es reemplazado por &>, en versiones de bash bastante recientes. ¿Y por qué no usarlo? Porque ese atajo solamente sirve para redireccionar a archivos regulares. Por lo tanto, hay que usar la manera clásica de redireccionamiento de stdin y stderr.

Power Tip #2

Reemplazar un paquete por otro con dnf. Por ejemplo, reemplazar pipewire-pulseaudio, por pulseaudio, en caso de problemas de compatibilidad.

dnf swap pipewire-pulseaudio pulseaudio --allowerasing

Power Tip #3

Usar ollama, para ejecutar y gestionar modelos de AI especializados en lenguaje en tu propia máquina, por ejemplo para explicar el contenido de un archivo:

ollama run gemma3 "Explicar sintéticamente, lo que hace este archivo de reglas de polkit  $(cat /usr/share/polkit-1/rules.d/org.freedesktop.Flatpak.rules)" 

Ollama, LLM en tu propia máquina

Stop Pretending Chatbots Have Feelings: Media's Dangerous AI Anthropomorphism Problem

3 Power Tips + 1 Power Link I2

En esta edición: 3 poderosos consejos para bash, advirtiéndo sobre la letra chica de ellas y una noticia importante sobre certificados SSL/TLS.

Power Tip #1

Agregar de manera inteligente y selectiva la opción pipefail en bash con set -o pipefail a los scripts de bash.

De esta manera, bastará con que un solo comando tenga un estado de salida distinto de 0 para que el resultado final también de distinto de 0. Hay muchas publicaciones e incluso GPTs que aconsejan el uso de pipefail.

Esto puede ser valioso cuando cualquier comando unido por | tiene que terminar sin errores para que tenga sentido continuar con la ejecución del script.

Sin embargo, acá van algunas recomendaciones:

  • Evitar set -o pipefail globalmente al usar comandos como:

    • grep -q
    • head
    • awk 'exit'
    • sed 'q'
  • Activar pipefail solo donde realmente sea necesaria:

(set -o pipefail; comando1 | comando2)
  • O desactivar luego de usarla:
set -o pipefail
comando1 | comando2
set +o pipefail

Power Tip #2

Realizá tus propios tests para decidir si un script tiene que terminar al ocurrir un error

Se puede leer en el Debian Policy Manual que recomienda fuertemente el uso set -e. Esa opción le dice a bash que cuando un comando termina en un estado de salida de distinto de 0 el script debe termina inmediatamente. La cuestión es que esa opción tiene muchas de excepciones (algo que se puede verificar al leer la manpage de bash), lo cual hace el uso de esta configuración poco confiable en scripts de gran complejidad. Tenemos que comprender que bash sabe poco de la semántica. Por ejemplo, considerar este sencillo script:

#! /bin/bash
set -e

cd /home/admin/download
curl -O https://example.com/project.zip
unzip project.zip

El comando curl no tiene exit status distinto de 0 si obtiene http code 404, bash no sabe como cada herramienta externa maneja el exit status. Si el archivo projec.zip ya existe, el comando unzip estará operando sobre el la versión del archivo que probablemente no queremos.

Lo correcto que nosotros mismos le agreguemos la lógica necesaria de acuerdo a lo que estamos necesitando.

Probablemente alguien puede estar tentado a agregarle la opción -f sin embargo la propia manpage de curl dice que no es 100% segura. Además puede haber casos en los que necesitamos saber exactamente el tipo de problema que hubo. En tal caso lo mejor será obtener el http code con curl y evaluar dicho código con bash, es decir hacemos que cada herramienta haga lo mejor que sabe hacer.

Power Tip #3

Usar set -u para forzar a que el script termine con error si hay hay variables no definidas. En general, esta opción tiene menos tiene contraindicaciones que las dos anteriores. Es altamente conveniente combinarla con la herramienta shellcheck. Por ejemplo, en el siguiente script:

#!/bin/bash
set -u
[[ "$DEBUG" == "yes" ]] && echo "Modo debug"
echo "$somevar"
someanothervar="example"
  • No tiene definida la variable DEBUG
  • No tiene definida la variable somevar
  • La variable someanothervar si bien está definida no se usa nunca. No es un error grave, pero al no utilizarse probablemente sea inncesaria, pero es algo que no es detectado por set -u.

ShellCheck

¿Certificados SSL/TLS para direcciones IP?: We've Issued Our First IP Address Certificate

Comparación de systemd-run con nuhup, tmux y screen

systemd-run
Si estamos conectados por ssh y sufrimos una desconexión mientras ejecutamos un comandos, puede representar un problema, desde la interrupción del proceso o la pérdida del acceso a la salida estándar/error del mismo. Existen comandos como nohup que de alguna manera nos ayudan a mitigar esas situaciones, tales como nohup, o multiplexores de terminal como screen y tmux.

Al usar systemd, contamos con una herramienta tan sencilla como poderosa: el comando systemd-run que permite ejecutar un comando muy sencillo como el siguiente en un servicio. O para ser más exactos en una service unit:

systemd-run --user ping 8.8.8.8

Comparación con nohup, tmux/screen

Característica systemd-run nohup tmux / screen
Supervisión del estado Sí, vía systemctl status y journalctl No, se debe usar ps o pgrep Parcial, requiere inspección manual de la sesión
Control del ciclo de vida Completo: iniciar, detener, reiniciar con políticas de reinicio Nulo: solo iniciar, sin reinicio automático Manual: requiere interacción del usuario
Manejo de logs Centralizado en journal, con metadata y timestamps Básico: redirige a nohup.out sin rotación Opcional: solo si se configura logging explícitamente
Integración con el sistema Alta: como unidad de systemd, con cgroup, slices, y logs centralizados Nula: proceso genérico del usuario Baja: proceso de usuario sin integración con systemd
Persistencia tras logout Alta: configurable vía lingering o como unidad del sistema Limitada: depende de configuración de logind Alta (tradicional), pero afectada por KillUserProcesses
Persistencia tras reinicio Posible mediante conversión a unidad persistente o uso de systemd-timer No, se requiere cron, scripts externos No, sesión se pierde tras reboot
Políticas de recursos/aislamiento Completa: límites CPU, memoria, I/O, namespaces, privilegios, etc. Nula: se requiere uso externo de ulimit o nice Nula: requiere herramientas externas
Facilidad de uso interactivo Baja: orientado a ejecución no interactiva Nula: no interactivo Alta: diseñado para interacción, múltiples ventanas/sesiones
Ideal para Tareas ad-hoc, servicios temporales, pruebas controladas Procesos simples que deben continuar tras logout Tareas interactivas largas o sesiones remotas persistentes

Más Ejemplos

Ansible

Advertencia: Los siguiente comandos no son para copiar y pegar sin analizarlos, deben ser ajustados al entorno en los cuales se los desea utiizar. El propósito principal es mostrar la potencia práctica de la herramienta systemd-run.

Objetivo: Ejecutar playbooks críticos en entornos controlados, como servicios temporales autoreiniciables.

systemd-run -p Restart=on-failure -p PrivateTmp=yes -p Description="Provisionar servidores" \
  -p SuccessExitStatus=0 \ 
  -p RestartSec=5 \ 
  -p TimeoutStopSec=30   \ 
  --unit=ansible-run ansible-playbook site.yml -i inventory/prod

Ventajas:

  • Crea un entorno temporal (/tmp aislado).
  • Si falla, se reinicia automáticamente.
  • El log de toda la ejecución queda en journal.

mysqldump

Objetivo: Realizar dumps de bases de datos con límites de memoria y sin cargar el sistema.

systemd-run \
  -p MemoryMax=750M \
  -p MemorySwapMax=150M \
  -p Nice=10 \
  -p Description="Backup de MySQL sin afectar el sistema" \
  --unit=mysql-dump \
  bash -c 'mysqldump --all-databases > /tmp/backup.sql'

Ventajas:

  • Protege al sistema de un uso excesivo de memoria
  • Baja prioridad de batch (Nice=10).
  • Log y control vía systemd.

Azure CLI

Objetivo: Apagar/desasignar todas las VMs del grupo "GrupoDesarrollo" en segundo plano

systemd-run --unit=apagar_vms \
    --service-type=oneshot \
    -p WorkingDirectory=/tmp \
    bash -c 'az login --identity && az vm list -g GrupoDesarrollo --query "[].id" -o tsv | xargs -r az vm deallocate --ids'

Ventajas:

  • Ejecución desacoplada de la terminal.
  • Se puede usar journalctl para auditar el comando.
  • Control sobre el entorno de ejecución

Conclusión

El comando systemd-run es una alternativa más robusta que otros comandos legacy o multiplexores de terminal, ya que permite, no solamente desacoplar el proceso de la terminal sino también poder gestionarlo perfectamente dentro de systend.

Fuentes y más recursos

3 Power Tips + 1 Power Link I1

Power Tip #1

El comando cd - sirve para ir rápidamente al directorio anterior

cd /usr/local/bin
cd /tmp
cd -
pwd
/usr/local/bin

Power Tip #2

La variable HISTTIMEFORMAT agrega una marca de tiempo en el hi:storial de bash

Agegar en ~/.bashrc

HISTTIMEFORMAT="%F %T"

También se puede usar bash-it para realizar la configuración.

Al recargar la configuración, se agregará la marca de tiempo:

234475  2025-06-03 21:54:27 vim  ~/Documentos/Arts/nikola-env/sebelkfloss/files/assets/css/custom.css 
234476  2025-06-02 08:18:37 vim  ~/.config/nvim/lua/core/lazy.lua 
234477  2025-06-04 18:27:09 nohup nikola serve &> /dev/null &
234478  2025-06-04 18:29:38 vim  ~/.config/nvim/lua/core/lazy.lua 
234479  2025-06-04 18:29:57 loadnikola 

Power Tip #3

Usar una herramienta de monitoreo local como wallpaper

El emulador de terminal kitty posee herramientas pequeñas que amplian su funcionalidad. Una de ellas permite mostrar usar la terminal como wallpaper:

Este comando mostrará el panel de la herramienta glances en un entorno Wayland

kitty +kitten panel --edge=background --focus-policy exclusive --detach  glances


Sencillamente un link: Stop disabling SELinux

¡Hasta la próxima!