screen, launchd y un watchdog: cómo mantener un bot de Discord vivo sin pagar hosting
Un montaje casero para que un bot de Discord sobreviva al cierre de la terminal, a los reinicios y a los bloqueos silenciosos, sobre una máquina que ya está encendida.

Un bot de Discord que arranca en una terminal muere al cerrar la ventana. Y si el equipo se reinicia, para una actualización o por un corte de luz, se queda muerto. La salida habitual es buscar alojamiento gratuito 24/7, pero si ya tienes una máquina encendida en casa, esa es el host. El autor del montaje usa un Mac mini con 34 días de uptime y coste de alojamiento cero; lo único que paga es la luz.
Frente a un plan gratuito, el proceso no se duerme cuando nadie lo usa —esos planes suelen hibernar el bot y perder los comandos que llegan mientras despierta—, no caduca cuando el proveedor cambia las condiciones y tiene acceso a los ficheros y las herramientas instaladas en la máquina. El precio es la dependencia de la luz y la conexión de casa.
De la terminal al arranque automático
El primer salto es screen, que viene de serie en macOS. Con screen -dmS mybot python3 /Users/me/bot.py el proceso queda lanzado en segundo plano y con nombre. screen -ls muestra la sesión, screen -r mybot se engancha a ella y Ctrl+A seguido de D te desengancha sin matarla. Ojo con Ctrl+C dentro de la sesión: se lleva el bot por delante, y a todo el mundo le pasa una vez. tmux hace lo mismo; nohup es más simple, pero luego no hay pantalla que mirar.
El segundo salto es sobrevivir al reinicio, y ahí entran launchd en macOS y systemd en Linux. La forma que el autor defiende no es lanzar el bot directamente desde el gestor de servicios, sino lanzar un script pequeño que a su vez gestione la sesión de screen. El motivo es práctico: un proceso arrancado por launchd no tiene pantalla a la que engancharse. El script comprueba cada 30 segundos si la sesión existe y la levanta si no, y launchd lo mantiene vivo a él. Dos capas. Antes del primer arranque conviene verificar que la red está levantada, porque justo después de un reinicio todavía no lo está y el bot falla al conectar.
También hay que impedir que la máquina se duerma. pmset -g confirma el estado, y un sleep 0 significa que no lo hará. Que la pantalla se apague da igual. Un equipo sin cabeza, como ese Mac mini, encaja mejor que un portátil.
Vigilar que trabaja, no que respira
El caso peor no es que el proceso muera. Es que siga vivo, Discord lo siga mostrando en línea, ps lo liste y el bot no conteste a nada: una sesión caducada, una cuota agotada, algo atascado por dentro. Un reinicio por caída no se dispara nunca porque nada se ha caído. La solución es que el bot escriba una marca de tiempo cada vez que atiende algo de verdad, y que el vigilante mate el proceso cuando esa marca envejezca. Matarlo basta: la estructura de arriba lo vuelve a levantar.
Hay una trampa que al autor le costó ocho horas de bot caído. Su watchdog comprobaba la conectividad descargando una página entera, 170 KB; en un día malo se pasó del timeout y el vigilante falló mientras el bot estaba muerto. Con una petición HEAD bajó a 0,5 segundos. Si el que vigila es pesado, se rompe antes que el vigilado. Tampoco sirve screen -X hardcopy para volcar la pantalla a un fichero: con interfaces de texto sale vacío. Mejor comprobar que hay proceso hijo y conexión de red establecida.
Para quien opera servicios pequeños sobre hardware propio, el patrón se reutiliza más allá de Discord: supervisión en dos capas, comprobación de trabajo real y un vigilante lo bastante barato como para no ser él el que caiga primero.
