
Мое приложение записывает логи в каталог, который жестко закодирован как "Logs" и находится в каталоге времени выполнения моего приложения.
Сегодня клиент спросил меня, возможно ли хранить эти логи в другом месте (на другом компьютере).
В качестве первого теста я попробовал создать символическую ссылку:
- Я остановил приложение.
- Я удалил каталог «Logs».
- Используя WSL на своем компьютере, я создал символическую ссылку, что-то вроде
ln -s /mnt/c/Temp_Folder/TestLog/ /mnt/c/<Application>/Logs
. - Я запустил свое приложение.
Я не увидел никаких журналов в каталоге C:\Temp_Folder\TestLog\
.
Я вижу разные причины:
- Либо это совершенно глупая идея — пытаться использовать технологию Linux на компьютере с Windows.
- Оба варианта могут сработать, но необходимо учитывать некоторые дополнительные факторы.
Надеюсь, это второй вариант, но в таком случае, что мне нужно принять во внимание?
Редактировать послеГарриответ:
Зачем использовать WSL, ln -s
если можно использовать технологию Windows, например mklink
? :-)
Мне нравится эта идея, но, к сожалению, она, похоже, не работает, как вы можете видеть из следующих экспериментов:
C:\<Runtime_Dir>mklink /D Logs E:\TestLog\
=> result:
29/03/2024 08:21 <SYMLINKD> Logs [E:\TestLog\]
=> Итак, действительно, Logs
символическая ссылка на каталог создается, но когда я запускаю свое приложение, оно, похоже, больше не пишет никаких журналов (я вижу, что они создаются в окне консоли, но они не записываются в файл).
Еще несколько экспериментов: (Я помню что-то о перекрестке, но подробности вылетели из головы)
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.
Редактирование2 после еще нескольких экспериментов:
Похоже, это не работает при обращении к другому диску, но работает, когда я обращаюсь к другому каталогу на том же компьютере, как вы можете видеть здесь:
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\
Я могу подтвердить, что в обоих случаях журналы создаются!
Другими словами, проблема не в том, что символическая ссылка/соединение Windows не работает: проблема в том, что символическая ссылка/соединение ссылается на другой диск.
Я помню, что в Windows есть два, даже три способа создать диск (сопоставление дисков, subst (?) и еще один(???), все это очень размыто в моей голове), и мне интересно, может ли история с символической ссылкой/соединением работать на одном типе дисков, но не на другом, и есть ли способ обойти это.
Редактировать3 после ответаu1686_гравитация:
Даже при использовании UNC-пути и «правильной» настройке поведения, похоже, это все равно не работает:
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\
Ссылка создается, но никаких лог-файлов там не создается.
Итак, поскольку я думаю, что я на правильном пути, я решил провести еще один тест: использовать проводник Windows для входа в Logs
каталог/символическую ссылку/соединение и создать простой текстовый файл, используя контекстное меню проводника. Это не работает из-за следующего сообщения об ошибке:
На данный момент я усвоил три вещи:
- Для создания символической ссылки в Windows используйте
mklink
вместо WSLln -s
. Для этого откройте командную строку от имени администратора. - Для создания символической ссылки/соединения с удаленным каталогом необходимо использовать UNC-путь, а не букву диска.
- Разрешение на создание символических ссылок/соединений из удаленных каталогов и в них проверяется с помощью
fsutil
командыfsutil behavior query symlinkEvaluation
.
Следующее, что мне нужно узнать: где проверить разрешения на назначение симлинка/соединения? Есть у кого-нибудь идеи?
решение1
Символические ссылки в Linux реализованы иначе, чем в Windows:
- В Windows символическая ссылка — это запись в таблице файлов, которая реализуется и управляется вызовами ядра.
- В Linux символическая ссылка — это просто текстовый файл со специальным флагом, содержимое которого представляет собой путь к месту назначения. (Путь даже не обязательно должен быть действительным.)
Это означает, что Windows не может использовать символические ссылки (или симлинки), созданные с помощью подсистемы Windows для Linux (WSL).
Windows создает символические ссылки с помощью команда mklink.
Более подробную информацию смотрите в статье
Полное руководство по созданию символических ссылок (также известных как симлинки) в Windows.
По проблеме «Доступ запрещен» цитирую пост создание символических ссылок на сетевом диске часть ответ GambleNerd:
Исправление ошибки «Отказано в доступе»
Если вы запускаете
mklink /D
команду от имени администратора, аLink
часть команды представляет собой сетевой путь UNC и вы получаетеAccess Denied
сообщение об ошибке, то для возможного решения этой проблемы выполните следующие действия.
- На том сервере, где(и/или на клиентском ПК Windows вы получаете сообщение об ошибке «Отказано в доступе» при запуске команды)часть
Link
команды находится, запустите эту команду от имени администратора на сервере:fsutil behavior query SymlinkEvaluation
- Если вы видите
Remote to remote symbolic links are disabled.
, выполните эту команду:fsutil behavior set SymlinkEvaluation R2R:1
- Вы можете запустить это из того места, где вы запускаете команду MKLINK и получаете отказ в доступе, будь то на самом сервере Windows или на клиентском ПК Windows.
- Теперь попробуйте выполнить команду еще раз, и, надеюсь, теперь она сработает успешно.
Ссылка Ссылка: Доступ запрещен на mklink
решение2
Есть ли способ использовать символические ссылки, подобные Linux, на компьютере с Windows, указывающие на местоположение на другом компьютере?
Это возможно, но вам нужно использовать пути UNC, а не буквы дисков, поскольку последние не обязательно являются глобальными — в то время как физические тома имеют глобальные назначения, каждый сеанс входа может иметь свои собственные частные сопоставления поверх этого (например, пользователь 1 может иметь Y:\, представляющий одно местоположение, а пользователь 2 может иметь его, представляющий другое). Думайте об этом немного как о том, что каждый пользователь имеет свое собственное «пространство имен монтирования» в Linux (pam_namespace).
В частности, все буквы дисков "mapped network share" являются частными для вашего сеанса входа и не будут поняты в контексте ядра при переходе по символической ссылке. Поэтому, если цель находится на другой машине, вам нужно использовать для нее необработанный UNC-путь:
cmd /c mklink /d Logs \\FileServer\Trash\Logs
Вам также следует убедиться, что оценка локальных и удаленных символических ссылок не отключена с помощью fsutil behavior query symlinkEvaluation
.
где проверить разрешения на назначение симлинка/соединения? Есть у кого-нибудь идеи?
Запустите icacls
на целевом объекте или щелкните его правой кнопкой мыши в Проводнике и выберите «Свойства > Безопасность».
icacls \\FileServer\Trash\Logs
Также, символические ссылки и соединения в Windowsможетимеют собственные разрешения, которые можно проверить с помощью icacls Logs /l
. Я сомневаюсь, что это будет проблемой, так как ссылка изначально унаследует те же разрешения, что и обычный каталог, — но это, возможно, стоит проверить.
Поэтому сначала убедитесь, что создание файлов/папок работает.безнепосредственно через путь UNC (или через отображенный диск, без разницы), и только после того, как вы это сделаете, попытайтесь сделать то же самое через символическую ссылку.
Не забывайте, что если ваше приложение работает как служба со своими собственными учетными данными (учетная запись службы), то разрешения должны быть предоставлены этой учетной записи; если оно работает как «NetworkService», то разрешения должны быть предоставленымашинаучетная запись (FOOBAR$). (А если она запущена как «LocalService», у нее никогда не будет доступа к сетевому ресурсу.)