PrivateTmp: el hook escribió el archivo, ¿pero adónde fue?
Un espacio temporal privado oculta el archivo en lugar de borrarlo. Revisa la raíz del proceso antes de cambiar la unidad y luego da una ruta real a los datos compartidos.
Los hooks informan de éxito, y la misma ruta sigue pareciendo vacía desde una shell. Ambas afirmaciones pueden ser ciertas a la vez, porque un servicio de systemd puede vivir en su propio espacio de nombres de montaje con un directorio temporal privado. Una vez entendido eso, la pregunta interesante es si la escritura llegó a funcionar.
Dos directorios temporales, una sola ruta
El ajuste de aislamiento da a la unidad una visión privada de los directorios temporales en lugar de hacerlos de solo lectura. Los procesos fuera de la unidad no pueden ver lo que escribe allí, y todo lo que deja atrás se descarta cuando la unidad se detiene. Por tanto, una ruta impresa por el hook y una ruta comprobada desde una shell pueden referirse a objetos distintos con el mismo nombre.
Es un problema de visibilidad, y parece un problema de pérdida de datos. No se ha borrado nada, porque el archivo simplemente está en un espacio de nombres del que la shell no forma parte. El mismo comando se comporta de forma distinta cuando se ejecuta dentro de la unidad, y esa es la observación que suele resolver la discusión. Lee los ajustes de la unidad antes de concluir nada sobre la escritura.
Separa lo invisible de lo no escribible
Una escritura correcta y una apertura fallida producen pruebas distintas, y esa distinción decide la reparación. Si el hook dice que el archivo se creó pero un lector externo no lo encuentra, tienes una cuestión de espacio de nombres. Si el hook informa de un error de permisos o de una apertura fallida, el archivo nunca se escribió y ningún cambio de espacio de nombres ayudará.
systemctl show [email protected] -p PrivateTmp -p User -p Group -p RuntimeDirectory
systemctl show [email protected] -p MainPID --value
sudo ls -l /proc/PID/root/tmp/client-stateLa ruta de la raíz del proceso expone la propia visión del sistema de archivos del servicio, sujeta a las comprobaciones de permisos sobre ese proceso mientras sigue en ejecución. Lee el diario de la unidad en la misma sesión, porque un error de escritura y un archivo ausente se confunden fácilmente cuando alguien ya ha decidido la causa.
Da a los datos compartidos una ubicación explícita
Los datos que solo necesita el servicio pertenecen a su directorio temporal privado. Los datos que otro proceso debe leer necesitan una ruta definida para ambos, con un propietario, un modo y una caducidad declarados. Decide cuál de los dos casos tienes antes de editar la unidad. La mayoría de estos incidentes vienen de tratar un archivo privado como si fuera compartido.
[Service]
RuntimeDirectory=openvpn-hook-office
RuntimeDirectoryMode=0750Un directorio de ejecución coloca la carpeta bajo el área de ejecución del sistema, la crea para el usuario y el grupo configurados de la unidad y la elimina cuando la unidad se detiene. Añádelo mediante un drop-in para que la unidad del paquete quede intacta, luego recarga el gestor y reinicia esa instancia, aceptando que sus clientes se reconectarán.
Conserva cualquier directorio de ejecución que la unidad instalada ya requiera. Sustituir la lista en lugar de añadir a ella es una forma habitual de romper una función no relacionada que nadie conecta con el cambio.
Dos capas de privilegios pueden no coincidir
El gestor de servicios crea el directorio para el usuario configurado de la unidad, mientras que el demonio VPN puede bajar por separado a su propia cuenta antes de ejecutar un hook de conexión. Son capas distintas, y pueden nombrar identidades distintas.
Un directorio propiedad de root con un modo restrictivo es perfectamente visible para un demonio que ya ha renunciado a sus privilegios, y aun así no puede escribir en él. El error se lee entonces como un problema de permisos aunque la ruta exista exactamente donde esperabas. Compara el propietario del directorio con la identidad que informa el hook. Cuando difieren, el modo nunca fue la cuestión.
Comprueba la identidad con la que se ejecuta realmente el hook antes de cambiar la propiedad. Cambiar el usuario de ejecución del servicio para arreglar un directorio puede alterar el acceso a dispositivos y los privilegios de red en otros lugares, lo que es un precio alto para un problema pequeño.
Verifica toda la entrega
Confirma cuatro cosas a la vez: el hook escribe bajo su identidad real, el lector previsto puede consumir el archivo, los usuarios no relacionados no pueden, y detener la unidad limpia según lo diseñado. Que aparezca un archivo en el directorio temporal compartido del host no es un requisito, y suele ser señal de que el intercambio nunca obtuvo su propia ruta. Prueba el lector tras un reinicio, no solo durante la primera ejecución. El comportamiento de limpieza forma parte del diseño, así que obsérvalo en lugar de suponerlo.
El estado persistente pertenece a un lugar con una vida útil equivalente, ya que un directorio de ejecución está hecho para desaparecer. Elige la ubicación por la vida útil y no por la comodidad. Ese hábito evita la siguiente versión de esta misma investigación.