
Mi aplicación está escribiendo registros en un directorio, que está codificado como "Registros" y está presente en el directorio de tiempo de ejecución de mi aplicación.
Hoy un cliente me preguntó si era posible tener esos registros en otro lugar (en otra computadora).
Como primera prueba, intenté crear un enlace simbólico:
- Detuve la aplicación.
- Eliminé el directorio "Registros".
- Usando un WSL en mi computadora, creé un enlace simbólico, algo así como
ln -s /mnt/c/Temp_Folder/TestLog/ /mnt/c/<Application>/Logs
. - Inicié mi aplicación.
No vi ningún registro en el directorio C:\Temp_Folder\TestLog\
.
Veo diferentes razones:
- O es una idea completamente estúpida intentar utilizar la tecnología Linux en una computadora con Windows.
- Puede que funcione, pero hay que tener en cuenta algunas cosas adicionales.
Espero que sea la segunda opción, pero en ese caso ¿qué cosas debo tener en cuenta?
Editar despuésHarryLa respuesta de:
¿Por qué usar WSL ln -s
si puedes usar tecnología de Windows, como mklink
? :-)
Me gusta la idea, pero desafortunadamente parece no funcionar, como puedes ver en los siguientes experimentos:
C:\<Runtime_Dir>mklink /D Logs E:\TestLog\
=> result:
29/03/2024 08:21 <SYMLINKD> Logs [E:\TestLog\]
=> Entonces, de hecho, se crea el Logs
enlace simbólico del directorio, pero cuando inicio mi aplicación, parece que ya no escribe ningún registro (veo que se crean en una ventana de consola, pero no están escritos en un archivo).
Algunos otros experimentos: (Recuerdo algo sobre un cruce de antes, pero se me han olvidado los detalles)
C:\<Runtime_Dir>mklink /D /J Logs E:\TestLog\
Local volumes are required to complete the operation.
C:\<Runtime_Dir>mklink /D /H Logs E:\TestLog\
The system cannot find the path specified.
C:\<Runtime_Dir>mklink /J Logs E:\TestLog\
Local volumes are required to complete the operation.
Edit2 después de algunos experimentos más:
Parece no funcionar cuando hago referencia a otra unidad, pero parece funcionar cuando hago referencia a otro directorio en la misma computadora, como puede ver aquí:
C:\<Runtime_Dir>mklink /D Logs C:\Temp_Folder\TestLog\
symbolic link created for Logs <<===>> C:\Temp_Folder\TestLog\
C:\<Runtime_Dir>mklink /D /J Logs C:\Temp_Folder\TestLog\
Junction created for Logs <<===>> C:\Temp_Folder\TestLog\
¡Puedo confirmar que, en ambos casos, se están creando los registros!
En otras palabras, el problema no es que el enlace simbólico/unión de Windows no funcione: el problema está en el hecho de que el enlace simbólico/unión se refiere a otra unidad.
Recuerdo que hay dos, incluso tres formas de crear una unidad en Windows (un mapeo de unidad, un subst (?) y otro (???), todo esto está muy borroso en mi cabeza), y me pregunto si la historia de enlace simbólico/unión podría estar funcionando en un tipo de unidad, pero no en el otro, y si hay una manera de solucionar este problema.
Edit3 después de la respuesta deu1686_gravedad:
Incluso cuando se utiliza la ruta UNC y se tiene el comportamiento configurado "correcto", todavía parece no funcionar:
fsutil behavior query symlinkEvaluation
Local to local symbolic links are enabled.
Local to remote symbolic links are enabled. => That's the one, isn't it?
Remote to local symbolic links are disabled.
Remote to remote symbolic links are disabled.
C:\<Runtime_Dir>mklink /D Logs \\petrvs01\Log\TestLog\
symbolic link created for Logs <<===>> \\petrvs01\Log\TestLog\
Se crea el enlace, pero no se crean archivos de registro allí.
Entonces, como creo que voy por el camino correcto, decidí realizar otra prueba: usar el explorador de Windows para ingresar al Logs
directorio/enlace simbólico/unión y crear un archivo de texto simple, usando el menú contextual del explorador. Esto no funciona debido al siguiente mensaje de error:
He aprendido tres cosas hasta ahora:
- Para crear un enlace simbólico en Windows, utilice
mklink
en lugar del archivoln -s
. Abra un símbolo del sistema como administrador para esto. - Para crear un enlace simbólico/unión a un directorio remoto, debe utilizar la ruta UNC, no la letra de la unidad.
- El permiso para crear enlaces simbólicos/uniones desde y hacia directorios remotos se verifica mediante el
fsutil
comandofsutil behavior query symlinkEvaluation
.
Lo siguiente que necesito aprender: ¿dónde comprobar los permisos de enlace simbólico/destino de unión? Alguien tiene una idea?
Respuesta1
Los enlaces simbólicos en Linux se implementan de manera diferente que en Windows:
- En Windows, un enlace simbólico es una entrada de tabla de archivos que se implementa y manipula mediante llamadas al kernel.
- En Linux, un enlace simbólico es simplemente un archivo de texto con una bandera especial, cuyo contenido es una ruta al destino. (La ruta ni siquiera tiene que ser válida).
Esto significa que Windows no puede seguir los enlaces simbólicos (o enlaces simbólicos) creados a través del Subsistema de Windows para Linux (WSL).
Windows crea enlaces simbólicos usando el comando mklink.
Para más información ver el artículo.
La guía completa para crear enlaces simbólicos (también conocidos como enlaces simbólicos) en Windows.
Para el problema de "Acceso denegado", cito del post crear enlaces simbólicos en una unidad en red parte de respuesta de GambleNerd:
Solución de acceso denegado
Si ejecuta el
mklink /D
comando como administrador y laLink
parte del comando es una ruta de red UNC y recibeAccess Denied
un mensaje de error, siga lo siguiente para resolver potencialmente este problema.
- En el servidor donde(y/o en la PC cliente de Windows aparece el mensaje de error Acceso denegado cuando ejecuta el comando)Se encuentra la
Link
parte del comando, ejecute este comando como administrador en el servidor:fsutil behavior query SymlinkEvaluation
- Si lo ve
Remote to remote symbolic links are disabled.
, ejecute este comando:fsutil behavior set SymlinkEvaluation R2R:1
- Puede ejecutar esto desde la ubicación donde está ejecutando el comando MKLINK y se le deniega el acceso, ya sea en el servidor Windows o en la PC cliente de Windows.
- Ahora intente ejecutar su comando nuevamente y, con suerte, ahora funciona correctamente.
Referencia del enlace: Acceso denegado en mklink
Respuesta2
¿Existe alguna forma de utilizar enlaces simbólicos similares a Linux en una computadora con Windows, refiriéndose a una ubicación en otra computadora?
Es posible, pero es necesario utilizar rutas UNC en lugar de letras de unidad, ya que estas últimas no son necesariamente globales; si bien los volúmenes físicos tienen asignaciones globales, cada sesión de inicio de sesión puede tener sus propias asignaciones privadas además de eso (por ejemplo, el usuario 1 puede tener Y :\ representa una ubicación y el usuario 2 puede hacer que represente otra). Piense en ello como si cada usuario tuviera su propio "espacio de nombres de montaje" en Linux (pam_namespace).
Específicamente, todas las letras de unidad de "recurso compartido de red asignado" son privadas para su sesión de inicio de sesión y no se entenderán en el contexto del kernel cuando se siga el enlace simbólico. Entonces, si el objetivo está en otra máquina, debe usar la ruta UNC sin formato para ello:
cmd /c mklink /d Logs \\FileServer\Trash\Logs
También debe asegurarse de que la evaluación de enlaces simbólicos de local a remoto no se haya deshabilitado a través de fsutil behavior query symlinkEvaluation
.
¿Dónde comprobar los permisos de enlace simbólico/destino de unión? Alguien tiene una idea?
Ejecute icacls
en el objetivo o haga clic derecho en él en el Explorador y vaya a "Propiedades > Seguridad".
icacls \\FileServer\Trash\Logs
Además, enlaces simbólicos y uniones en Windowspodertienen sus propios permisos, que se pueden verificar usando icacls Logs /l
. Dudo que ese sea el problema, ya que el enlace inicialmente heredaría los mismos permisos que un directorio normal, pero podría valer la pena comprobarlo.
Así que primero asegúrese de que la creación de archivos/carpetas funcionesinhay enlaces simbólicos involucrados, es decir, directamente a través de la ruta UNC (o una unidad asignada, no hay diferencia), y solo después de que eso funcione, intente hacer lo mismo a través de un enlace simbólico.
No olvide que si su aplicación se ejecuta como un servicio, con sus propias credenciales (cuenta de servicio), entonces se deben otorgar permisos a esa cuenta; si se ejecuta como "NetworkService", entonces se deben otorgar permisos almáquinacuenta (FOOBAR$). (Y si se ejecuta como "LocalService", nunca tendrá acceso compartido de red).