Linux(CentOS7)で、ASP.NET Coreアプリをサービス化する
ASP.NET Coreプロジェクトで、dotnet publish
コマンドの動作が確認できました。
今のところdotnet run
もしくはdotnet [dllファイル名]
で動作確認しています。
しかし実際にサービス運用するのに、このままシェルを占有させる訳にもいきません。
PHPと違って、apache がプログラムをキックしてくれるわけでもなく。
何かの不具合で異常終了しまうと、こわい。
というわけで、OSにプログラムの面倒を見てもらえるように、サービス化します。
systemd用のサービス定義を書く
公式ドキュメントをあたると、どうやらsystemd
を使うようです。
sudo nano /etc/systemd/system/kestrel-hellomvc.service
の、nano
ってナニソレ?と思ったら、テキストエディタなんですね。
ふむふむ、じゃvi
でいいや。
サービス定義ファイルを作ります。
[root@centos7 ~]# vi /etc/systemd/system/dotnet_sample.service
中身はこんな感じに。
[Unit] Description=Service Sample on CentOS7 [Service] ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll Restart=always RestartSec=10 SyslogIdentifier=dotnet_sample User=root Environment=ASPNETCORE_ENVIRONMENT=Production [Install] WantedBy=multi-user.target
公式サンプルをコピペして、実行ファイルのパス、実行ユーザーなどを書き換えました。
さて、どうなるでしょう?
[root@centos7 system]# systemctl daemon-reload [root@centos7 system]# systemctl start dotnet_sample [root@centos7 system]# systemctl status dotnet_sample ● dotnet_sample.service - Service Sample on CentOS7 Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled) Active: active (running) since 土 2016-12-03 17:56:09 JST; 6s ago Main PID: 3618 (dotnet) CGroup: /system.slice/dotnet_sample.service mq3618 /usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll 12月 03 17:56:09 centos7.local systemd[1]: Started Service Sample on CentOS7. 12月 03 17:56:09 centos7.local systemd[1]: Starting Service Sample on CentOS7... 12月 03 17:56:10 centos7.local dotnet_sample[3618]: Hosting environment: Production 12月 03 17:56:10 centos7.local dotnet_sample[3618]: Content root path: / 12月 03 17:56:10 centos7.local dotnet_sample[3618]: Now listening on: http://localhost:5000 12月 03 17:56:10 centos7.local dotnet_sample[3618]: Application started. Press Ctrl+C to shut down.
あー。
一見、動いてるように見えますが、Content root path: /
と出てます。
publish先のパスでなく、ルートディレクトリになっちゃってます。
前回末尾に書いた、Internal Server Errorになっちゃうヤツですね。
はい、動いていません。
実行時のカレントパスを指定しないといけませんね。
参考:
Publish to a Linux Production Environment
カレントパスは、どうやって書く?
かなり頑張ってぐぐりました。
おかげさまで、図らずもsystemd
のことがざっくり飲み込めました。
どうやら、*.service ファイルでWorkingDirectory
という項目を指定できるようです。
追記してみます。
[Unit] Description=Service Sample on CentOS7 [Service] ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll WorkingDirectory=/home/webroot/dotnet_sample/bin/ # <-この行を追記 Restart=always RestartSec=10 SyslogIdentifier=dotnet_sample User=root Environment=ASPNETCORE_ENVIRONMENT=Production [Install] WantedBy=multi-user.target
どうなるでしょう?
[root@centos7 system]# systemctl stop dotnet_sample Error: No space left on device Warning: dotnet_sample.service changed on disk. Run 'systemctl daemon-reload' to reload units. [root@centos7 system]# systemctl daemon-reload [root@centos7 system]# systemctl start dotnet_sample [root@centos7 system]# systemctl status dotnet_sample ● dotnet_sample.service - Service Sample on CentOS7 Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled) Active: active (running) since 土 2016-12-03 18:09:45 JST; 7s ago Main PID: 3698 (dotnet) CGroup: /system.slice/dotnet_sample.service mq3698 /usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll 12月 03 18:09:45 centos7.local systemd[1]: Started Service Sample on CentOS7. 12月 03 18:09:45 centos7.local systemd[1]: Starting Service Sample on CentOS7... 12月 03 18:09:45 centos7.local dotnet_sample[3698]: Hosting environment: Production 12月 03 18:09:45 centos7.local dotnet_sample[3698]: Content root path: /home/webroot/dotnet_sample/bin 12月 03 18:09:45 centos7.local dotnet_sample[3698]: Now listening on: http://localhost:5000 12月 03 18:09:45 centos7.local dotnet_sample[3698]: Application started. Press Ctrl+C to shut down.
おっ。パスがセットできてますね!
動作はいかが?
動きましたね~~!
参考:
Executing chdir before starting systemd service
実行権限をapacheに変える
いつまでも、root
で動かしてちゃダメですよね。一応公開を前提にするわけで。
というわけで、apache
ユーザーで動作するように、設定を見直します。
dotnet_sample.service
ファイルより、実行ユーザーを変更します。
[Unit] Description=Service Sample on CentOS7 [Service] ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll WorkingDirectory=/home/webroot/dotnet_sample/bin/ Restart=always RestartSec=10 SyslogIdentifier=dotnet_sample # User=root User=apache Environment=ASPNETCORE_ENVIRONMENT=Production [Install] WantedBy=multi-user.target
これでいいはず...?
[root@centos7 system]# systemctl stop dotnet_sample Warning: dotnet_sample.service changed on disk. Run 'systemctl daemon-reload' to reload units. [root@centos7 system]# systemctl daemon-reload [root@centos7 system]# systemctl start dotnet_sample [root@centos7 system]# systemctl status dotnet_sample ● dotnet_sample.service - Service Sample on CentOS7 Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled) Active: activating (auto-restart) (Result: exit-code) since 土 2016-12-03 18:19:50 JST; 3s ago Process: 3748 ExecStart=/usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll (code=exited, status=203/EXEC) Main PID: 3748 (code=exited, status=203/EXEC) 12月 03 18:19:50 centos7.local systemd[1]: Unit dotnet_sample.service entered failed state. 12月 03 18:19:50 centos7.local systemd[1]: dotnet_sample.service failed.
あらー。起動出来なかった...。
原因なんだっけなーと、諸々探してみますと。
[root@centos7 dotnet]# pwd /opt/dotnet [root@centos7 dotnet]# ls -alF 合計 148 drwxr-xr-x. 5 root root 99 12月 2 16:35 ./ drwxr-xr-x. 3 root root 19 12月 2 16:31 ../ -rwxr--r--. 1 root root 9410 11月 3 08:49 LICENSE.txt* -rwxr--r--. 1 root root 8103 11月 3 08:49 ThirdPartyNotices.txt* -rwxr--r--. 1 root root 128693 11月 9 06:52 dotnet* drwxr-xr-x. 3 root root 16 12月 2 16:35 host/ drwxr-xr-x. 4 root root 64 12月 2 16:52 sdk/ drwxr-xr-x. 3 root root 34 12月 2 16:35 shared/
あらっ。
dotnetコマンド実体ファイルの権限が、root以外で実行出来なくなってますやん。
こらあかん。
全員が実行出来るよう、サブフォルダを含めて一括修正します。
[root@centos7 dotnet]# cd ../ [root@centos7 opt]# pwd /opt [root@centos7 opt]# chmod -Rf 755 ./dotnet
どやっ?
[root@centos7 system]# systemctl stop dotnet_service Failed to stop dotnet_service.service: Unit dotnet_service.service not loaded. [root@centos7 system]# systemctl start dotnet_sample [root@centos7 system]# systemctl status dotnet_sample ● dotnet_sample.service - Service Sample on CentOS7 Loaded: loaded (/etc/systemd/system/dotnet_sample.service; enabled; vendor preset: disabled) Active: active (running) since 土 2016-12-03 18:30:04 JST; 1min 1s ago Main PID: 3875 (dotnet) CGroup: /system.slice/dotnet_sample.service mq3875 /usr/bin/dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll 12月 03 18:30:04 centos7.local systemd[1]: Started Service Sample on CentOS7. 12月 03 18:30:04 centos7.local systemd[1]: Starting Service Sample on CentOS7... 12月 03 18:30:04 centos7.local dotnet_sample[3875]: Hosting environment: Production 12月 03 18:30:04 centos7.local dotnet_sample[3875]: Content root path: /home/webroot/dotnet_sample/bin 12月 03 18:30:04 centos7.local dotnet_sample[3875]: Now listening on: http://localhost:5000 12月 03 18:30:04 centos7.local dotnet_sample[3875]: Application started. Press Ctrl+C to shut down. 12月 03 18:31:02 centos7.local systemd[1]: Started Service Sample on CentOS7.
おっしゃ!
イケましたな。
dotnetプロセスを殺してみる
これで、dotnet_sampleサービスが死んでもsystemd
が再起動してくれる、はずです。
試してみます...。
[root@centos7 ~]# ps -A | grep dotnet 3875 ? 00:00:00 dotnet [root@centos7 ~]# kill 3875 -->(dotnet_sample.serviceファイルの RestartSec設定どおり、10秒待ってから)--> [root@centos7 ~]# ps -A | grep dotnet 3914 ? 00:00:00 dotnet
大丈夫!理不尽に殺害されても、生き返ります!
ちなみに、supervisorだと?
systemd
が標準化する以前は、プロセス監視にsupervisor
を使ってた、ようです。
や、すいません。
LinuxだとPHPオンリーで、監視が必要なサービスは書いたこと無かったんです...。
CentOS7では、yum install supervisor
でインストールできました。
設定ファイルは/etc/supervisord.d/[各種サービス].ini
に書きます。
こちらを参考に、こんな感じで動きました。
[program:dotnet_sample] directory=/home/webroot/dotnet_sample/bin/ command=dotnet /home/webroot/dotnet_sample/bin/WebApplication1.dll user=apache ; 起動ユーザ autostart=true autorestart=true ; プロセスダウン時に自動再起動 stdout_logfile=/var/log/supervisor/dotnet_sample.out.log ; 標準出力ログ stderr_logfile=/var/log/supervisor/dotnet_sample.err.log stdout_logfile_maxbytes=1MB stdout_logfile_backups=5 stdout_capture_maxbytes=1MB redirect_stderr=true ; エラー出力を標準出力にリダイレクト environment=Hosting__Environment=Production,HOME=/home/webroot/dotnet_sample/bin/ stopsignal=INT
参考:
ASP.NET Core アプリを Ubuntu サーバーで公開
今回分のソースコードはこちら。
まだ、Visual Studioが生成するテンプレートのままです。
github.com