A certain engineer "COMPLEX"

開発メモ その71 NLogでLoggerの読み込みに失敗する

Problem


NLogはシンプルで使いやすいです。
個人的にはlog4netよりもシンプルで使いやすくて好きです。

そんなNLogで、複数のLoggerを準備している際に問題が起きました。
下記のようなNLog.configです。

このファイルをアプリと一緒に読み込み、LogManager.GetLogger("GHILogger");と実行してもログを書き出すことができません。
しかもエラーも発生しません。

Solution


ポイントは、targets内の、targetセクションにおいて、rules内のloggerセクションのwriteTo属性と対応付けすることが出来ないtargetが存在することになります。
つまり、DEF_がそれです。
このため、NLogの内部では処理がおかしくなっているのか、ABCLoggerは読み込めますが、次のDEFLoggerは対応付くDEFが存在しないため読み込めません。
さらに不味いのは、この状態だと後続のGHILoggerも読めません。
途中で対応付けに失敗すると、それ以降の対応付けに失敗あるいは対応付けそのものを中止してしまうのでしょう。

対応は簡単です。

targetのname属性またはloggerのwriteTo属性を正しく対応付けるように修正するだけです。
この場合は、2番目のtargetのname属性をDEFに修正することで正しく動きます。

仕事で、ログが出力されなくて悩みましたが、一見無関係に見える、使っていないLoggerが影響するとは思いませんでした。

.NETでLinuxと遊んでみる Visual Studio Code編 第5回

Introduction


前回は、System.IO.FileStreamを使ってファイルのアクセス権限を確認してみました。

.NETでLinuxと遊んでみる Visual Studio Code編 第4回
Introduction前回は、System.IO.DirectoryInfoを使って、ファイルの一覧を列挙してみました。今回はファイルへのアクセス可否についてです。May I open this file?Windo...

今回は少し高度なファイルへのアクセス可否についてです。

P/Invoke


ファイルに実際にアクセスしてみて、アクセスできるかどうかを試すって、結構良くないと思います。
かといって、Windowsの.NET Frameworkにアクセスできるかどうかを試すAPIは無かったはずです。

ですが、Linuxのシステムコールを使えば、それが実現可能です。
システムコールの呼び出しは当然P/Invokeで実現します。

Linuxのシステムコールで、ファイルに対して、読み込みができるか、書き込みが出来るか、実行できるか、という状態を調べるには、accessを呼び出します。

大抵のシステムコールはlibcに定義されています。
実際に、libcに定義されている関数の一覧からaccessを探してみます。
そのために、nmコマンドに-Dオプションを渡します。

これでlibcにaccessが定義されていることがわかりました。

次にaccessの使い方です。
定義は下記です。

第一引数はファイルパスです。
第二引数は調べるモードを表します。

意味
F_OK 存在するか
R_OK 読み込み可能か
W_OK 書き込み可能か
X_OK 実行可能か

第二引数のモードを組み合わせることで、アクセス可否をチェックします。
指定したモードを満たせば、0を返します。
満たさない場合は-1を返します。

Try


今回は、/etc/passwdを調べてみます。

root以外は、読み込みしかできません。

では、これをコードで調べてみます。

引数で指定したファイルの読み込み、書き込み、実行の可否を調べます。

前回同様、まずは、一般ユーザで確認します。
whichでdotnetコマンドの場所を調べているのは、rootユーザでdotnetまでのパスが通っていなかったので、実施しているだけです。
パスが通っているなら不要です。
引数のファイルパスはdotnet runの直後に追記することで指定できます。

読み込みしかできないようです。
ls -laで調べたとおりです。

続いて、rootで確認します。

読み書きができて、実行できないことが確認できました。
これも、ls -laで調べたとおりです。

では、存在しないファイルを指定してみます。

きちんと存在しないことを確認してくれます。

フォルダも調べることが出来ます。

Conclusion


Windows同様、P/Invokeが利用可能であることを確認できました。

.NETでLinuxと遊んでみる Visual Studio Code編 第4回

Introduction


前回は、System.IO.DirectoryInfoを使って、ファイルの一覧を列挙してみました。

.NETでLinuxと遊んでみる Visual Studio Code編 第3回
Introduction前回は、デバッグ時に引数を指定して実行してみました。今回はファイルパスを使ったAPIのメモです。System.IO.DirectoryInfo相対パス扱いなの?前回、デバッ...

今回はファイルへのアクセス可否についてです。

May I open this file?


Windows上のC#なら、ファイルに書き込みできるかどうか等は、実際にファイルへのストリームを作成してみたりします。

では、Linuxでこれを実施するとどうなるでしょう?
ありがちなのは、所有者がrootになっていて、root以外が読み込みも出来ないパターンです。
例えば、/etc/sudo.confがそうです。

なので、こんなソースを用意してみました。

引数で指定したファイルを開くことが出来れば、'' can be opened!!と表示されます。
ファイルを開こうとして、例外を投げれば、開けなかった理由が表示される、というシンプルなテストです。

ソースを記述したら、プロジェクトフォルダで

を実行します。
これでビルドが成功するはずです。

まずは、一般ユーザで確認します。
whichでdotnetコマンドの場所を調べているのは、rootユーザでdotnetまでのパスが通っていなかったので、実施しているだけです。
パスが通っているなら不要です。
引数のファイルパスはdotnet runの直後に追記することで指定できます。

アクセスが拒否されています。

続いて、rootで確認します。

無事にアクセスできました。

Conclusion


基本的なアクセス権も.NET Coreで対処できそうです。
次回は、もう少し高度な方法で読み書きできるかを調べてみたいと思います。

.NETでLinuxと遊んでみる Visual Studio Code編 第3回

Introduction


前回は、デバッグ時に引数を指定して実行してみました。

.NETでLinuxと遊んでみる Visual Studio Code編 第2回
Introduction前回は、GUIからgitによるコミットを実行しました。今回はDebug時の引数指定のメモです。Tryデバッグ時の引数を指定してみます。Visula Studio使っているな...

今回はファイルパスを使ったAPIのメモです。

System.IO.DirectoryInfo


相対パス扱いなの?

前回、デバッグ引数として、~/を指定しました。
Linuxにおいてこのパスは、実行ユーザのホームディレクトリを示します。
(~も同様。)

これを使って、下記のコードを実行します。

よくある、指定したパスの配下のファイルを列挙するプログラムです。

これを実行すると下記の例外を投げます。

Could not find a part of the path '/home/XXXXXX/git/Demo/DotNetCoreLinux3/~/'という記述から、指定したパスは、カレントディレクトリからの相対パス扱いになってしまいました。
なので、System.IO.Path.GetFullPathメソッドで絶対パスに変換してみます。

変わらず同じ例外が出力されます。
デバッグコンソールの出力は下記のようになります。

なので、~はダメな模様。

ルートから指定してみる

Windowsでも、パス指定の際の基準はカレントディレクトリになりました。
でも、フルパスを指定したなら、それはフルパスとして解釈されます。
間違っても、<カレントディレクトリ>\<フルパス>みたいな解釈はされません。

Linuxでもそうなるでしょうか?
Linuxにおけるルートは/になります。

次は、デバッグ引数に/を指定して、実行してみます。
無事に最後まで実行できています。
また、/はGetFullPathでも/として認識されています。

きちんとルートディレクトリの内容と比較してみます。
同じ内容であることがわかります。

Conclusion


少しずつ基本的なAPIを使えるようになってきました。
Windows/Mac/Linuxでの挙動の違いを比較してみたいですね。

.NETでLinuxと遊んでみる Visual Studio Code編 第2回

Introduction


前回は、GUIからgitによるコミットを実行しました。

.NETでLinuxと遊んでみる Visual Studio Code編 第1.5回
Introduction前回は、CUI、GUIから.NET Coreのプロジェクトを実行、デバッグしました。今回はちょっと脇道で、バージョン管理システムとしてgitをVisual Studio Codeか...

今回はDebug時の引数指定のメモです。

Try


デバッグ時の引数を指定してみます。
Visula Studio使っているなら、プロジェクトのプロパティ見て、引数を、ってのがすぐ思い浮かべますが、プロジェクトファイルが存在しない(.NET Core 1.1の場合)ので、ちょっと構えてしまいます。

Debugの手順については、きちんと下記の公式ページのLaunch.json attributesに明記されています。

Debugging in Visual Studio Code
One of the great things in Visual Studio Code is debugging support. Set breakpoints, step-in, inspect variables and more.

このlaunch.jsonが肝になります。
ちょっと上のページは文字だけでわかりにくいので画像をつけて。

まずdotnet newでプロジェクト作成後のフォルダを開いた状態です。

Program.csの内容は

に変更します。
また、Console.WriteLineの行とその次の行にブレークポイントを貼っておきます。

左側のデバッグアイコンをクリックします。

デバッグペインが出現するので、上部の歯車アイコンをクリックします。

.NET Coreを選択します。

launch.jsonが作成されて表示されます。
name:.NET Core Launch (console)になっているセクションを

  • "program": ${workspaceRoot}/bin/Debug//<project-name.dll>
    • "program": ${workspaceRoot}/bin/Debug/netcoreapp1.1/DotNetCoreLinux2.dll に変更
  • "args: []"
    • "args: ["~/"]"

に変更して、保存します。

この状態でF5でデバッグを開始すると、エラー preLaunchTask 'build' が見つかりませんでした。とエラーが表示されます。
右側のタスクランナーの構成という選択肢を選択します。

ドロップダウンから.NET Coreを選択します。

tasks.jsonが作成されて、表示されます。
特に変更する必要はありません。

再度、F5でデバッグを実施します。
コードにエラーが無くても、エラー preLaunchTask 'build' の実行中にビルド エラーが検出されました。とエラーが表示されるかもしれませんが、そのままデバッグが始まります。

引数argsにカーソルを合わせると、ウォッチ出来ます。
launch.jsonで指定した引数が、先頭に格納されているのがわかります。

次の行に進めます。デバッグコンソールargs[0]の内容が表示されています。

Conclusion


引数の指定が出来るようになりました。
次回は、ファイルパスを利用したAPIを試してみます。