Cuando una app de Mac no se deja desinstalar: siete causas, un síntoma cada una
Una desinstalación fallida en macOS no es un solo problema. El Finder puede negarse a mover el bundle. El movimiento puede tener éxito y la app puede volver en el siguiente inicio de sesión. El bundle puede desaparecer mientras el helper que te molestaba sigue corriendo. Cada uno es un mecanismo distinto con un arreglo distinto, así que empieza por lo que exactamente hizo tu Mac. Para la secuencia normal, revisa desinstalar por completo; lo que sigue asume que eso ya falló.
Empieza por el síntoma
- "El elemento no se puede mover a la Papelera porque está abierto." Algo está corriendo, con frecuencia no la app que cerraste.
- Se borró, y volvió. Un trabajo de launchd, un perfil, o un gestor de paquetes lo volvió a poner.
- Finder pide una contraseña de administrador. Un
.pkgdejó el bundle propiedad de root. Normal. - No pasa nada. Ni diálogo ni error. El permiso de Gestión de apps está denegado.
rmcomo root dice "Operation not permitted". System Integrity Protection.- Atenuado, o reaparece en un Mac de trabajo. Un perfil de configuración o MDM es su dueño.
1. La app, o uno de sus helpers, sigue corriendo
Finder se niega a mover un bundle cuyos archivos están abiertos, y cerrar el proceso que
puedes ver no detiene todo lo que la app arrancó. El Monitor de Actividad lista cada
proceso, no solo los que tienen una ventana. Busca el nombre del proveedor y lee todo el
conjunto de resultados: una app llamada Foo suele traer Foo Helper, un FooUpdater, y
un bundle de ítem de inicio con un nombre visible que no tiene relación. La ventana de
menú Apple > Forzar salida no es un sustituto, porque solo lista aplicaciones con
presencia de interfaz.
pgrep -fl -i foo
lsof +D /Applications/Foo.app 2>/dev/null | awk '{print $1, $2}' | sort -u
pgrep -fl coincide con la línea de comando completa, así que atrapa un helper cuya ruta
ejecutable lleva el nombre del proveedor aunque su nombre de proceso no lo lleve.
lsof +D reporta cada proceso que mantiene abierto un archivo dentro del bundle.
Forzar la salida del padre no detiene de forma confiable a un helper. Un helper es su propio proceso con su propio PID, así que matar al padre lo deja huérfano a menos que el padre lo desmonte al salir. Y si launchd gestiona al helper, matar a cualquiera de los dos solo le dice a launchd que lo vuelva a arrancar. Eso es la siguiente sección.
Una vista previa de Quick Look o la indexación de Spotlight también pueden mantener abiertos archivos del bundle, y un reinicio limpia ambas cosas. Si el mensaje vuelve, la guía de eliminación de apps de Apple sugiere el modo seguro.
2. Un agente o daemon de launchd la vuelve a traer
Este es el caso de "la borré y volvió", y el que más se diagnostica mal: la gente revisa el Monitor de Actividad, no ve nada, y concluye que la app no estaba corriendo. El arranque bajo demanda significa que eso no es evidencia.
launchd supervisa los trabajos en segundo plano. Un trabajo es una property list con un
Label, un programa, y condiciones para correrlo. RunAtLoad lo arranca cuando el
trabajo carga, KeepAlive lo reinicia cuando termina. Un trabajo sin ninguno de los dos
igual vuelve: MachServices, Sockets, WatchPaths, QueueDirectories, y
StartInterval hacen que launchd arranque el proceso en el momento en que algo lo pide,
así que un helper que queda en reposo después de diez segundos y se reinicia con su
servicio Mach se ve ausente cada vez que revisas.
Las definiciones viven en tres sitios. ~/Library/LaunchAgents es solo tu usuario,
dentro de tu sesión de inicio; /Library/LaunchAgents corre para cada usuario al iniciar
sesión; y /Library/LaunchDaemons corre en todo el sistema como root antes de que nadie
inicie sesión, por eso un daemon sobrevive a una desinstalación manual y un agente
muchas veces no. /System/Library/Launch* es de Apple y está protegido.
launchctl list | grep -i foo
launchctl print-disabled gui/$(id -u) | grep -i foo
grep -l -i foo ~/Library/LaunchAgents/*.plist /Library/LaunchAgents/*.plist \
/Library/LaunchDaemons/*.plist 2>/dev/null
En launchctl list, una etiqueta con un PID está corriendo ahora y una con un guion está
cargada y esperando un disparador; print-disabled lee la base de datos persistente de
estado deshabilitado, un hecho separado de si existe un plist. Lee el candidato con
plutil -p <path> y comprueba que Program o ProgramArguments apunte a la app que
estás quitando: los proveedores no siempre nombran el archivo según la etiqueta que
lleva dentro.
El orden importa
Detén y deshabilita primero el trabajo, luego quita el plist, luego quita la app.
launchctl bootout gui/$(id -u)/com.vendor.foo.helper
sudo launchctl bootout system/com.vendor.foo.daemon
launchctl disable gui/$(id -u)/com.vendor.foo.helper
Borra el plist mientras el trabajo está cargado y launchd mantiene un servicio cuya definición ya no existe en disco; corre hasta el siguiente reinicio y puede dejar una entrada obsoleta en la base de datos de estado deshabilitado. Quitar la app primero es peor: el trabajo vuelve a arrancar contra un ejecutable que ya no está y falla en bucle, de ahí viene "ya no está pero sigue apareciendo en Ítems de inicio".
En macOS 13 y posterior, las apps se registran a través de
SMAppService
y esos registros viven dentro del bundle de la app, así que puede que no haya ningún
plist que encontrar. Esos pertenecen a Background Task Management, controlado en
Ajustes del Sistema > General > Ítems de inicio y extensiones
(guía de ítems de inicio).
3. Es una app del sistema protegida por SIP
System Integrity Protection es una política a nivel de kernel, no un bit de permiso.
Apple la describe como el uso de permisos de kernel para limitar la capacidad de
escritura de archivos críticos del sistema, aplicada "a cada proceso que corre en el
sistema, sin importar si ese proceso corre en sandbox o con privilegios administrativos"
(Apple Platform Security).
Desde Big Sur el contenido del sistema también vive en un volumen separado y sellado
criptográficamente. csrutil status imprime si la protección está activada, y Apple es
explícita en que "no puedes quitar apps que tu Mac necesita", un conjunto que incluye
Mail, Music, Books, Notes, Podcasts, Maps, News y Stocks.
Desactivar SIP para borrar un solo bundle es un mal cambio. Significa arrancar en Recuperación y cambiar una política de seguridad de toda la máquina; en Macs Intel, Apple señala que desactivarlo quita la protección de cada partición del dispositivo de almacenamiento físico, y en Apple silicon el Mac sale de Full Security. Y la ganancia tampoco dura: el volumen del sistema se reemplaza por completo en la siguiente actualización de macOS, y no se recupera espacio utilizable.
Mejor: arrastra el ícono fuera del Dock, quítalo de Ajustes del Sistema > General > Ítems de inicio y extensiones, y si sigue abriendo tus archivos, cambia el manejador con Obtener información > Abrir con > Cambiar todo.
4. La instaló MDM o un perfil de configuración
En un Mac gestionado, una app se puede volver a empujar según el horario del servidor de gestión, y un perfil se puede marcar como no removible. Los síntomas son una eliminación que se deshace horas después, un control atenuado, o una búsqueda en launchd que no encuentra nada porque la reinstalación se dirige de forma remota. Revisa Ajustes del Sistema > General > Gestión de dispositivos; si esa sección no está, el Mac no está gestionado y esta no es tu causa.
profiles status -type enrollment
sudo profiles list
El primero reporta la inscripción a través de Automated Device Enrollment y si está aprobada por el usuario; el segundo lista los perfiles instalados y necesita root. Luego pregúntale a TI. La guía de Apple es preguntarle a quien te dio un perfil que no puedes quitar, y advierte que quitar un perfil borra todo lo que ese perfil configuró, así que uno que lleve tu cuenta de correo se la lleva consigo.
5. Propiedad, y el permiso que falla en silencio
Finder pide una contraseña de administrador. Normal. Un instalador .pkg corre como
root y deja el bundle propiedad de root, así que moverlo necesita autenticación.
Confírmalo con ls -ld /Applications/Foo.app. Vale la pena conocer los recibos ya que
estás aquí: pkgutil --files <id> lista las rutas que puso un paquete, y
sudo pkgutil --forget <id> quita el recibo de /private/var/db/receipts sin borrar ni
un solo archivo.
No pasa nada en absoluto. Sin aviso, sin error, la app sigue en /Applications, y la
herramienta que usaste reporta un fallo vago o recurre a otra cosa. En macOS 14 y
posterior esto normalmente es Gestión de apps, que Apple describe como "Permitir que las
apps actualicen o eliminen otras apps en tu Mac". La señal es que la ruta es escribible
según POSIX y la escritura de todos modos falla:
test -w /Applications/Foo.app && echo "posix says yes"
Si eso imprime y la eliminación sigue sin ocurrir, los permisos no son tu problema. Ve a Ajustes del Sistema > Privacidad y seguridad > Gestión de apps, activa la app que está haciendo la eliminación, y luego vuelve a abrirla, porque muchas apps consultan el permiso solo al arrancar.
Por debajo: tres negativas que se ven iguales
Los permisos POSIX son la primera compuerta: el bundle es propiedad de root, tú no lo
eres, y sudo lo resuelve, porque la comprobación solo se trata de qué usuario eres.
TCC, la capa de privacidad detrás de Ajustes del Sistema, decide después de que POSIX
pasa. Gestión de apps es una compuerta de TCC para una sola operación, modificar o
borrar el bundle de otra app. Ser administrador no la satisface y sudo tampoco, porque
está atada al programa que hace la solicitud y no al usuario, por eso su negativa puede
aparecer como un error genérico sin ningún aviso.
SIP está por debajo de ambas y rechaza a root de plano. Una negativa POSIX establece
EACCES e imprime Permission denied; una negativa de SIP establece EPERM e imprime
Operation not permitted. La primera significa que lo intentes de nuevo con autoridad,
la segunda significa que no hay autoridad con la que volver a intentarlo.
6. Una extensión del sistema o un filtro de red sigue activo
El software de seguridad, los clientes VPN y los productos de virtualización instalan extensiones del sistema. El bundle de la app registra la extensión; no es la extensión. Borra el contenedor mientras la extensión está activa y el registro queda sin dueño, así es como un Mac sigue filtrando tráfico a través de software que crees que quitaste.
systemextensionsctl list
La salida muestra el identificador de equipo, el identificador de bundle, y un estado
como [activated enabled]. La desactivación pertenece a la app contenedora y a menudo
necesita un reinicio, así que corre primero el desinstalador del proveedor.
Desinstalar antivirus en Mac cubre el orden de
desmontaje para esta categoría.
7. Vino de la App Store, o de Homebrew
Apps de la Mac App Store. Borrar el bundle no quita la compra. El caso que atrapa a la gente es el ajuste que Apple describe como "Descargar automáticamente las apps que compraste en la App Store en otras Mac y dispositivos": si un segundo Mac con la misma cuenta todavía la tiene, ese ajuste puede volver a traerla. Desactívalo en App Store > Ajustes.
Casks de Homebrew. Si instalaste con brew install --cask foo, mandar la app a la
Papelera deja a Homebrew creyendo que sigue instalada. brew list --cask todavía
muestra el token, y el siguiente brew upgrade puede reinstalar la app que acabas de
borrar, una causa real de "volvió" sin ningún trabajo de launchd de por medio. Corre
brew uninstall --cask foo en su lugar. El manual de Homebrew describe --zap como
quitar "todos los archivos asociados a un cask" y advierte que "puede quitar archivos
que se comparten entre aplicaciones", así que recurre a esa opción de forma deliberada.
Después de un borrado exitoso: qué se queda atrás
Ítems de inicio y extensiones todavía la lista. O una entrada de "Abrir al iniciar sesión" que apunta a una ruta que ya no existe, o un registro de Background Task Management de un servicio cuyo programa ya no está. Quítala con el botón menos en Ajustes del Sistema > General > Ítems de inicio y extensiones; macOS suele limpiar esto solo después de un reinicio.
Aparece un ícono en la barra de menús al arrancar. Algo todavía carga un binario:
normalmente un launch agent que nunca quitaste, o un helper que el instalador copió a
~/Library/Application Support/<vendor>.
Sobrevive un helper con privilegios. El software que necesitaba root se instala en
/Library/PrivilegedHelperTools/<label> con un /Library/LaunchDaemons/<label>.plist a
juego. Ambos son propiedad de root y están fuera del bundle, así que mandar la app a la
Papelera no toca ninguno de los dos.
ls -la ~/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons \
/Library/PrivilegedHelperTools 2>/dev/null
Para el lado de los datos, revisa archivos sobrantes tras desinstalar.
Hacer este diagnóstico en Mole
La versión manual de este artículo cuesta cinco pantallas: Monitor de Actividad, tres carpetas de launchd, Ítems de inicio y extensiones, Privacidad y seguridad, y Finder. Mole pone las partes que pertenecen a una app en una sola pestaña, y escanear siempre es gratis, así que funciona como diagnóstico de solo lectura la compres o no.
Abre la pestaña Software de Mole. Tiene tres segmentos: el inventario de apps instaladas, las actualizaciones disponibles, y los ítems de inicio. Ese último es el inventario de launchd e ítems de inicio que este artículo te dijo que armaras a mano, así que la causa de "vuelve" es visible antes de borrar y no después.
Selecciona una app y Mole resuelve su identificador de bundle, y luego encuentra qué posee esa identidad: Application Support, Caches, Preferences, Containers, HTTPStorages, y launch agents o daemons cuyo plist de verdad hace referencia a la app en vez de solo compartir una palabra con su nombre. Cada candidato lleva su ruta, tamaño, y la evidencia que lo asoció, y todo lo de baja confianza llega desmarcado.
Confirmar corre el orden que recomienda este artículo, aplicado en vez de recordado.
Mole cierra la app y los helpers anidados dentro de su bundle, da de baja sus helpers de
ítem de inicio, descarga cualquier ítem de arranque aprobado a través de launchctl
antes de quitar su plist, y vuelve a validar cada ruta al momento de borrar. Los borrados
van a la Papelera, así que un error se arregla arrastrando de vuelta.
Luego Mole reporta los elementos omitidos y fallidos con sus rutas en vez de un total de
éxito, así que una fila rechazada porque Gestión de apps está denegado, o porque una
ruta es propiedad de root y la salvaguarda la rechazó, te dice cuál de las causas de
arriba acabas de encontrar. Una herramienta que imprime una marca de verificación sobre
una escritura rechazada es la razón por la que la gente se pasa una tarde preguntándose
por un ícono en la barra de menús. Todo lo que hace Mole corre localmente, y las
operaciones de archivo se añaden a ~/Library/Logs/mole/operations.log. En una terminal,
el Mole CLI es gratis y de código abierto, y
mo uninstall acepta --dry-run así que puedes leer la lista de rutas primero.
Mole no pelea las tres causas que no puede ganar: no va a desactivar SIP ni a quitar una app de fábrica de Apple del volumen sellado, no puede anular un perfil de configuración que reinstala software en un Mac gestionado, y para agentes de seguridad, clientes VPN y productos de virtualización no es un sustituto del desinstalador del proveedor que conoce el orden de desmontaje. Cuando Gestión de apps está denegado, Mole reporta el fallo en vez de escalar privilegios para saltárselo.
Preguntas frecuentes
¿Por qué vuelve una app después de que la borro?
Cuatro causas, en orden aproximado de frecuencia. Un agente o daemon de launchd todavía
tiene una definición de trabajo que apunta a ella y la reinicia con un disparador que no
puedes ver en el Monitor de Actividad. Un registro de cask de Homebrew sobrevivió porque
mandaste la app a la Papelera en vez de correr brew uninstall --cask. En un Mac
gestionado, MDM la volvió a empujar. O el ajuste de la App Store para descargar
automáticamente apps compradas en tus otros dispositivos la trajo de un segundo Mac.
¿Puedo borrar las apps integradas de Apple si desactivo SIP?
Técnicamente sí, y es un mal cambio: una rebaja de seguridad de toda la máquina hecha desde Recuperación, a cambio de un bundle que vuelve en la siguiente actualización de macOS cuando se reemplaza el volumen del sistema sellado. Mejor quítala del Dock y de Ítems de inicio.
Finder pide mi contraseña para borrar una app. ¿Algo está mal?
No. Un instalador .pkg puso el bundle ahí como root, así que moverlo necesita
autenticación. El fallo que vale la pena preocuparse es el opuesto: sin aviso, sin
error, no pasa nada. Eso normalmente es Gestión de apps denegado bajo
Ajustes del Sistema > Privacidad y seguridad, y sudo no lo arregla, porque la
compuerta está atada al programa que pregunta y no al usuario.
Lecturas relacionadas
- Cómo desinstalar apps por completo en Mac para la secuencia normal y las capas de Library que revisa.
- Cómo desinstalar antivirus en Mac para software con extensiones del sistema, donde el orden de desmontaje es todo el trabajo.
- Cómo desactivar programas de inicio en Mac para el lado de launchd e Ítems de inicio una vez que nada te pelea.