利用C#编写Linux守护进程实例代码
前言
linux守护进程是linux的后台服务进程,相当于windows服务,对于为linux开发服务程序的朋友来说,linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯、控制等方面,是实现linux大型服务的基础技术之一。
如果要在red hat enterprise linux上将.net core进程作为后台进程运行,则可以创建自定义systemd单元。今天我将为.net core编写两个自定义系统单元的例子。一个是运行.net core控制台应用程序的一种类型,另一个是运行asp.net core web应用程序的简单类型。
控制台应用程序
建立一个应用程序
您可以用dotnet run在systemd中使用指定项目目录作为工作目录。但是,我们来构建一个二进制文件并将其用于systemd。用dotnet new 命令创建您的项目后编辑program.cs如下。
using system; using system.io; namespace consoleapplication { public class program { public static void main(string[] args) { var path = path.gettempfilename(); file.writealltext(path, "hello temp file!"); console.writeline($"wrote temp file: {path}"); } } }
然后用dotnet publish命令发布项目。你会看到bin/<configuration>/<framework>目录下的二进制文件。
$ dotnet publish -c release publishing consoleapp for .netcoreapp,version=v1.1 project consoleapp (.netcoreapp,version=v1.1) was previously compiled. skipping compilation. publish: published to /home/tatanaka/documents/git/tanaka-takayoshi/systemdexample/1.1/consoleapp/bin/release/netcoreapp1.1/publish published 1/1 projects successfully
创建一个自定义的systemd
首先,创建一个运行守护进程和工作目录的用户。
$ sudo useradd -s /sbin/nologin dotnetuser $ sudo mkdir /var/systemdexample $ sudo cp /home/tatanaka/documents/git/tanaka-takayoshi/systemdexample/1.1/consoleapp/bin/release/netcoreapp1.1/publish/* /var/systemdexample $ sudo chown -r dotnetuser:dotnetuser /var/systemdexample
然后在/etc/systemd/system/目录下创建一个自定义的systemd单元文件。文件名应该是<unit-name>.<unit-type>。我创建的目录和文件名为:/etc/systemd/system/netcore-console-example.service。
[unit] description=example for .net core consoleapp with systemd defaultdependencies=no [service] type=oneshot remainafterexit=no execstart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet consoleapp.dll workingdirectory=/var/systemdexample user=dotnetuser group=dotnetuser [install]
您应该在execstart中指定dotnet的完整路径。以上是红帽提供的.net core 1.1的情况。然后你可以用systemctl命令执行守护进程。您可以使用systemctl status命令或journalctl命令查看控制台输出。
$ sudo systemctl start netcore-console-example.service $ sudo systemctl status netcore-console-example.service ● netcore-console-example.service - example for .net core consoleapp with systemd loaded: loaded (/etc/systemd/system/netcore-console-example.service; enabled; vendor preset: disabled) active: inactive (dead) since fri 2017-02-24 00:29:16 jst; 13s ago process: 18075 execstart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet consoleapp.dll (code=exited, status=0/success) main pid: 18075 (code=exited, status=0/success) feb 24 00:29:16 localhost.localdomain systemd[1]: starting example for .net core consoleapp with systemd... feb 24 00:29:16 localhost.localdomain dotnet[18075]: wrote temp file: /tmp/tmph1ok6h.tmp feb 24 00:29:16 localhost.localdomain systemd[1]: started example for .net core consoleapp with systemd. $ journalctl -u netcore-console-example.service -e feb 24 00:29:16 localhost.localdomain systemd[1]: starting example for .net core consoleapp with systemd... feb 24 00:29:16 localhost.localdomain dotnet[18075]: wrote temp file: /tmp/tmph1ok6h.tmp feb 24 00:29:16 localhost.localdomain systemd[1]: started example for .net core consoleapp with systemd. $ sudo cat /tmp/tmph1ok6h.tmp hello temp file!
使用privatetemp
在上述系统单元中,程序在临时文件夹下写入一个文件。你有时想写一个来自其他用户的临时文件是安全的。您可以在[service]section中的指定使用privatetemp。
[service] type=oneshot remainafterexit=no execstart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet consoleapp.dll workingdirectory=/var/systemdexample user=dotnetuser group=dotnetuser privatetemp=true
重新加载单元文件后,程序可以像前一样访问/tmp目录,但这不是实际的/tmp目录。
$ sudo systemctl daemon-reload $ sudo systemctl start netcore-console-example.service $ sudo systemctl status netcore-console-example.service ● netcore-console-example.service - example for .net core consoleapp with systemd loaded: loaded (/etc/systemd/system/netcore-console-example.service; enabled; vendor preset: disabled) active: inactive (dead) since fri 2017-02-24 00:35:46 jst; 12s ago process: 18415 execstart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet consoleapp.dll (code=exited, status=0/success) main pid: 18415 (code=exited, status=0/success) feb 24 00:35:46 localhost.localdomain systemd[1]: starting example for .net core consoleapp with systemd... feb 24 00:35:46 localhost.localdomain dotnet[18415]: wrote temp file: /tmp/tmpjlwagc.tmp feb 24 00:35:46 localhost.localdomain systemd[1]: started example for .net core consoleapp with systemd. $ ls /tmp/tmpjlwagc.tmp ls: cannot access /tmp/tmpjlwagc.tmp: no such file or directory
web应用程序
建立一个应用程序
现在我们来构建一个asp.net core web应用程序。今天我使用默认的模板项目。
$ dotnet new -t web created new c# project in /home/tatanaka/documents/git/tanaka-takayoshi/systemdexample/1.1/webapp. $ dotnet restore ** snipped** log : restore completed in 9721ms. $ dotnet publish -c release publishing webapp for .netcoreapp,version=v1.1 ** snipped ** publish: published to /home/tatanaka/documents/git/tanaka-takayoshi/systemdexample/1.1/webapp/bin/release/netcoreapp1.1/publish published 1/1 projects successfully
现在可以用dotnet命令运行。
$ dotnet bin/release/netcoreapp1.1/publish/webapp.dll info: microsoft.extensions.dependencyinjection.dataprotectionservices[0] user profile is available. using '/home/tatanaka/.aspnet/dataprotection-keys' as key repository; keys will not be encrypted at rest. hosting environment: production content root path: /home/tatanaka/documents/git/tanaka-takayoshi/systemdexample/1.1/webapp now listening on: http://localhost:5000 application started. press ctrl+c to shut down.
创建一个自定义的systemd
为这个web应用程序也指定dotnetuser名称。
$ sudo mkdir /var/systemdexample $ sudo cp -r bin/release/netcoreapp1.1/publish/* /var/systemdwebexample $ sudo chown -r dotnetuser:dotnetuser /var/systemdwebexample
然后创建一个自定义的systemd单元文件/etc/systemd/system/netcore-web-example.service。
[unit] description=example for .net core webapp with systemd defaultdependencies=no wants=network.target # network is required after=network.target [service] execstart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet webapp.dll workingdirectory=/var/systemdwebexample restart=always restartsec=10 # restart service after 10 seconds if dotnet service crashes syslogidentifier=dotnet-example user=dotnetuser group=dotnetuser privatetmp=true environment=aspnetcore_environment=production # specify environment variable for environment environment=aspnetcore_urls=http://*:8080 # specify environement variable for listening port [install] wantedby = multi-user.target
最后,您可以将asp.net core应用程序作为linux守护程序运行。请注意,此应用程序侦听端口8080代替了asp.net core 默认的 5000,因为我在aspnetcore_urls单元文件中指定了环境变量 。
$ systemctl start netcore-web-example.service [tatanaka@localhost webapp]$ systemc^c [tatanaka@localhost webapp]$ sudo systemctl status netcore-web-example.service [sudo] password for tatanaka: ● netcore-web-example.service - example for .net core webapp with systemd loaded: loaded (/etc/systemd/system/netcore-web-example.service; disabled; vendor preset: disabled) active: active (running) since sat 2017-02-25 01:02:12 jst; 11s ago main pid: 7041 (dotnet) cgroup: /system.slice/netcore-web-example.service └─7041 /opt/rh/rh-dotnetcore11/root/usr/bin/dotnet webapp.dll feb 25 01:02:12 localhost.localdomain systemd[1]: started example for .net core webapp with systemd. feb 25 01:02:12 localhost.localdomain systemd[1]: starting example for .net core webapp with systemd... feb 25 01:02:12 localhost.localdomain dotnet-example[7041]: info: microsoft.extensions.dependencyinjection.dataprotectionservices[0] feb 25 01:02:12 localhost.localdomain dotnet-example[7041]: user profile is available. using '/home/dotnetuser/.aspnet/dataprotection-keys' as key repository; keys will not be encrypted at rest. feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: hosting environment: production feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: content root path: /var/systemdwebexample feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: now listening on: http://*:8080 feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: application started. press ctrl+c to shut down. $ journalctl -u netcore-web-example -xf -- logs begin at mon 2017-02-20 11:58:31 jst. -- feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: microsoft.aspnetcore.staticfiles.staticfilemiddleware[2] feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: sending file. request path: '/images/banner4.svg'. physical path: '/var/systemdwebexample/wwwroot/images/banner4.svg' feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: microsoft.aspnetcore.hosting.internal.webhost[2] feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: request finished in 0.1973ms 200 image/svg+xml feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: microsoft.aspnetcore.hosting.internal.webhost[1] feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: request starting http/1.1 get http://localhost:8080/favicon.ico feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: microsoft.aspnetcore.staticfiles.staticfilemiddleware[2] feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: sending file. request path: '/favicon.ico'. physical path: '/var/systemdwebexample/wwwroot/favicon.ico' feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: microsoft.aspnetcore.hosting.internal.webhost[2] feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: request finished in 0.5824ms 200 image/x-icon
然而这对于asp.net core的生产使用来说是不够的。你可能需要设置一个反向代理服务器,比如jexus,nginx,防火墙等等。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。