Voltar ao blog

Como Configurar um Serviço Linux para Iniciar Automaticamente Após uma Reinicialização ou Falha do Sistema: Parte 2 (Explicações Teóricas)

Como Configurar um Serviço Linux para Iniciar Automaticamente Após uma Reinicialização ou Falha do Sistema: Parte 2 (Explicações Teóricas)

Nesta segunda parte do tutorial de duas partes sobre a configuração de Linux serviços para iniciarem automaticamente após uma reinicialização ou falha do sistema, discutiremos o sistema init em detalhes. Você pode consultar a Parte 1 da série: Como Configurar um Serviço Linux para Iniciar Automaticamente Após uma Reinicialização ou Falha do Sistema: Exemplos Práticos aqui.

O tutorial atual será focado em teoria. Portanto, você deve usá-lo como referência para obter uma compreensão mais profunda de como o sistema init funciona no Linux. Na primeira parte deste tutorial, compartilhamos alguns trechos de código e scripts de inicialização que o sistema init lê ao iniciar. Também usamos o MySQL como exemplo para aprender como ativar e desativar um serviço Linux para iniciar automaticamente após uma falha ou reinicialização. Como você aprendeu na primeira parte deste tutorial de duas partes, existem três sistemas init usados em diferentes distribuições do Linux: System V, Upstart e Systemd. Você pode consultar a primeira parte deste tutorial para entender a distribuição e a versão configuradas para usar um sistema init específico.

Neste tutorial, explicaremos o código que usamos na primeira parte do tutorial. Detalharemos os comandos e os arquivos de configuração que o sistema init usa. Vamos começar!

Pré-requisitos

Na conclusão da primeira parte deste tutorial de duas partes, mencionamos que você deve manter os três servidores de teste em execução. Se você os tiver excluído, poderá voltar e recriá-los. Isso ajudará você a acompanhar o tutorial. Os três servidores de teste que você deve ter são:

Você deve ter um usuário com privilégios sudo em cada um dos servidores que usará para executar os comandos. Este tutorial sobre como configurar o arquivo sudoers do Linux pode orientá-lo.

Nota:  Os comandos no tutorial irão interferir nos serviços do sistema. Portanto, você não deve aplicá-los em um servidor de produção ativo.

Runlevels

Um runlevel é um nível operacional que descreve o estado atual de um sistema Linux em relação aos serviços disponíveis. O conceito se origina no init do System V. Quando o sistema Linux inicializa, ele inicializa o kernel, entra em um runlevel e executa o script de inicialização associado a esse runlevel. Você pode executar apenas um runlevel na inicialização.

Outros exemplos de runlevels incluem o estado de desligamento, o modo de reinicialização, um modo de usuário único, etc. Cada nível determina quais serviços executar nesse estado. Alguns serviços podem ser executados em mais de um nível, enquanto outros não.

Existem sete runlevels: de 0 a 6. Abaixo está uma definição dos sete runlevels:

  • Runlevel 0: Desligamento do sistema
  • Runlevel 1: Modo de usuário único e recuperação
  • Runlevels 2, 3, 4: Multi-usuário e modo texto com rede ativada
  • Runlevel 5: Multi-usuário, com rede ativada e modo gráfico
  • Runlevel 6: Reinicialização do sistema

Os runlevels não são necessariamente executados sequencialmente. Os runlevels 2, 3 e 4 variam dependendo da distribuição Linux que você está executando. Você pode implementar o runlevel 4 em algumas distribuições e em outras não. Quando você ativou um serviço para iniciar automaticamente, como explicado na parte um, você na verdade o adicionou a um runlevel. No System V, o SO inicia com um runlevel específico e, durante a inicialização, tenta iniciar todos os serviços associados a esse runlevel. Os runlevels são targets no Systemd, os quais discutiremos na seção do Systemd.

Init e PID 1

O sistema init é o primeiro processo executado quando um sistema Linux inicializa e o Kernel é carregado na memória. Ele realiza várias tarefas, incluindo determinar como um processo de usuário ou serviço de sistema será carregado, em qual ordem e se deve iniciar automaticamente. Em toda distribuição Linux, cada processo é identificado por um ID de processo (PID) e o init tem o PID 1. Ele é o pai de todos os outros processos que iniciam sucessivamente à medida que o sistema inicializa.

História do init

O sistema init encontrado nas distribuições Linux recentes é uma melhoria em relação ao original. As primeiras versões das distribuições Linux usavam o System V init, que era usado de forma semelhante em sistemas Unix. À medida que o Linux evoluiu, o daemon init Upstart foi implementado – ele foi criado pelo Ubuntu. Agora (no momento da escrita deste tutorial, 2021), temos o daemon init Systemd – que foi implementado pela primeira vez pelo Fedora. À medida que os sistemas Linux continuam a evoluir, poderá surgir um sistema init mais recente. Para este tutorial, discutiremos estes três: System V, Upstart e Systemd.

As versões recentes do Linux vêm com o sistema init Systemd por padrão. No entanto, elas mantiveram os outros sistemas init mais antigos para compatibilidade retroativa. Existem diferentes implementações do System V que você pode usar em outras variantes do Linux. Por exemplo, o FreeBSD, uma variante do UNIX, usa o BSD init. Versões mais antigas do Debian usam o SysVinit. Ambos vêm do System V.

A maneira como cada versão do daemon init gerencia os serviços é diferente. As melhorias adicionadas em cada versão foram direcionadas para uma ferramenta robusta de gerenciamento de serviços que lidaria com tudo o que um sistema Linux precisa, desde serviços, dispositivos, portas e outros recursos. Havia a necessidade de um sistema poderoso que pudesse carregar recursos em paralelo e que pudesse se recuperar elegantemente de uma falha do sistema.

Sequência de Inicialização do System V

O System V utiliza um arquivo inittab para conter as instruções de inicialização. O Upstart mantém o arquivo inittab para compatibilidade retroativa. Aqui está o fluxo de inicialização do System V:

  • O sistema init vem do arquivo binário /sbin/init.
  • Assim que o sistema init é carregado na memória, ele lê seu primeiro arquivo em /etc/inittab.
  • Uma das entradas neste arquivo determina o runlevel em que a máquina deve inicializar. Por exemplo, se o valor para o runlevel for especificado como 5, o Linux inicializará no modo gráfico, multiusuário, com a rede ativada (comum em distribuições projetadas para uso em desktop). O runlevel especificado aqui é conhecido como o runlevel padrão porque é o que sempre será usado.
  • Em seguida, o sistema init procura mais a fundo no /etc/inittab e lê quais scripts de init ele precisa executar para esse runlevel.

Ao encontrar quais scripts executar para um determinado runlevel, o sistema init encontrará quais serviços ele precisa iniciar. Esses scripts de init são onde você geralmente configura o comportamento de inicialização para serviços individuais, da mesma forma que configuramos o serviço MySQL na primeira parte deste tutorial.

Estrutura dos Scripts de Init do System V

Nesta seção, veremos os scripts de init em detalhes. Os arquivos de configuração do System V ou scripts de init são o que controla os serviços. Os scripts de init inicializam um serviço, daí o nome script de init.

Cada serviço tem seu próprio script de init. Por exemplo, o script de init do MySQL controla o servidor MySQL. Os fornecedores de aplicativos fornecem os scripts de init para seus aplicativos específicos, enquanto os serviços nativos do Linux vêm com a instalação do sistema operacional. Quando você cria um aplicativo personalizado, também pode criar seus próprios scripts de init personalizados para ele.

Para iniciar um serviço como o servidor MySQL, seu programa binário é primeiro carregado na memória. Dependendo de sua configuração, o programa pode continuar em execução em segundo plano para continuar aceitando conexões de clientes. O script de init do serviço lida com o trabalho de iniciar, parar ou recarregar o aplicativo binário. Os scripts de init no System V são scripts shell. Outro nome para eles é scripts rc (run command).

Estrutura de Diretórios do System V

O diretório pai para os scripts de init é o /etc. O diretório /etc/init.d é o diretório real para os scripts shell de init. Os scripts são vinculados simbolicamente aos diretórios rc.

Existem vários diretórios rc dentro do /etc, cada um com um número em seu nome. Os números representam diferentes runlevels. Se você listar o conteúdo do diretório, verá nomes como /etc/rc0.d, /etc/rc1.d, /etc/rc2.d, etc.

Se você visualizar o conteúdo de cada um dos diretórios rc, verá arquivos que começam com K ou S em seu nome de arquivo, seguidos por dois dígitos. Esses arquivos contêm links simbólicos que apontam de volta para os scripts de shell init reais do programa real. As letras K e S são abreviações: K significa Kill ou Stop, enquanto S significa Start. Os dois dígitos nos nomes dos arquivos representam a ordem de execução. Se você vir um arquivo chamado K05script_name, ele será executado antes de um arquivo chamado K09script_name.

Inicialização

Avançando com a sequência de inicialização, vejamos como os scripts init são chamados.

Os scripts S e K não são chamados diretamente pelo sistema init. Em vez disso, eles são chamados por outro script: o /etc/init.d/rc script. O arquivo /etc/inittab instrui o daemon init sobre em qual runlevel o sistema deve inicializar por padrão. Dependendo do runlevel especificado, uma linha no arquivo /etc/inittab chama o script /etc/init.d/rc, passando o runlevel padrão como parâmetro. Usando esse parâmetro, o script chamará os arquivos no diretório correspondente /etc/rcN.d, onde N denota o runlevel. Por exemplo, se o servidor inicializar com o runlevel 5, os arquivos correspondentes no diretório /etc/rc5.d serão chamados.

Dentro do diretório rc, todos os scripts K são executados numericamente com um argumento de stop, enquanto todos os scripts S são executados de forma semelhante com um argumento de start. Os scripts de shell init reais correspondentes para o programa para o qual os arquivos em /etc/rcN.d apontam por meio de links simbólicos serão chamados com os parâmetros stop e start respectivamente.

Em termos simples, o que acontece sempre que um sistema Linux entra ou muda para um determinado runlevel é que certos scripts serão executados para parar alguns serviços, enquanto outros serão executados para iniciar outros serviços. Esse processo garante que qualquer processo que não deva ser executado em um determinado estado do Linux seja interrompido, e qualquer processo que deva ser executado seja iniciado automaticamente.

Inicialização Automática do System V

Quando você ativa um serviço para iniciar automaticamente no momento da inicialização, você está modificando diretamente o comportamento do init. Por exemplo, se você configurar um serviço para iniciar automaticamente no runlevel 2, o processo init criará os links simbólicos apropriados no diretório /etc/rc2.d. Para ajudar você a entender, explicaremos isso com um exemplo.

Exemplo do System V

Para dar um exemplo prático, usaremos a configuração do serviço MySQL da parte 1. Portanto, faça login no VPS Debian 6 com seu usuário sudo/root usando ssh (or putty se estiver no Windows) e prossiga com as seguintes etapas.

Etapa 1: Abrir e examinar o arquivo inittab

Primeiro, insira o seguinte comando para visualizar o conteúdo do arquivo inittab no terminal:

O conteúdo do arquivo deve ser algo como isto:

O número 2 denota o runlevel com o qual o sistema inicia. Neste caso, o runlevel 2 é o padrão, portanto, este sistema Debian iniciará no runlevel 2 como multiusuário, modo texto. Você pode executar o seguinte comando para confirmar:

Ele mostrará uma saída semelhante a:

Etapa 2: Examinando os diretórios rc

A seguir, para listar os diretórios rc, execute o seguinte comando:

Aqui está uma captura de tela da saída:

root screenshot

Como vimos no arquivo inittab anteriormente, o sistema está configurado para inicializar no runlevel 2, portanto, os scripts em /etc/rc2.d serão executados na inicialização do sistema. Você pode listar o conteúdo deste diretório usando o comando:

Como você pode ver na saída, os arquivos são apenas links simbólicos que apontam para os arquivos de script reais em /etc/init.d. Aqui está um trecho da saída:

service crash 1

Não há scripts K neste diretório, apenas scripts S (start). Os scripts iniciarão os serviços vinculados aqui, como rsync. Você também pode notar o serviço mysql listado, o qual discutiremos no próximo subtópico.

Etapa 3: Examinando o Script Init

Quando um serviço compatível com o System V é instalado, ele cria um script shell no diretório /etc/init.d. Você pode verificar a disponibilidade do script shell do MySQL inserindo o seguinte comando:

Ele mostra a saída abaixo:

screenshot output

O arquivo é bastante grande. Você pode inserir o seguinte comando para visualizar seu conteúdo:

Passo 4: Usando chkconfig ou sysv-rc-conf

Chkconfig é um comando que você pode usar em distribuições baseadas em RHEL como CentOS para ativar ou desativar serviços compatíveis com o System V. Você também pode usá-lo para listar os serviços instalados e seus respectivos runlevels. Aqui está o comando para isso (funciona no CentOS):

Nas distribuições Debian, esse utilitário não existe nativamente. O update-rc.d em sistemas Debian apenas instala e remove serviços dos runlevels. Uma ferramenta personalizada está disponível e você pode usá-la para trazer a funcionalidade do chkconfig para sistemas Debian. Insira o seguinte comando para instalá-la:

Assim que for instalado, você poderá executar o seguinte comando para visualizar os comportamentos de runlevel para vários serviços:

A saída deste comando é formatada em uma tabela que mostra o nome do serviço à esquerda e o runlevel sob o qual o serviço é executado:

service crash 2

O X indica o runlevel sob o qual o serviço será executado. Esta ferramenta permite desativar ou ativar um serviço para um runlevel usando as teclas de seta e a barra de espaço. Para sair da ferramenta, pressione Q.

Passo 5: Testar o Comportamento de Inicialização do MySQL durante o Boot do Sistema

Na captura de tela acima, você pode ver que o serviço mysql está ativado nos runlevels 2,3,4,5. Você pode desativar o MySQL usando o seguinte comando:

A saída se parece com isso. Observe que o serviço parou para todos os runlevels:

service crash 3

Execute o comando abaixo para ver o conteúdo do diretório:

Veja a linha do mysql na saída abaixo:

A saída mostra que o symlink mudou para K, significando Kill (parar). Portanto, o MySQL não iniciará automaticamente por padrão no runlevel 2. Sempre que você ativa ou desativa um serviço no System V, é isso que acontece. Desde que haja um script S (start) sob o diretório de runlevel padrão para um serviço, o daemon init iniciará esse serviço durante a inicialização do sistema.

Para ativar o serviço novamente, insira o seguinte comando:

Passo 6: Testar o Comportamento de Inicialização do MySQL após uma Falha do Sistema

Nesta seção, discutiremos como o System V lida com falhas de serviço. Você pode usar esse conhecimento para configurar o comportamento de seus serviços personalizados após uma falha.

Na primeira parte deste tutorial, fizemos uma alteração no arquivo /etc/inittab para permitir que o MySQL iniciasse automaticamente após uma falha. Adicionamos a seguinte linha para habilitar esse comportamento:

Podemos verificar esse comportamento fazendo alguns testes. Primeiro, reinicie seu VPS inserindo o seguinte comando:

Após a reinicialização, verifique com quais IDs de processo o mysql_safe e o mysqld estão sendo executados, insira o seguinte comando para obter os IDs de processo:

A saída que obtivemos foi:

Anote os IDs dos processos. No nosso caso, foram 1836 e 186338. Agora, simule um travamento encerrando o processo com a opção -9 inserindo o seguinte comando. Lembre-se de substituir pelos seus IDs de processos:

Após alguns minutos, verifique o status do MySQL executando o seguinte comando:

A saída indica que o MySQL está em execução, o que significa que ele foi reiniciado após o travamento simulado. Se você executar o comando ps -ef | grep mysql novamente, você verá que ambos os processos mysqld_safe e mysqld estão em execução, embora com novos IDs.

Você pode tentar encerrar os processos várias vezes e eles serão reiniciados após alguns minutos. Esse comportamento é possível devido à linha que adicionamos ao arquivo /etc/inittab. É assim que você configura serviços para reiniciar automaticamente após um travamento no System V. Para ver a sintaxe novamente, dê uma olhada na Parte 1 deste tutorial.

Alguns serviços personalizados podem conter bugs e falhar ao reiniciar após várias tentativas. O daemon init tentará reiniciar um serviço, mas se falhar mais de dez vezes em dois minutos, o sistema Linux desativará o serviço por até 5 minutos. Isso ajuda a manter o sistema estável e garante que os recursos do sistema não sejam desperdiçados com serviços que estão travando. É uma boa ideia verificar os logs do sistema para identificar problemas com suas aplicações personalizadas que precisam ser corrigidos.

Introdução ao Upstart

O sistema init System V tem sido crucial para as distribuições Linux por muito tempo. No entanto, como é o caso da tecnologia, ela continua avançando. O ecossistema Linux cresceu tremendamente graças ao apoio da comunidade de código aberto. O System V carrega tarefas e serviços de maneira serializada, o que traz complexidade e consome tempo. Além disso, a introdução de mídias de armazenamento plugáveis modernas, para as quais o System V não havia sido projetado, impulsionou a necessidade de um sistema init diferente.

Os desenvolvedores do Ubuntu começaram a trabalhar em outro sistema de inicialização. Esse sistema init foi projetado para lidar com um carregamento mais rápido do sistema operacional, garantir a limpeza adequada de serviços travados, manter a dependência entre os serviços do sistema previsível e dar suporte a mídias de armazenamento plugáveis. O daemon Upstart nasceu.

O init Upstart tem várias vantagens sobre o init System V das seguintes maneiras:

  • O Upstart não carrega serviços de forma serial como o System V, reduzindo assim o tempo de inicialização do sistema.
  • Ele foi projetado para lidar melhor com serviços travados, com limpeza adequada e reinicialização do serviço.
  • O Upstart usa um sistema de eventos flexível para personalizar o gerenciamento de serviços em vários estados.
  • O init evita os scripts de shell complexos para carregar e gerenciar serviços como no System V. O Upstart usa arquivos de configuração simples que são fáceis de entender e modificar.
  • O Upstart foi construído com a compatibilidade com versões anteriores em mente. O script /etc/init.d/rc ainda é executado para gerenciar serviços nativos do System V.
  • Ele evita manter links simbólicos redundantes, todos apontando para o mesmo script.

Eventos do Upstart

O Upstart é baseado em eventos, permitindo que múltiplos eventos sejam associados ao mesmo serviço. Essa arquitetura baseada em eventos garante um gerenciamento de serviços flexível. Cada evento pode chamar um script de shell específico para o evento.

Os eventos do Upstart incluem:

  • Starting
  • Started
  • Stopping
  • Stopped

Entre um evento e outro, um serviço pode estar em vários estados, incluindo, mas não se limitando a:

  • Waiting
  • Pre-start
  • Starting
  • Post-start
  • Running
  • Pre-stop
  • Stopping
  • Post-stop

O init Upstart pode ser configurado para tomar ações para cada um desses estados, daí o seu design flexível.

Sequência de Inicialização do Init Upstart

O init Upstart executa o script /etc/init.d/rc na inicialização, assim como o System V. Este script executa quaisquer scripts de inicialização do System V normalmente para garantir a compatibilidade com versões anteriores.

Os arquivos de configuração do Upstart estão localizados no diretório /etc/init portanto, ele procura lá por padrão e executa os comandos de shell encontrados nos arquivos de configuração sob este diretório.

Arquivos de Configuração do Upstart

O init do Upstart usa arquivos de configuração de serviço para controlar serviços, ao contrário dos scripts bash usados no System V. O padrão de nomenclatura para esses arquivos de configuração de serviço é service_name.conf.

Os arquivos contêm conteúdo em texto simples dividido em várias seções chamadas stanzas. Cada stanza descreve um estado diferente de um serviço e seu comportamento. Diferentes stanzas controlam diferentes eventos de um serviço. Por exemplo, waiting, pre-start, start, pre-stop, stopping, etc.

Uma stanza contém comandos shell, tornando possível iniciar várias ações para cada evento de cada serviço. Além disso, cada arquivo de configuração de serviço especifica as duas seguintes coisas:

  • Em quais runlevels o serviço deve iniciar e parar.
  • Se o serviço deve reiniciar (respawn) se ele falhar.

Estrutura de Diretórios do Upstart

Os arquivos de configuração de serviço do Upstart estão localizados sob o diretório /etc/init. Não confunda isso com /etc/init.d.

Exemplo do Upstart

Neste exemplo, veremos como o Upstart lida com um serviço durante a inicialização do sistema e em caso de falha. Entraremos em mais detalhes explicando os exemplos práticos mostrados na primeira parte deste tutorial.

Passo 1: Fazer login no servidor Ubuntu 14.0.4

Primeiro, para testar o Upstart, usaremos o segundo VPS, aquele que executa o Ubuntu 14.0.4. Isso ocorre porque esta distribuição Linux implementa o Upstart nativamente. Use ssh ou putty se estiver no Windows. Você deve fazer login com um usuário com privilégios de root ou sudo. Eu tenho um usuário chamado hackins, então é assim que eu faria o login:

Substitua pelo seu usuário root/sudo e pelo endereço IP público do servidor. Em seguida, pressione enter e forneça uma senha ou frase secreta.

Passo 2: Examinar os diretórios init e rc

Os arquivos de configuração do Upstart são armazenados no diretório /etc/init. É o diretório que você usará ao criar novos arquivos de configuração de serviço.

Para listar os nomes dos arquivos de configuração no diretório /etc/init, execute o seguinte comando:

Como você verá na saída do comando acima, muitos serviços estão sendo executados sob o Upstart. Pressione Q para sair do less.

Se você executar o seguinte comando para listar os arquivos de configuração de serviço do System V no diretório rc, verá apenas alguns:

Passo 3: Examinar um arquivo do Upstart

Na primeira parte deste tutorial, usamos um arquivo mysql.conf para aprender sobre a configuração do servidor. Para expandir nosso conhecimento, vamos usar uma configuração diferente. O arquivo de configuração do cron é um bom candidato. Digite o seguinte comando para abrir o arquivo:

Você deve obter uma saída semelhante à captura de tela abaixo:

screenshot 4

O script é bastante simples. Observe os seguintes campos importantes: start on, stop on, fork, e respawn. Vamos definir o que essas diretivas estão fazendo:

  • start on instrui o Ubuntu a iniciar o daemon cron quando o sistema entra nos runlevels 2, 3, 4 ou 5. Ele não será executado nos outros runlevels não especificados aqui, ou seja, 0, 1 ou 6.
  • stop on instrui o Ubuntu a parar um daemon em execução. No entanto, neste caso, há um ponto de exclamação (!) que é um sinal de negação. O script não deve ser parado nos runlevels após o ponto de exclamação: 2,3,4,5.
  • fork instrui o Upstart a desvincular o processo do console e mantê-lo em execução em segundo plano.
  • respawn instrui o sistema a iniciar o cron automaticamente se ele falhar por qualquer motivo.

Pressione Ctrl X para sair do editor sem digitar nada.

Outros arquivos de configuração do Upstart seguem a mesma estrutura, com stanzas para start, stop e respawn. Alguns arquivos de configuração podem ter blocos de script adicionais para pre-start, pre-stop, post-start e outros. Esses blocos de código dizem ao sistema o que executar quando um processo está em qualquer um dos estados definidos.

Passo 4: Testar o comportamento de inicialização do serviço MySQL após a inicialização do sistema

O MySQL está configurado por padrão para iniciar automaticamente após a inicialização do sistema. Vamos tentar desativá-lo e ver o comportamento. No Upstart, um serviço pode ser desativado criando um arquivo chamado service_name.override no diretório /etc/init/. O conteúdo do arquivo é apenas uma palavra: manual.

Vejamos como podemos usar este comando para desativar o serviço MySQL. Insira o seguinte comando para abrir o arquivo com o editor nano:

No arquivo aberto, adicione a seguinte linha:

Salve as alterações pressionando Ctrl + O e, em seguida, Enter. Saia do editor pressionando Ctrl + X. Execute o seguinte comando para reiniciar o servidor:

Aguarde alguns minutos e faça login novamente. Assim que estiver logado novamente, teste o status do serviço MySQL inserindo o seguinte comando:

O resultado indicará que o serviço não está em execução:

Isso indica que o MySQL não iniciou automaticamente após a inicialização do sistema. Em seguida, abra o arquivo de configuração do MySQL e verifique se a diretiva start mudou:

O resultado indicará que nada foi alterado:

Isso significa que se o seu serviço não estiver iniciando automaticamente, e você apenas verificar o arquivo de configuração do serviço (service_name.conf), você pode não encontrar o erro. Você também deve verificar a existência do arquivo service_name.override no diretório.

Insira o seguinte comando para excluir o arquivo override e reativar o serviço MySQL. Em seguida, reinicie o servidor:

Assim que o servidor for inicializado, teste o status do serviço MySQL novamente:

Deve mostrar que o serviço MySQL iniciou automaticamente.

Passo 5: Testar o Comportamento de Inicialização do Serviço MySQL após uma Falha do Sistema

Por padrão, o serviço MySQL reinicia automaticamente se falhar. Para interromper esse comportamento, editaremos o arquivo mysql.conf . Insira o seguinte comando para abrir o arquivo com o editor nano:

Encontre as linhas da diretiva respawn e comente-as como mostrado abaixo com #:

Execute os seguintes comandos para reiniciar o serviço:

Usamos os comandos acima para parar e iniciar o serviço porque usar o initctl restart ou initctl reload não funcionaria aqui. Quando você executa o comando para iniciar o serviço MySQL, a saída exibirá um PID para o MySQL como:

Nosso PID foi 1439. Em seguida, anote o que você obteve ao executar o comando, pois o usaremos na próxima etapa. Para simular uma falha, encerre o processo do MySQL usando o seguinte comando, lembrando-se de substituir pelo seu PID conforme explicado acima:

Para verificar se o MySQL reiniciou após a falha, aguarde alguns minutos e insira o seguinte comando:

O resultado indicará que o MySQL está parado:

Tente verificar o status mais algumas vezes para ver se há alguma alteração. Você notará que o MySQL permanece parado. Isso ocorre porque o arquivo de configuração do serviço não possui as diretivas respawn (as que comentamos). Confira a parte 1 deste tutorial para mais explicações sobre a diretiva respawn.

Por que mostramos como desativar a reinicialização automática de serviços após a inicialização ou falha do sistema? Isso serve principalmente para fins de solução de problemas. Se, por exemplo, seu serviço for iniciado e continuar falhando, você pode querer desativá-lo para poder solucionar o problema e também manter seu sistema estável. Você também pode impedir que algumas configurações antigas de serviços sejam reiniciadas automaticamente se você atualizar para uma nova distribuição Linux que venha nativamente com systemd discutido na próxima seção.

Introdução ao Systemd

Systemd é o sistema de inicialização mais recente, encontrado nas distribuições Linux mais recentes. Ele inclui muitos componentes que compõem um sistema Linux moderno.

Systemd gerencia não apenas os serviços, mas também todo o sistema Linux. Nesta seção, focaremos em como o systemd controla o comportamento dos serviços após a inicialização ou falha do sistema.

O Systemd é retrocompatível com scripts e comandos de inicialização do System V. Portanto, se você tiver algum serviço configurado no System V, ele também será executado no Systemd. A maioria dos comandos administrativos do Upstart e do System V foi alterada para funcionar com o Systemd. O Systemd se renomeia para init no momento da inicialização. Um arquivo /sbin/init existe que é um link simbólico para /bin/systemd.

Arquivos de Configuração do Systemd: Arquivos de Unidade

A configuração do Systemd consiste em arquivos de unidade. Cada arquivo de unidade representa um recurso do sistema. Enquanto os outros dois sistemas de inicialização (ou seja, System V e Upstart) eram responsáveis por gerenciar os serviços de um sistema Linux, o Systemd não apenas gerencia os daemons de serviço, mas também outros tipos de recursos do sistema, como caminhos do sistema operacional de dispositivos, sockets, pontos de montagem, etc. Os arquivos de unidade armazenam informações sobre o recurso.

Cada arquivo de unidade representa um recurso específico do sistema com um estilo de nomenclatura de service_name.unit_type. Isso significa que você encontrará arquivos como home.mount, dbus.service, sshd.socket, etc. Os arquivos de unidade são arquivos de texto simples com uma sintaxe declarativa que é fácil de entender e modificar.

Estrutura de Diretórios

O local principal dos arquivos de unidade nativos é o diretório /lib/systemd/system/. Os arquivos de unidade que você cria ou aqueles criados de forma personalizada por administradores de sistema, e outros arquivos de unidade nativos modificados, são armazenados no diretório /etc/systemd/system.

Se um arquivo de unidade com o mesmo nome existir tanto em /lib/systemd/system/ quanto em /etc/systemd/system, o systemd usará aquele que está sob o diretório /etc.

Quando você ativa um serviço para iniciar no momento da inicialização ou em qualquer outro target/runlevel, um link simbólico é criado para esse arquivo de unidade de serviço nos diretórios apropriados em /etc/systemd/system. Os arquivos de unidade no diretório /etc/systemd/system são apenas links simbólicos para os arquivos com nome semelhante no diretório /lib/systemd/system.

Sequência de Inicialização do Systemd: Unidades Target

As unidades target são tipos exclusivos de arquivos de unidade, geralmente com o sufixo .target. As unidades target diferem de outros tipos de arquivos de unidade porque não representam um recurso específico. Em vez disso, elas representam o estado de todo o sistema em um determinado momento.

Para conseguir isso, as unidades target agrupam e iniciam vários arquivos de unidade que fazem parte de um estado específico. Embora os targets do Systemd e os runlevels do System V possam ser comparados de forma geral, eles não são a mesma coisa. Um arquivo de unidade target tem um nome em vez de um número. Por exemplo, você encontrará algo como multi-user.target em vez de runlevel 3 ou reboot.target em vez de runlevel 6. Um sistema Linux pode inicializar com o multi-user.target. Neste caso, ele está basicamente levando o servidor para o runlevel 2, 3 ou 4, o que inicia o sistema no modo de texto multiusuário com a rede ativada.

A diferença está em como ele leva o servidor a esse nível. O System V inicia os serviços sequencialmente. Por outro lado, à medida que o sistema é inicializado, o systemd verifica se existem outros serviços ou recursos e determina sua ordem de carregamento.

Outra diferença entre as unidades target do systemd e os runlevels do System V é que uma distribuição Linux que usa o System V existirá em apenas um runlevel. Se você modificar o runlevel, ele simplesmente mudará para e existirá nesse novo runlevel. Por outro lado, os arquivos de unidade target podem ser inclusivos. Além disso, a ativação de uma unidade target garante que outras unidades target sejam carregadas como parte dela. Por exemplo, se você inicializar um sistema Linux com uma interface gráfica de usuário, ele terá o graphical.target ativado. Isso, por sua vez, garante automaticamente que o multi-user.target também seja carregado e ativado.

Aqui está uma tabela comparando runlevels e targets.

Runlevel (System V) Unidades Target (systemd)
runlevel 0 poweroff.target
runlevel 1 rescue.target
runlevel 2,3,4 multi-user.target
runlevel 5 graphical.target
runlevel 6 reboot.target

Systemd default.target

No systemd, default.target é o equivalente ao runlevel padrão no System V. Vimos que o runlevel padrão no System V era definido no arquivo inittab. No systemd, temos o arquivo default.target. O arquivo target padrão é armazenado no diretório /etc/systemd/system. Ele cria um link simbólico para um dos arquivos de unidade target sob /lib/systemd/system. Alterar o target padrão significa simplesmente recriar um link simbólico e modificar o runlevel do sistema.

No System V, o inittab especificava em qual diretório o Linux encontraria os scripts init. Este poderia ser qualquer um dos diretórios rc como explicado anteriormente. Por outro lado, o target padrão do systemd determina as unidades de recursos a serem carregadas no momento da inicialização. Todas as unidades definidas são carregadas. No entanto, nem todas são carregadas em paralelo, e nem todas são carregadas sequencialmente. O carregamento da unidade de recurso depende dos outros recursos que ela wants ou requires.

Dependências do Systemd: Wants e Requires

Nesta seção, discutiremos como o Systemd lida com dependências. Vimos que com o Upstart, o carregamento paralelo de serviços é possível ao usar arquivos de configuração. Também discutimos como o System V usa runlevels para determinar qual serviço iniciar automaticamente ou esperar até que outro serviço ou recurso seja iniciado. Da mesma forma, os serviços do Systemd podem ser configurados para carregar em um ou mais targets, ou esperar até que outro serviço ou recurso seja iniciado.

No Systemd, um arquivo de unidade que requires outra unidade não iniciará até que a unidade requerida seja carregada e se torne ativa. Se a unidade requerida falhar ao carregar enquanto a primeira unidade estiver ativa, a primeira unidade irá parar.

Este comportamento garante a estabilidade do sistema. Um serviço que requires um recurso específico (por exemplo, uma porta) para estar disponível e ativo pode, assim, ser feito esperar até que o recurso esteja disponível (ou seja, a porta esteja aberta).

Em contraste, uma unidade que wants outra unidade não impõe tais restrições. Ela não irá parar se a unidade desejada parar enquanto a unidade chamadora ainda estiver ativa. Por exemplo, alguns serviços não essenciais no modo graphical-target.

Exemplo do Systemd

Vejamos como podemos configurar o comportamento de um serviço no systemd.

Passo 1: Faça login na sua instância VPS

Usaremos o MySQL como um serviço da vida real e o CentOS 7 como servidor. Para seguir as etapas na prática e entender os conceitos, faça login no seu VPS CentOS 7 ou crie um na CloudSigma. Um VPS executando a distribuição CentOS 7, Debian 7 ou 8, ou Ubuntu 15 ou mais recente é apropriado para esta seção, pois todos vêm com o systemd. Faça login usando o comando ssh ou, se estiver no Windows, use o PuTTY:

Passo 2: Examine o arquivo default.target e as dependências

A sequência de inicialização do Systemd segue uma longa cadeia de dependências que discutiremos em detalhes nesta seção.

  • default.target

O arquivo default.target controla os serviços que iniciam durante uma inicialização normal. Você pode listar o arquivo de unidade target padrão usando o seguinte comando:

A saída mostra algo como a captura de tela abaixo:

screenshot

A captura de tela mostra que o target padrão aponta via link simbólico para o arquivo multi-user.target no /lib/systemd/system/ diretório. Isso significa que, por padrão, o sistema será iniciado sob o multi-user.target, equivalente ao runlevel 3.

  • multi-user.target.wants

Para ver todos os serviços que o arquivo multi-user.target deseja, insira o seguinte comando:

A saída contém muitas linhas, aqui está um trecho:

Como a saída mostra, eles são links simbólicos que apontam para os arquivos de unidade reais no diretório /lib/systemd/system/. Destacamos mysqld.service para lhe mostrar que ele também faz parte do multi-user.target. Se você quiser confirmar se um determinado serviço está configurado para inicialização, você pode modificar o comando para esse arquivo. Por exemplo, podemos filtrar as saídas para encontrar o daemon mysql ou cron usando os seguintes comandos:

A saída mostrará:

Para filtrar o resultado para o daemon cron, insira o seguinte comando:

A saída mostrará:

Além do multi-user.target, existem outros tipos diferentes de targets, ou seja, system-update.target ou basic.target.

Insira o seguinte comando para ver de quais targets o multi-user target depende:

A saída mostra:

Isso significa que o basic-target deve ser carregado primeiro para que o sistema seja iniciado no modo multi-user.target.

  • basic-target

Insira o seguinte comando para ver quais outros targets o basic.target deseja:

O resultado mostrará:

  • sysinit.target

Pode executar o seguinte comando para ver se existem targets necessários para sysinit.target. A sintaxe do comando é a mesma. Pode continuar a modificá-lo para ver quais unidades de target são necessárias para outra unidade de target à medida que avança. Aqui está o comando:

O resultado mostrará que não existem unidades necessárias para sysinit.target. Podemos verificar se existem outros serviços e targets desejados por sysinit.target utilizando o seguinte comando:

O resultado mostra uma longa lista de serviços e targets desejados por sysinit.target. Pode ver parte do resultado abaixo:

Durante a inicialização do sistema com o system4, o sistema não permanece apenas num target. Em vez disso, carrega serviços de forma dependente à medida que se move de um target para outro.

Passo 3: Examinar um Arquivo de Unidade

Vejamos como é um arquivo de unidade. Tínhamos utilizado o arquivo de unidade do serviço MySQL na primeira parte deste tutorial, e voltaremos a utilizá-lo. No entanto, também podemos olhar para outro arquivo de unidade de serviço – o arquivo de unidade sshd. Introduza o seguinte comando para abrir o arquivo de configuração do sshd:

Abaixo está uma captura de ecrã que mostra as linhas no arquivo:

unit screesnhot

Como pode ver, os blocos de código delineados no arquivo facilitam a compreensão e a modificação sempre que necessário. Abaixo estão algumas diretivas importantes a compreender:

  • After – a cláusula After indica ao sistema para carregar o serviço apenas após o carregamento dos targets e serviços especificados. Neste caso, o serviço SSHD será carregado após o carregamento do target de rede e do serviço keygen.
  • Wants – a cláusula Wants mostra quais targets desejam este serviço. Neste caso, o ssh-keygen.service deseja o sshd.service. No entanto, se o sshd falhar ou falhar inesperadamente, não irá encerrar o ssh-keygen.service.

Pressione Ctrl + X para fechar o editor.

Passo 4: Testar o Comportamento de Inicialização do Serviço MySQL no Arranque do Sistema

Nesta secção, mostraremos como pode alterar e testar o comportamento do serviço MySQL no momento do arranque do sistema. Na secção anterior, vimos que o mysqld.service é desejado pelo multi-user.target. Por isso, será iniciado automaticamente no arranque.

Pode desativar o serviço executando o seguinte comando:

A execução do comando mostra que o symlink do mysql é removido do diretório /etc/systemd/system/multi-user.target.wants/. Para testar isto, execute o seguinte comando para testar se o MySQL ainda é desejado pelo multi-user.target:

O comando não retorna nada. Se você tentar reiniciar o servidor e verificar o status do MySQL, ele não estará em execução, o que significa que não iniciou automaticamente na inicialização.

Agora reative o serviço usando o comando:

A saída mostrará um link simbólico. Se você reiniciar o servidor, o MySQL deve iniciar automaticamente. Ativar um serviço do Systemd cria um link simbólico no diretório wants do target padrão. Desativar um serviço do Systemd remove o link simbólico do wants diretório.

Passo 5: Testar o Comportamento de Inicialização do Serviço MySQL após uma Falha do Serviço

Por padrão, o serviço MySQL iniciará automaticamente caso falhe. Podemos desativar esse comportamento no arquivo de configuração do Systemd para o MySQL. Primeiro, vamos dar uma olhada no arquivo. Digite o seguinte comando para abrir o arquivo:

A captura de tela abaixo mostra a saída:

screen shot 5

O valor da diretiva Restart está definido como on-failure. Isso significa que o serviço MySQL será reiniciado após códigos de saída incorretos, tempo limite ou sinais incorretos. Abaixo está uma tabela mostrando alguns dos parâmetros de reinicialização da página de manual.

Configurações de reinicialização/Causas de saída no always on-success on-failure on-abnormal on-abort on-watchdog
código de saída limpo ou sinal X X
Código de saída incorreto X X
Sinal incorreto X X X X
Tempo limite X X X
Watchdog X X X X

As duas diretivas importantes em um arquivo de unidade do Systemd são Restart e RestartSec. Elas controlam o comportamento de falha do serviço. Restart especifica quando o serviço deve ser reiniciado, e RestartSec especifica quanto tempo ele deve esperar antes de reiniciar após uma falha. Para desativar o comportamento de reinicialização, comente a diretiva Restart adicionando um # no início da linha, como mostrado:

Agora, recarregue o daemon do sistema e, em seguida, recarregue o serviço mysqld usando os seguintes comandos:

Em seguida, execute o seguinte comando para encontrar o PID principal do serviço MySQL:

screenshot 7

O PID principal para o nosso teste foi 23809. Anote o seu para usar no próximo comando. Usando o comando kill -9, simule uma falha encerrando o processo. Além disso, lembre-se de substituir pelo número do processo que você obteve no seu teste:

Se você executar o comando que verifica o status do MySQL, verá que ele não está ativo e falhou ao reiniciar:

screesnshot 8

Ele permanecerá no estado de falha enquanto a diretiva Restart estiver comentada no arquivo de configuração mysqld.service. Isso emula uma falha onde um serviço para e não volta a funcionar.

Para reativar o serviço, você pode editar o arquivo de configuração mysqld.service, descomentar a diretiva Restart, salvar e fechar. Como fez anteriormente, recarregue o daemon e reinicie o serviço. Isso leva o serviço de volta à sua configuração inicial, e agora ele pode iniciar automaticamente após uma falha. Finalmente, isso é tudo para configurar um serviço para iniciar automaticamente após uma falha. Se você deseja configurar serviços para iniciar automaticamente após uma falha, basta adicionar a diretiva Restart directive, (e se desejar, também pode adicionar a diretiva RestartSec), sob a seção [Service] do arquivo de unidade do serviço.

Conclusão

Neste tutorial, discutimos como o Linux lida com serviços durante a inicialização ou após uma falha. Para entender o processo de inicialização do sistema Linux, discutimos os três sistemas init que o Linux usa: System V, Upstart e Systemd. Discutimos sua evolução e como cada processo init funciona em relação à inicialização automática de um serviço após uma reinicialização do sistema ou falha.

Como tanto os daemons init quanto as distribuições Linux têm evoluído ao longo do tempo, lembre-se de verificar a versão da distribuição Linux que você está executando para saber qual daemon init seu sistema suporta nativamente.

Os aplicativos nativos do Linux e a maioria dos aplicativos de terceiros já iniciam automaticamente após a inicialização ou falha do sistema, então você não precisará fazer nada. O conhecimento neste tutorial é crucial ao configurar o comportamento de inicialização e respawn de seus próprios serviços personalizados, ou ao solucionar problemas de serviços que travam constantemente.

Boa computação!

author

Manpreet Singh

Autor · CloudSigma

Preslav Dobrev é um designer criativo na CloudSigma, focado na construção de uma identidade empresarial consistente por meio de canais de marketing tradicionais e inovadores. Ele é hábil em combinar a visão artística com o marketing estratégico para criar narrativas de marca impactantes.

Comentários

Nenhum comentário ainda. Seja o primeiro.