Systemd

Entendendo o Systemd

O Linux usa o SysVinit para gerenciamento de scripts e boot, seguindo o mesmo padrão do SVr4 do UNIX e ainda encontrado em várias distribuições Linux, com todo o seus scripts centralizados em /etc/init.d. Algumas outras como o Slackware seguem o padrão BSDInit com todos os seus scripts centralizados em /etc/rc.d/ , e dependente ainda do /etc/rc.local, com definições diferentes de processo de boot. Lembrando que a grande diferença esta no comportamento do processo “pai” de todos os processos, o velho init, seja ele gerenciando níveis de execução de scripts no sistema ou modos multi-user e mono-user. O systemd abre sockets para comunicação entre os serviços, afim de que todos os serviços marcados pelo administrador como target possam iniciar em paralelo e caso possua dependencias com outros serviços, estes também sejam iniciados sob demanda. O Systemd é compatível com o sysvinit.

O systemd foi desenvolvido para centralizar a forma como os processos, serviços e scripts são gerenciados pelo processo pai, substituindo o famoso e poderoso sysvinit e bsdinit. Muitas distribuições ja estão com o systemd embutidas como o Gentoo (uma das melhores distros pra mim), que substituiu o seu OpenRC pelo systemd e até mesmo o Fedora que desde a versão 15/16 recebeu por definitivo o novo gerenciamento do sistema, como outras distribuições também receberam, o poderoso Archlinux (distribuição que tanto usei no passado e inicio de desenvolvimento), OpenSuSE e outras também receberam o novo gerenciador de sistema. O systemd usa o cgroups ou control groups, para agrupar os programas ou processos. O systemd ao gerenciar um serviço, pode agir de diversas maneiras em dispositivos e em outros processos e conclui todos estes eventos encerramento todos os processos filhos no mesmo cgroup. Mas e o cgroups? O cgroups permite atribuir tags aos processos e registra-os em um pseudo-filesystem em /sys que permite qualquer outro programa e usuário. O cgroups esta no kernel a muito tempo e desde a versão 2.6, sendo muito mais aproveitado hoje. Ele também requer muito mais o consumo de CPU para cada criação de um novo processo, e então usa o wonder-patch do kernel que reduz a percepção de latência pelo usuário.

O Systemd usa o /etc/fstab durante a inicialização do sistema e cria políticas de montagens automáticas, sendo assim, não havendo mais a necessidade do autofs. Isso ai já não existe mais no systemd (me refiro ao pacote e ao serviço e não ao modulo do autofs do kernel que é bastante utilizado pelo systemd, o que muda é a maneira como ele se comporta). Ele utiliza o diretório /lib/systemd/system com os sufixos como: .service (que define servicos do sistema, como antes em /etc/init.d), .target (que define o apontamento para qual gerenciamento o sistema vai se conectar, muito semelhante a runlevels e o que voce fazia no /etc/inittab), arquivos .mount (definem quais sistemas de arquivos devem montar e em quais diretórios). Durante o processo de boot o systemd monta primeiro o diretório /var/run para que mantém os arquivos com suas respectivas informações de processos, seguido da montagem de /sys/kernel e suas partições definidas em /etc/fstab. Mas ai esta um fato importantíssimo, o systemd não depende ou não precisa do arquivo /etc/fstab para saber quais sistemas de arquivos devem ser montados e em quais pontos de montagens (diretórios). Vale lembrar novamente que os arquivos .mount são responsáveis por montar devices, sem a necessidade do tradicional /etc/fstab, mas uma vez montado, sempre montado a não ser que voce desmonte com o comando umount. Isso define que o diretório somente será utilizado quando for acessado, caso será montado. Mas um aviso, cuidado ao mexer no /lib/systemd/system, mexa somente no /etc/systemd/system, pois todo o seu processo de configuração deve partir dali pelo administrador. Uma solução para o automount do systemd é voce criar os arquivos .automount neste mesmo diretório, apenas contendo o seguinte:

[Automount]
Where = /dados

Dentro do diretório /lib/systemd/system, voce encontra todos os pontos de montagens nos seus respectivos sistemas de arquivos e permissões padrão. Voce encontra as seguintes linhas no exemplo do arquivo var-run.mount:

[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime

Entendendo: em [ ] esta o nome do o tipo de objeto que é de montagem, o “What” diz qual é device ou pseudo-device, “Where” diz a onde deve ser montado, “Type” define qual é o sistema de arquivos e “Options” as opções de montagem como nosuid, noexec, mode e outros. Lembra muito o /etc/filesystem do AIX nao? Embaixo segue outro exemplo:

[Mount]
What=/dev/sda8
Where=/dados
Type=ext4
Options=noexec,noatime

Outros arquivos (como um exemplo do meu Fedora)

# ls *.mount (adicionei uma , para vc separar bem)
dev-hugepages.mount, proc-sys-fs-binfmt_misc.mount,  sys-kernel-debug.mount
dev-mqueue.mount,  sys-fs-fuse-connections.mount,  tmp.mount
proc-fs-nfsd.mount,  sys-kernel-config.mount,  var-lib-nfs-rpc_pipefs.mount

No padrão SysvInit do RedHat, Debian, Ubuntu, SuSE e como todas as outras ditros que utilizam do mesmo formato, o operador do daemon é o comando service, como o invoke-rc.d a anos no Debian. Até o proprio Ubuntu por ser baseado totalmente no Debian, usa o service pela total adaptação do sysvinit do rh ao sistema. Tal como a gerencia de scripts (scripts rc), vinculados a runlevel conectada, esta gerenciada ainda em /etc/rcX.d com ligações simbolicas de /etc/init.d, por definições de prioridades e ordem do processo de boot.

Mas no systemd, tudo muda. Desde o init=/sbin/systemd ao processo principal.

No systemd usa-se o systemctl, que parece demais com o launchctl do OSX e um pouco com o svcadm  do Solaris (O Solaris 10 reescreveu todo o gerenciamento de scripts e daemon ao optar de svr4init para SMF/FMRI, que é excelente). O systemctl permite gerenciar todos os serviços durante o processo de boot e no sistema ativo. Funciona do seguinte modo: systemctl <opções> <endereço>

Para saber todos os serviços ativos, montados, em aguardo, desabilitado, como plugado, socket ativo, no momento digite: systemctl com as opções –all (ou -a) para tudo conectado ao systemd e list-units que permite verificar apenas uma unidade do systemd como os serviços e targets, exemplo para visualizar apenas os serviços, como antes no /etc/rc.d ou /etc/init.d:  systemctl list-units –type=service ou systemctl list-units -t service

Exemplo:

rpcbind.service loaded active running RPC bind service
rsyslog.service loaded active running System Logging Service
rtkit-daemon.service loaded active running RealtimeKit Scheduling Policy Service
sendmail.service loaded active running Sendmail Mail Transport Agent

Outro exemplo é a visualização apenas dos arquivos em linha que estão  /lib/systemd/system pelo comando systemctl list-unit-files, como antes vc listava no /etc/rc.d/init.d, /etc/rc.d ou /etc/init.d

[root@fedora ~]# systemctl list-unit-files -t service
UNIT FILE STATE
abrt-ccpp.service enabled
abrt-oops.service enabled
abrt-pstoreoops.service disabled
abrt-vmcore.service enabled
abrt-xorg.service enabled
abrtd.service enabled
accounts-daemon.service enabled
alsa-restore.service static
alsa-state.service static
alsa-store.service static
arp-ethers.service disabled
atd.service enabled
auditd.service enabled
autovt@.service disabled
avahi-daemon.service enabled

Note que quando você utliza o systemctl para executar um enable e disable, o mesmo que chkconfig, para habilitar o serviço para a sua runlevel conectada e para o próximo boot, ele cria sozinho pra você o link de /usr/lib/systemd/system/ para /etc/systemd/system, seja na runlevel mult-target e graphical, pois as coisas agora mudaram. Antes, o chkconfig (redhat, fedora, centos e suse) ou update-rc.d (debian e ubuntu), criavam de /etc/rc(sua runlevel).d para /etc/rc.d/init.d ou /etc/init.d.

# systemctl enable sm-client
ln -s ‘/usr/lib/systemd/system/sm-client.service’ ‘/etc/systemd/system/multi-user.target.wants/sm-client.service’

Para iniciar, parar ou restart um serviço no systemd, nao é mais pelo service e muito menos no path completo em /etc/init.d/servico e sim com:

# systemctl start serviço
# systemctl stop serviço
# systemctl status serviço
# systemctl –system daemon-reload

Geralmente voce deve deve colocar .service no final de cada serviço especificado no comando systemctl, que é o operador do systemd para maior entedimento dos arquivos de /lib/systemd, mas mesmo que voce não coloque, vai funcionar.

* nota que a opção status informa todo o SYSOUT do processo pelo systemd, como os erros, eventos, relacionados, dependencias e warnings.

* nota que o comando systemctl daemon-reload faz com que o systemd releia todos os daemons fixando tudo no seu devido lugar, uma espécie de refresh nos links.

Quando voce executa o comando systemctl como informado antes, ele lista todos os conectores como serviços, targets e outros (isso se executado com -a, se não apenas serviços), são visualizados as seguintes colunas: UNIT que define o nome do objeto, LOAD que diz se o serviço esta sim ou nao carregado ou com error, ACTIVE que informa qual é o status do serviço com o systemd se esta ativo ou inativo,SUB que informa mais detalhes da coluna active e possui uma informação muito importante, como dead que informa que o serviço esta parado, ativo, waiting que informa os serviços sob demanda, running, mounted e plugged (apenas para pontos de montagens e devices em questão) e failed que é uma possivel falha que pode ser explorada pelo systemctl status.

Exemplo abaixo do resultado de systemctl.-a

sysinit.target loaded active active System Initialization
rsyslog.target error inactive dead rsyslog.target
time-sync.target loaded inactive dead System Time Synchronized

Então eu tive que verificar com o comando: systemctl status rsyslog.target, e entendi qual era o problema.

# sysctl status rsyslog.target
rsyslog.target
Loaded: error (Reason: No such file or directory)
Active: inactive (dead)

Todos os serviços que são verificados com o comando systemctl,  na coluna SUB, identificados como exited, não é um serviço e apenas um comando para executar um serviço ou aplicação, como no caso do iptables (no fedora), sysctl, lvm, mdadm, lm-sensors e outros.

Outra informação importante é como o systemd entende agora os níveis de execução no sistema Linux, ou seja a runlevel. Por padrão a runlevel do RedHat, Fedora, CentOS para modo texto, sem a necessidade de parar o daemon de gerenciador de login é a 3, ja para iniciar o sistema no gráfico é a 5. Vale lembrar que essa informação não se aplica ao Debian e Ubuntu, que tudo fica no tty7 e basta interromper o gdm ou lightdm com /etc/init.d/[lightdm ou gdm] stop.

No systemd agora a runlevel conectada é orientada  ao link simbolico /etc/systemd/system/default.target que aponta para o arquivo em /lib/systemd/system/*target, que define qual a runlevel ativada no sistema.  Seja ele /lib/systemd/system/multi-user.target (modo texto e equivalente a runlevel 3), ou /lib/systemd/system/graphical.target (modo gráfico e equivalente a runlevel 5), sendo que existem varios outros arquivos de target e com as mesmas definições “simuladas” do tradicional sysvinit, como os arquivos runlevel2.target, que na verdade apontam para o multi-user.target. Nesse sentido, o sistema fica muito proximo do que era no bom e velho formato BSD, ou é multi-user ou é graphical-user. Mas isso quer dizer que o comando telnet e init nao funcionam mais? Sim funcionam por questões de compatibilidade do systemd ao sysvconfig.

Para trocar para a runlevel 3

ln -sf /lib/systemd/system/multi-user.target   /etc/systemd/system/default.target

ou pelo proprio systemctl com o comando: systemctl isolate multi-user.target

Para trocar para a runlevel 5

ln -sf /lib/systemd/system/graphical.target   /etc/systemd/system/default.target

ou pelo proprio systemctl com o comando: systemctl isolate graphical.target

 

Mas definitivamente o que a runlevel inicia de serviço se eu estiver conectado na multi-user? Dentro de /lib/systemd/system existem os mesmos arquivos de .target apontando os serviços que serao iniciados com novos links dentro deles, ou seja, para ver tudo que será iniciado nessa runevel basta lista os arquivos em /lib/systemd/system/multi-user.target.wants/.

Como são de responsabilidade do administrador definir quais tty’s receberão um getty, o diretório é criado por padrão em  /etc/systemd/system/. Então o systemd carrega um getty nos tty’s 1 a 6 (ainda sendo como links simbolicos como em (/lib/systemd/system/getty@.service. Todos os serviços com nome <algo>@.service têm esta propriedade e podem existir em várias instâncias, sobre outros serviços ou sobre outros recursos. Por padrão todos os serviços relacionados aos targets, são armazenados em /etc/systemd/system/multi-user.target.wants/ e isso é muito importante.

Um serviço é configurado no systemd em  /etc/systemd/system respeitando os target (runlevel) que voce vai se conectar, como em /etc/systemd/system/multi-user.target.wants/ para runlevel 3 e  /etc/systemd/system/graphical.target.wants, para runlevel 5 OU /etc/systemd/system/default.target.wants para o padrão, sendo utilizado por qualquer runlevel conectada, pois é a default.

Até os scripts e comandos de desligamento do sistema operacional mudou, mudou totalmente. Teoricamente os comandos shutdown, halt, poweroff, reboot não deveriam funcionar pois arrancam e descarregam processos do formato antigo, no svr4 – sysvinit, conectando o sistema na runlevel 0 (para halted) e runlevel 6 (para reboot).

O correto para desligar e reiniciar o sistema agora é utilizar os seguintes comandos:

# systemctl poweroff
# systemctl reboot

Mas por padrão voce nem precisa se preocupar, pois por padrão estas distros que ja acompanham o systemd ja possuem o binário ou scripts modificados para isso.

Antes de encerrar essa materia, vale a pena entender que os serviços, assim como os targets, sockets e todo o resto, são configurados pelo proprio systemd centralizando todas as informações do processo de inicializaçao do sistema operacional e gerencia nele. Mas onde podemos configurar os serviços? Não se assuste se voce observar que o diretório /etc/init.d esta praticamente vazio e o comando service nao encontra nada, a resposta é bem tranquila, em  /etc/systemd/system/, sempre. Segue um exemplo abaixo de como se encontra a configuração para o serviço (arquivo .service) do sshd, nao por sysvinit em /etc/rc.d/init.d (ou /etc/init.d) mas pelo systemd em /etc/systemd/system/*.service ou /etc/systemd/system/multi-user.target.wants/  com os links apontados para /usr/lib/systemd/system/ (como exemplo o gentoo e fedora).

Arquivo sshd.service: 

[Unit]
Description=OpenSSH server daemon
After=rsyslog.target network.target auditd.service

[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process

[Install]
WantedBy=multi-user.target

Existem vários parâmetros bem legais de configurar no systemd para serviços que vou deixar para a próxima matéria. Mas os serviços são configurados pelos campos “Unit” que define as descrições do serviço, “Service” que define os comandos de execução e opções para a execução e “Install” que define a qual target ele esta associado.

Vale a pena voce entender que o Linux somente tem a ganhar com o systemd como o OSX Unix teve pela substituição do init SVr4 pelo launchd.Assim como o serviço de gerenciamento de serviços do antigo Solaris 9 foi totalmente reescrito para o uso de SMF/FMRI pelo svc/svcadm e do histórico, bom, velho e poderoso ODM do AIX um dos mais interessantes. Por lá, voce gerencia todo o sistema operacional pelos seus Objects Managers e isso é muito bom.

O systemd usa como base o o Rsyslog ou Syslog-NG e centraliza essa informação em /etc/systemd/system/syslog.service.

Linux é o poder ;)

Aprígio Simões
@aprigiosimoes

Powered by Moblie Video for WordPress + Daniel Watrous