
私のアプリケーションは、ハードコードされた「Logs」ディレクトリにログを書き込みます。このディレクトリは、アプリケーションのランタイム ディレクトリの下にあります。
今日、顧客から、これらのログを別の場所 (別のコンピューター) に置くことは可能かどうか尋ねられました。
最初のテストとして、シンボリックリンクを作成してみました。
- アプリケーションを停止しました。
- 「Logs」ディレクトリを削除しました。
- コンピューター上の WSL を使用して、次のようなシンボリック リンクを作成しました
ln -s /mnt/c/Temp_Folder/TestLog/ /mnt/c/<Application>/Logs
。 - アプリケーションを起動しました。
ディレクトリにログが表示されませんでしたC:\Temp_Folder\TestLog\
。
さまざまな理由が考えられます:
- いずれにせよ、Windows コンピュータで Linux テクノロジーを使用しようとするのは完全に愚かな考えです。
- どちらでも機能する可能性がありますが、いくつか追加の事項を考慮する必要があります。
2番目の選択肢であることを願いますが、その場合、どのような点を考慮する必要がありますか?
編集後ハリーの答え:ln -s
のような Windows テクノロジーを使用できる場合、 なぜ WSL を使用するのでしょうか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
でドライブを作成する方法は 2 つ、さらには 3 つあると記憶しています (ドライブ マッピング、subst (?)、および別の方法 (???)、これらはすべて私の頭の中では非常にぼんやりしています)。シンボリック リンク/ジャンクションの仕組みが、ある種類のドライブでは機能していても、他の種類のドライブでは機能していないのではないか、また、これを回避する方法があるかどうか疑問に思っています。
回答後の編集3重力:
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
ディレクトリ/シンボリックリンク/ジャンクションに入り、エクスプローラーのコンテキスト メニューを使用して単純なテキスト ファイルを作成します。次のエラー メッセージが表示されるため、これは機能しません。
これまでに私が学んだことは3つあります。
- Windows でシンボリックリンクを作成するには、
mklink
WSL の代わりにを使用しますln -s
。これを行うには、管理者としてコマンド プロンプトを開きます。 - リモート ディレクトリへのシンボリック リンク/ジャンクションを作成するには、ドライブ文字ではなく UNC パスを使用する必要があります。
- リモート ディレクトリからの、またはリモート ディレクトリへのシンボリック リンク/ジャンクションを作成する権限は、
fsutil
コマンドを使用してチェックされますfsutil behavior query symlinkEvaluation
。
次に学ぶ必要があるのは、シンボリックリンク/ジャンクションの宛先権限をどこで確認するかです。誰かアイデアを持っていますか?
答え1
Linux 上のシンボリックリンクは Windows とは異なる方法で実装されています。
- Windowsでは、シンボリックリンクはカーネル呼び出しによって実装および操作されるファイルテーブルエントリです。
- Linux では、シンボリックリンクは、単に特別なフラグが付いたテキスト ファイルであり、その内容はリンク先へのパスです (パスが有効である必要はありません)。
つまり、Windows Subsystem for Linux (WSL) を通じて作成されたシンボリック リンク (または symlink) は、Windows では追跡できません。
Windowsは、 mklink コマンド。
詳細については記事をご覧ください
Windows でシンボリック リンク (別名 Symlink) を作成するための完全ガイド。
「アクセス拒否」の問題については、投稿から引用します。 ネットワークドライブにシンボリックリンクを作成する の一部 GambleNerdによる回答:
アクセス拒否の修正
mklink /D
管理者としてコマンドを実行し、Link
コマンドの一部が UNC ネットワーク パスであり、Access Denied
エラー メッセージが表示される場合は、以下の手順に従ってこの問題を解決できる可能性があります。
- そこのサーバーでは(および/または Windows クライアント PC でコマンドを実行すると、アクセス拒否エラー メッセージが表示されます)コマンドの部分
Link
が見つかったら、サーバー上で管理者としてこのコマンドを実行します。fsutil behavior query SymlinkEvaluation
- 表示されたら
Remote to remote symbolic links are disabled.
、次のコマンドを実行します。fsutil behavior set SymlinkEvaluation R2R:1
- これは、MKLINKコマンドを実行してアクセスが拒否された場所(Windows Server自体またはWindowsクライアントPC)から実行できます。
- ここでコマンドをもう一度実行してみてください。これで正常に動作するはずです。
リンク参照: mklink へのアクセスが拒否されました
答え2
Windows コンピュータで Linux のようなシンボリックリンクを使用して、別のコンピュータ上の場所を参照する方法はありますか?
可能ですが、ドライブ文字ではなく UNC パスを使用する必要があります。ドライブ文字は必ずしもグローバルではないためです。物理ボリュームにはグローバル割り当てがありますが、各ログオン セッションにはその上に独自のプライベート マッピングを設定できます (たとえば、ユーザー 1 は 1 つの場所を表す Y:\ を持ち、ユーザー 2 は別の場所を表す Y:\ を持つことができます)。これは、Linux で各ユーザーが独自の「マウント名前空間」(pam_namespace) を持つのと少し似ています。
具体的には、すべての「マップされたネットワーク共有」ドライブ文字はログオン セッション専用であり、シンボリック リンクをたどったときにカーネル コンテキストでは認識されません。したがって、ターゲットが別のマシン上にある場合は、そのマシンの生の 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」として実行されている場合は、ネットワーク共有にアクセスすることはできません。)