3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Linuxでdotnetを扱う場合の GetCurrentDirectory の罠

Last updated at Posted at 2019-03-14

GetCurrentDirectoryの設定の罠

どのASP.NET Coreや.NET CoreコンソールのドキュメントにもでてくるこのGetCurrentDirectoryメソッド。このように書かれているからこれを使う、という初心者的な考えで実装すると嵌まります。猫は、結構長いこと使ったりしてる言語/環境ではあるのですけど、やはり実行環境が変わる、実行したい方法が変わるとなると、意外にその概念を忘れます。
特に、Linux等でコンソールで動作させる場合、クローンを使ったりするときに、そのことを考えずに設定すると正常動作しない可能性があります(というか、これにかなり悩みました)。

config が読み込まれないじゃないか...

例えば、/etc/hogehoge/app/hoge.dll に、コンソールアプリ(バッチ処理)をおいて、定期的に実行しようとした場合、クローンに 0 0 * * * hoge /bin/dotnet /etc/hogehoge/app/hoge.dll として設定したとします。ちなみに、/etc/hogehoge/app/hoge.dll は、Directory.GetCurrentDirectory() メソッドを利用して、appsettings.json を読み込んでいます。すると、このプログラムのDirectory.GetCurrentDirectory()メソッドが返すカレントディレクトリは、どこになるのか?

そう、hoge のホームディレクトリになります。基本、hoge.dll と同じ場所に appsettings.json があると想定してデプロイすると、コンフィグを読めなくて死にます。

ASP.NET Core では、公式でもGetCurrentDirectoryを使う記述が書かれている

Microsoftのドキュメントにも、Directory.GetCurrentDirectory()メソッドを使って、コンフィグを取得する処理が書かれている。このままドキュメントの記述に習って、systemd などに書いた場合、気をつけないといけない点があります。WorkingDirectoryの設定が正確にされていないと、CurrentDirectory()メソッドは指定ユーザーのホームを返してくれるということです。そのため、dotnet run で実行しているときは正常に動いているにもかかわらず、デプロイしてsystemd なりで動作させようとすると、動かないという罠にはまり悩み続ける可能性があります。
そして、以外にこれらの内容を記した所はあまりないので、初心者には不親切だったりします。
https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2

元に戻って

ASP.NET Coreでsystemd を使う場合は、WorkingDirectory 項目にパスを指定すればいいのですが、では、Cronの場合はどうすればいいのでしょうか。

cd を使ってカレントの移動

0 0 * * * root cd /etc/hogehoge/app/;/bin/dotnet /etc/hogehoge/app/hoge.dll

今のところ、これぐらいしか対策はなさそうです。直接 dotnet を叩くのではなく、 .sh を通してもいいのですが、書く内容についてそれほど変わらないかと思います。
通常の.NET Framework の場合は、AppDomain.CurrentDomain.SetupInformation.ApplicationBase プロパティを使うことで、.exeや.dllのある場所のパスを取得可能ですが、残念ながら .net standard や .net core 2.2には追加されていないようで、利用できませんでした。そのため、デプロイ時点で、WorkingDirectory(CurrentDirectory)を意識して設計・設定しなと碌な目に遭いかねません(猫みたいに)ので注意しましょう。

AppDomain.CurrentDomain.BaseDirectory プロパティ

これで、アプリケーションのおいているディレクトリがわかる?というコメントをいただいているのですが、検証したところ、ちゃんと実行パスのディレクトリが返ってきました。
あとは、よく共有ライブラリ用DLLを作って、それをlib/hogehoge.dll として入れている。その共有ディレクトリないでもAppDomain.CurrentDomain.SetupInformationほげほげを使っていたことがあり、こちらはどこのパスが返ってくるのか確認するだけです。

3
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?