Nesta postagem, veremos como você pode executar um aplicativo .NET Core / .NET 5 como um serviço no Linux. nós vamos usarSystemdNamepara integrar nosso aplicativo com o sistema operacional e possibilitar iniciar e parar nosso serviço e obter logs dele.
Para construir o meuataque à cadeia de suprimentos com .NET, eu precisava hospedar um servidor DNS para capturar os nomes de host enviados para mim. Vamos usar isso como exemplo!
Criando um aplicativo .NET para ser executado como um serviço
Um serviço .NET precisará fazer uso doMicrosoft.Extensions.Hosting
modelo de hospedagem. Isso significa que qualquer aplicativo ASP.NET Core funcionará, assim como projetos criados usando oServiço do Trabalhadormodelo (dotnet novo trabalhador
). eu vou usarCavaleiroaqui.
Em seguida, você precisará instalar um pacote NuGet:Microsoft.Extensions.Hosting.Systemd
. Este pacote fornece a infraestrutura de hospedagem .NET para serviços Systemd. Em outras palavras: contém a infraestrutura para trabalhar com o daemon Systemd no Linux.
Só falta uma coisa: registrar as extensões de hospedagem do Systemd em nosso aplicativo. EmProgram.cs
, você precisará adicionar.UseSystemd()
no construtor de host:
público aula Programa{ // ... público estático IHostBuilder CriarHostBuilder(corda[] argumentos) => Hospedar.CreateDefaultBuilder(argumentos) .UseSystemd() // Adicione isso .ConfigurarServiços((hostContext, Serviços) => { Serviços.AddHostedService<Trabalhador>(); });}
Com isso instalado, nosso aplicativo pode ser executado como um serviço Systemd no Linux! Bem, quase… Restam duas coisas a fazer:
- Implemente o aplicativo
- Registre o aplicativo com o Systemd
Vamos começar com o primeiro e implementar um servidor DNS que executaremos como um serviço.
Implementar um servidor DNS .NET como um serviço
O servidor DNSmencionei no meu post anterioré construído em .NET usandoO excelente pacote de DNS de Mirza Kapetanovic, e hospedado como um serviço no Linux, usando Systemd.
Vamos construir um serviço DNS simples que retorne a hora atual como umTXT
registro.
Observação: você pode pular esta seção se quiser apenas aprender como registrar aplicativos .NET como serviços Systemd.
Primeiro, instale oDNS
pacote. Ele vem com um servidor DNS quase pronto, de modo que precisamos apenas conectá-lo e implementar a lógica do servidor.
OTrabalhador
A classe que foi criada pelo modelo de serviço do trabalhador é uma boa base para começar. Nele, você pode usar injeção de construtor para obter acesso a quaisquer serviços disponíveis em nosso aplicativo. Iremos com umILogger
(já presente no modelo), eIConfiguration
para obter acesso aappsettings.json
/variáveis de ambiente/argumentos de linha de comando. se estendeServiço de plano de fundo
, que tem umExecuteAsync
método que executará nosso serviço. Aqui está um esqueletoTrabalhador
:
público aula Trabalhador : Serviço de plano de fundo{ privado somente leitura ILogger<Trabalhador> _logger; privado somente leitura IConfiguration _configuração; público Trabalhador(ILogger<Trabalhador> registrador, IConfiguration configuração) { _logger = registrador; _configuração = configuração; } protegido sobrepor assíncrono Tarefa ExecuteAsync(CancellationToken stopToken) { // ... a lógica vai aqui ... }}
Agora vamos conectar o próprio servidor DNS. NoExecuteAsync
método, adicione o seguinte:
protegido sobrepor assíncrono Tarefa ExecuteAsync(CancellationToken stopToken){ era servidor = novo Servidor dns(novo SampleRequestResolver()); servidor.Audição += (_, _) => _logger.LogInformation("O servidor DNS está escutando..."); servidor.Requeridos += (_, e) => _logger.LogInformation("Solicitação: {Domínio}", e.Solicitar.Questões.Primeiro().Nome); servidor.Errou += (_, e) => { _logger.LogError(e.Exceção, "Um erro ocorreu"); se (e.Exceção é ResponseException responseError) { _logger.LogError("Resposta: {Resposta}", responseError.Resposta); } }; aguardam Tarefa.Quando Qualquer(novo[] { servidor.Ouvir( porta: int.TryParse(_configuração["Porta"], fora era porta) ? porta : 53531, ip: Endereço de IP.Qualquer), Tarefa.Atraso(-1, stopToken) });}
Hora de desembrulhar!
- Estamos configurando o
Servidor dns
, que resolverá registros usando umSampleRequestResolver
(que precisaremos construir). - Estamos assinando alguns eventos expostos pelo
Servidor dns
, para que possamos ver os logs de solicitações recebidas e ver sempre que algo dá errado. - Por fim, começamos a ouvir as solicitações recebidas.
OExecuteAsync
é passado umCancellationToken
, que será usado quando o Systemd solicitar que nosso serviço seja encerrado. Desde oDNS
biblioteca em si não tem suporte paraCancellationToken
, Estou a usarTask.WhenAny
aqui para iniciar o servidor DNS, para que possamos desligar nosso serviço quando o cancelamento for solicitado.
O próprio servidor escutará na porta definida na configuração e, quando ela não estiver presente, o padrão é53531
.
Resta uma coisa: queSampleRequestResolver
aula. Tem que implementarIRequestResolver
e crie uma resposta para as consultas de DNS recebidas. Como esse não é o escopo real desta postagem do blog, aqui está uma implementação rápida que retorna a data e hora atuais para qualquerTXT
registro solicitado e retorna um erro para outras solicitações:
público aula SampleRequestResolver : IRequestResolver{ público Tarefa<IResponse> Resolver(Eu peço solicitar, CancellationToken token de cancelamento = novo CancellationToken()) { IResponse resposta = Resposta.FromRequest(solicitar); para cada (era pergunta em resposta.Questões) { se (pergunta.Tipo == Tipo de Registro.TXT) { resposta.Registros de resposta.Adicionar(novo TextResourceRecord( pergunta.Nome, Cadeia de caracteres.FromString(Data hora.UtcNow.Para sequenciar("O")))); } outro { resposta.Código de resposta = Código de resposta.Recusou; } } retornar Tarefa.Do resultado(resposta); }}
Se você executar o serviço localmente, verá que funciona! Você pode usar ferramentas comonslookup
eescavação
para experimentá-lo.
Verifica aREADME.md
do projeto DNSpara mais exemplos, e tenha cuidado para não construir acidentalmente umabra o resolvedor de DNSse você explorar a construção de seu próprio DNS.
Criar configuração de unidade de serviço
Vamos hospedar nosso serviço no Linux! Systemd usaconfiguração da unidade de serviçoarquivos que definem o que um serviço faz, se deve ser reiniciado e tudo mais.
Você precisará criar um.serviço
arquivo na máquina Linux que você deseja registrar e executar o serviço. Em sua forma mais simples, um arquivo de serviço se parece com isto:
[Unit]Description=DNS Server[Service]Type=notifyExecStart=/usr/sbin/DnsServer --port=53[Install]WantedBy=multi-user.target
O[Unidade]
A seção descreve informações mais genéricas sobre nosso aplicativo. O Systemd pode executar mais do que apenas serviços e[Unidade]
é uma seção comum para todos os tipos de aplicativos que podem ser executados. Eu adicionei apenas oDescrição
, mas hámuito mais opções disponíveis aqui.
No[Serviço]
seção, definimos detalhes sobre nosso aplicativo. Para aplicativos .NET, oTipo
vai sernotificar
, para que possamos notificar o Systemd quando o host for iniciado ou interrompido - oMicrosoft.Extensions.Hosting.Systemd
pacote cuida disso.ExecStart
define o caminho onde nosso binário de inicialização do serviço está localizado. No exemplo acima, usarei um aplicativo .NET independente e direi a ele em qual porta escutar como um argumento de linha de comando.
finalmente, o[Instalar]
A seção define quais destinos de sistema operacional podem iniciar nosso serviço. Nesse caso,multiusuário.alvo
permite iniciar o serviço sempre que estivermos em um ambiente multiusuário (quase sempre). Você também pode definir isso paragráfico.alvo
então você precisará de um ambiente gráfico carregado para iniciar este serviço.
Crie um aplicativo .NET independente
Nosso próprio serviço precisará estar disponível na máquina Linux de destino, onde definimos que o Systemd pode encontrá-lo (comExecStart
):/usr/sbin/DnsServer
.
A última coisa que eu queria fazer era implantar o .NET na máquina de destino, então decidi construir umaplicativo independente, como um único arquivo – o tempo de execução .NET e todas as dependências necessárias são agrupadas em um único arquivo executável. Eu usei o seguinte comando para criar o aplicativo:
dotnet publish -c Release -r linux-x64 --self-contained=true -p:PublishSingleFile=true -p:GenerateRuntimeConfigurationFiles=true -o artefatos
Isso cria umServidor dns
executável de aproximadamente 62 MB (contém o necessário do runtime .NET). Copie para/usr/sbin/DnsServer
na máquina Linux e verifique se ele é executável (sudo chmod 0755 /usr/sbin/DnsServer
).
Instalando e executando o serviço no Linux
O.serviço
arquivo que criamos (eu o nomeeidnsserver.service
) precisa existir no/etc/systemd/system/
diretório da máquina Linux na qual o serviço será implantado.
Em seguida, execute o seguinte comando para que o Systemd carregue este novo arquivo de configuração:
sudo systemctl daemon-reload
Isso agora deve possibilitar a visualização do status do nosso serviço de servidor DNS:
sudo systemctl status dnsserver.service
Existem alguns outros comandos que podem ser úteis:
Inicie e pare o serviço:
sudo systemctl start dnsserver.servicesudo systemctl stop dnsserver.servicesudo systemctl restart dnsserver.service
(Video) Creating background .NET Core services on LinuxCertifique-se de que o serviço seja iniciado quando a máquina Linux for iniciada:
sudo systemctl habilitar dnsserver.service
Parabéns, agora temos uma aplicação .NET rodando como um serviço, no Linux!
O que está acontecendo no meu serviço?
Quando um serviço está em execução, você também pode se interessar pelo que ele está fazendo. Podemos inspecionar as últimas entradas de log que nosso aplicativo emite, usando o seguinte comando:
sudo systemctl status dnsserver.service
Podemos ver que nosso serviço está em execução, obter detalhes sobre o ID do processo e ver as entradas de log mais recentes.
Se você realmente precisa de logs, você pode usarjornalctl
e obtenha todos os logs da unidade (-você
) que é o nosso servidor DNS:
sudo journalctl -u dnsserver.service
O que é legal é que, graças aoMicrosoft.Extensions.Hosting.Systemd
pacote, obtemos códigos de cores e severidades de log aqui:
Conclusão
Nesta postagem, vimos como executar um aplicativo .NET como um serviço Systemd no Linux, usando oMicrosoft.Extensions.Hosting.Systemd
pacote. Nós apenas arranhamos a superfície, no entanto. Há muito mais opções que você pode fornecer ao Systemd, você pode filtrar os níveis de log comjornalctl
, e mais. recomendo dar uma olhadablog de Niels Swimberghepara mais alguns exemplos disso.
FAQs
Como instalar o .NET no Linux? ›
- wget https://packages.microsoft.com/config/ubuntu/19. ...
- sudo apt-get update sudo apt-get install apt-transport-https sudo apt-get update sudo apt-get install dotnet-sdk-3.1.
- dotnet --version.
- dotnet --list-sdks.
- dotnet new console -o MeuConsoleApp -f net5. ...
- mkdir myapp cd myapp dotnet new console.
Habilitando e desabilitando serviços
Para iniciar um serviço na inicialização, use o comando enable : sudo systemctl enable application .
Para listar todos os serviços que estão instalados no sistema, e o status de cada serviço, utilize o comando svcs com a opção -a . Este comando exibe todos os serviços, incluindo aqueles que estão desativados.
Como instalar o dotnet no Debian? ›Isso é usado no comando sudo apt-get install a seguir. Isso representa a versão de distribuição em que você está. Isso é usado no comando wget abaixo. A versão de distribuição é o valor numérico, como 20.04 no Ubuntu ou 10 no Debian.