One place for hosting & domains

      Gerenciar

      Como usar o ps, kill e nice para gerenciar processos no Linux


      Introdução


      Um servidor Linux, assim como qualquer outro computador que você conheça, executa aplicativos. Para o computador, eles são considerados “processos”.

      Embora o Linux lide nos bastidores com o gerenciamento de baixo nível no ciclo de vida de um processo, você precisará de uma maneira de interagir com o sistema operacional para gerenciá-lo de um nível superior.

      Neste guia, vamos discutir alguns aspectos simples do gerenciamento de processos. O Linux oferece uma coleção abundante de ferramentas para esse propósito.

      Vamos explorar essas ideias em um VPS Ubuntu 12.04, mas qualquer distribuição moderna do Linux funcionará de maneira similar.

      Como visualizar processos em execução no Linux


      top


      A maneira mais fácil de descobrir quais processos estão sendo executados no seu servidor é executando o comando top:

      top***
      
      top - 15:14:40 up 46 min,  1 user,  load average: 0.00, 0.01, 0.05 Tasks:  56 total,   1 running,  55 sleeping,   0 stopped,   0 zombie Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st Mem:   1019600k total,   316576k used,   703024k free,     7652k buffers Swap:        0k total,        0k used,        0k free,   258976k cached   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND               1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 init                   2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd               3 root      20   0     0    0    0 S  0.0  0.0   0:00.07 ksoftirqd/0            6 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0            7 root      RT   0     0    0    0 S  0.0  0.0   0:00.03 watchdog/0             8 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 cpuset                 9 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 khelper               10 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kdevtmpfs          
      

      A porção superior de informações mostra estatísticas do sistema, como a carga do sistema e o número total de tarefas.

      É possível ver facilmente que há 1 processo em execução e 55 processos estão suspensos (ou seja, ociosos/sem utilizar recursos da CPU).

      A parte inferior mostra os processos em execução e suas estatísticas de uso.

      htop


      Uma versão melhorada de top, chamada htop, está disponível nos repositórios. Instale-o com este comando:

      sudo apt-get install htop
      

      Se executarmos o comando htop, veremos que as informação são exibidas de uma maneira mais inteligível:

      htop***
      
        Mem[|||||||||||           49/995MB]     Load average: 0.00 0.03 0.05   CPU[                          0.0%]     Tasks: 21, 3 thr; 1 running   Swp[                         0/0MB]     Uptime: 00:58:11   PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command  1259 root       20   0 25660  1880  1368 R  0.0  0.2  0:00.06 htop     1 root       20   0 24188  2120  1300 S  0.0  0.2  0:00.56 /sbin/init   311 root       20   0 17224   636   440 S  0.0  0.1  0:00.07 upstart-udev-brid   314 root       20   0 21592  1280   760 S  0.0  0.1  0:00.06 /sbin/udevd --dae   389 messagebu  20   0 23808   688   444 S  0.0  0.1  0:00.01 dbus-daemon --sys   407 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.02 rsyslogd -c5   408 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5   409 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5   406 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.04 rsyslogd -c5   553 root       20   0 15180   400   204 S  0.0  0.0  0:00.01 upstart-socket-br
      

      Aprenda mais sobre como usar o top e htop aqui.

      Como usar o ps para listar processos


      Tanto o top quanto o htop fornecem uma interface agradável para visualizar processos em execução, de maneira semelhante a um gerenciador de tarefas gráfico.

      No entanto, essas ferramentas nem sempre são flexíveis o suficiente para abranger adequadamente todos os cenários. Um comando poderoso chamado ps é geralmente a resposta para esses problemas.

      Quando chamado sem argumentos, o resultado pode ser um pouco confuso:

      ps***
      
        PID TTY          TIME CMD  1017 pts/0    00:00:00 bash  1262 pts/0    00:00:00 ps
      

      Esse resultado mostra todos os processos associados ao usuário e sessão de terminal atuais. Isso faz sentido porque estamos executando apenas o bash e ps com esse terminal atualmente.

      Para conseguirmos uma visão mais completa dos processos neste sistema, podemos executar o seguinte:

      ps aux***
      
      USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND root         1  0.0  0.2  24188  2120 ?        Ss   14:28   0:00 /sbin/init root         2  0.0  0.0      0     0 ?        S    14:28   0:00 [kthreadd] root         3  0.0  0.0      0     0 ?        S    14:28   0:00 [ksoftirqd/0] root         6  0.0  0.0      0     0 ?        S    14:28   0:00 [migration/0] root         7  0.0  0.0      0     0 ?        S    14:28   0:00 [watchdog/0] root         8  0.0  0.0      0     0 ?        S<   14:28   0:00 [cpuset] root         9  0.0  0.0      0     0 ?        S<   14:28   0:00 [khelper] . . .
      

      Essas opções dizem ao ps para mostrar processos de propriedade de todos os usuários (independentemente da sua associação de terminais) em um formato facilmente inteligível.

      Para ver um modo de exibição em árvore, onde relações hierárquicas são mostradas, executamos o comando com essas opções:

      ps axjf***
      
       PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND     0     2     0     0 ?           -1 S        0   0:00 [kthreadd]     2     3     0     0 ?           -1 S        0   0:00  _ [ksoftirqd/0]     2     6     0     0 ?           -1 S        0   0:00  _ [migration/0]     2     7     0     0 ?           -1 S        0   0:00  _ [watchdog/0]     2     8     0     0 ?           -1 S<       0   0:00  _ [cpuset]     2     9     0     0 ?           -1 S<       0   0:00  _ [khelper]     2    10     0     0 ?           -1 S        0   0:00  _ [kdevtmpfs]     2    11     0     0 ?           -1 S<       0   0:00  _ [netns] . . .
      

      Como se vê, o processo kthreadd é mostrado como um pai do processo ksoftirqd/0 e de outros.

      Uma nota sobre IDs de processo


      No Linux e em sistemas do tipo Unix, cada processo é atribuído a um ID de processo, ou PID. É assim que o sistema operacional identifica e mantém o controle dos processos.

      Uma maneira rápida de obter o PID de um processo é com o comando pgrep:

      pgrep bash***
      
      1017
      

      Isso irá simplesmente consultar o ID do processo e retorná-lo.

      Ao primeiro processo gerado na inicialização do sistema, chamado init, é atribuído o PID de “1″.

      pgrep init***
      
      1
      

      Esse processo é então responsável por gerar todos os processos no sistema. Os processos posteriores recebem números PID maiores.

      O pai de um processo é o processo que foi responsável por gerá-lo. Os processos pais possuem um PPID, que pode ser visto no cabeçalho da coluna correspondente em muitos aplicativos de gerenciamento de processos, incluindo o top, htop e ps.

      Qualquer comunicação entre o usuário e o sistema operacional em relação aos processos envolve a tradução entre os nomes de processos e PIDs em algum ponto durante a operação. É por isso que os utilitários informam o PID.

      Relacionamentos pai/filho


      A criação de um processo filho acontece em dois passos: fork(), que cria espaços de endereço e copia os recursos de propriedade do pai via copia em gravação para que fique disponível ao processo filho; e exec(), que carrega um executável no espaço de endereço e o executa.

      Caso um processo filho morra antes do seu pai, o filho torna-se um zumbi até que o pai tenha coletado informações sobre ele ou indicado ao kernel que ele não precisa dessas informações. Os recursos do processo filho serão então libertados. No entanto, se o processo pai morrer antes do filho, o filho será adotado pelo init, embora também possa ser reatribuído a outro processo.

      Como enviar sinais de processos no Linux


      Todos os processos no Linux respondem a sinais. Os sinais são uma maneira ao nível de SO de dizer aos programas para terminarem ou modificarem seu comportamento.

      Como enviar sinais de processos por PID


      A maneira mais comum de passar sinais para um programa é com o comando kill.

      Como se espera, a funcionalidade padrão desse utilitário é tentar encerrar um processo:

      <pre>kill <span class=“highlight”>PIDoftarget_process</span></pre>

      Isso envia o sinal TERM ao processo. O sinal TERM pede ao processo para encerrar. Isso permite que o programa execute operações de limpeza e seja finalizado sem problemas.

      Se o programa estiver se comportando incorretamente e não se encerrar quando um sinal TERM for passado, podemos escalar o sinal passando o sinal KILL:

      <pre>kill -KILL <span class=“highlight”>PIDoftarget_process</span></pre>

      Esse é um sinal especial que não é enviado ao programa.

      Ao invés disso, ele é dado ao kernel do sistema operacional, que encerra o processo. Isso é usado para passar por cima de programas que ignoram os sinais que lhe são enviados.

      Cada sinal possui um número associado que pode ser passado ao invés de seu nome. Por exemplo, é possível passar “-15″ ao invés de ”-TERM” e ”-9″ ao invés de ”-KILL”.

      Como usar sinais para outros fins


      Os sinais não são usados apenas para encerrar programas. Eles também podem ser usados para realizar outras ações.

      Por exemplo, muitos daemons são reiniciados quando recebem o HUP, ou sinal de desligamento. O Apache é um programa que funciona dessa forma.

      <pre>sudo kill -HUP <span class=“highlight”>pidofapache</span></pre>

      O comando acima fará com que o Apache recarregue seu arquivo de configuração e retome o serviço de conteúdo.

      Liste todos os sinais que podem ser enviados com o kill digitando:

      kill -l***
      
      1) SIGHUP    2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP  6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM . . .
      

      Como enviar sinais de processos pelo nome


      Embora a maneira convencional de enviar sinais seja através do uso de PIDs, também existem métodos para fazer isso com os nomes regulares dos processos.

      O comando pkill funciona de maneira bastante similar ao kill, com a diferença de operar com um nome de processo:

      pkill -9 ping
      

      O comando acima é equivalente a:

      kill -9 `pgrep ping`
      

      Se quiser enviar um sinal para todas as instâncias de um determinado processo, utilize o comando killall:

      killall firefox
      

      O comando acima enviará o sinal TERM para todas as instâncias do firefox em execução no computador.

      Como ajustar prioridades de processos


      Geralmente, é desejável ajustar quais processos recebem prioridade em um ambiente de servidor.

      Alguns processos podem ser considerados críticos para sua situação, enquanto outros podem ser executados sempre que houver recursos sobrando no sistema.

      O Linux controla a prioridade através de um valor chamado niceness (gentileza).

      As tarefas de alta prioridade são consideradas menos nice (gentis), porque não compartilham recursos tão bem. Por outro lado, os processos de baixa prioridade são nice, porque insistem em utilizar apenas a menor quantidade de recursos.

      Quando executamos o top no início do artigo, havia uma coluna marcada “NI”. Esse é o valor de gentileza do processo:

      top***
      
       Tasks:  56 total,   1 running,  55 sleeping,   0 stopped,   0 zombie Cpu(s):  0.0%us,  0.3%sy,  0.0%ni, 99.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st Mem:   1019600k total,   324496k used,   695104k free,     8512k buffers Swap:        0k total,        0k used,        0k free,   264812k cached   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            1635 root      20   0 17300 1200  920 R  0.3  0.1   0:00.01 top                    1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 init                   2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd               3 root      20   0     0    0    0 S  0.0  0.0   0:00.11 ksoftirqd/0
      

      Os valores de gentileza podem variar entre “-19/-20” (prioridade mais alta) e ”19/20” (prioridade mais baixa), dependendo do sistema.

      Para executar um programa com um certo valor de gentileza, podemos usar o comando nice:

      <pre>nice -n 15 <span class=“highlight”>commandtoexecute</span></pre>

      Isso funciona apenas ao iniciar um novo programa.

      Para alterar o valor de gentileza de um programa que já está sendo executado, usamos uma ferramenta chamada renice:

      <pre>renice 0 <span class=“highlight”>PIDtoprioritize</span></pre>

      Nota: embora o comando nice opere necessariamente com um nome de comando, o renice opera chamando o PID do processo

      Conclusão


      O gerenciamento de processos é um tópico que pode ser de difícil compreensão para novos usuários, pois as ferramentas usadas são diferentes de seus equivalentes gráficos.

      No entanto, as ideias são habituais e intuitivas e, com um pouco de prática, se tornarão naturais. Como os processos estão envolvidos em tudo o que é feito em um sistema de computador, aprender como controlá-los de maneira eficaz é uma habilidade essencial.

      <div class=“author”>Por Justin Ellingwood</div>



      Source link

      Como usar Systemctl para gerenciar serviços e unidades do systemd


      Introdução

      Systemd é um sistema init e gerenciador de sistema que se tornou o novo padrão para distribuições Linux. Devido à sua forte adoção, familiarizar-se com o systemd vale muito a pena, pois irá tornar a administração de servidores consideravelmente mais fácil. Aprender sobre as ferramentas e daemons que compõem o systemd e como usá-los irá ajudar a entender melhor o poder, flexibilidade e capacidades que ele oferece ou, pelo menos, facilitará o seu trabalho.

      Neste guia, vamos discutir o comando systemctl, que é a ferramenta de gerenciamento central para controlar o sistema init. Vamos abordar como gerenciar serviços, verificar status, alterar estados de sistema e trabalhar com os arquivos de configuração.

      Observe que embora o systemd tenha se tornado o sistema init padrão para muitas distribuições Linux, ele não é implementado universalmente em todas as distros. À medida que você percorrer este tutorial, se o seu terminal exibir o erro bash: systemctl is not installed, então é provável que sua máquina tenha um sistema init diferente instalado.

      Gerenciamento de serviços

      O objetivo fundamental de um sistema init é inicializar os componentes que devem ser iniciados após o kernel do Linux ser inicializado (tradicionalmente conhecido como componentes “userland”). O sistema init também é usado para gerenciar serviços e daemons para o servidor em qualquer momento enquanto o sistema está em execução. Com isso em mente, vamos começar com algumas operações básicas de gerenciamento de serviços.

      No systemd, o alvo da maioria das ações são “unidades”, que são os recursos que o systemd sabe gerenciar. As unidades são categorizadas pelo tipo de recurso que representam e são definidas com arquivos conhecidos como arquivos unit. O tipo de cada unidade pode ser inferido a partir do sufixo no final do arquivo.

      Para tarefas de gerenciamento de serviços, a unidade de destino serão unidades de serviço, que possuem arquivos de unidade com um sufixo .service. No entanto, para a maioria dos comandos de gerenciamento de serviços, é possível deixar o sufixo .service, pois o systemd é inteligente o suficiente para saber que você provavelmente deseja operar em um serviço ao usar comandos de gerenciamento de serviços.

      Iniciando e interrompendo os serviços

      Para iniciar um serviço systemd, executando instruções no arquivo de unidade do serviço, use o comando start. Caso esteja usando um usuário não root, você terá que usar o sudo, pois isso afetará o estado do sistema operacional:

      • sudo systemctl start application.service

      Como mencionamos acima, o systemd sabe procurar por arquivos *.service para comandos de gerenciamento de serviços, de forma que o comando poderia ser também digitado desta forma:

      • sudo systemctl start application

      Embora você possa usar o formato acima para a administração geral, para maior clareza, vamos usar o sufixo .service para o resto dos comandos, para sermos explícitos sobre o alvo em que estamos operando.

      Para parar um serviço que esteja atualmente em execução, use o comando stop:

      • sudo systemctl stop application.service

      Reiniciando e recarregando

      Para reiniciar um serviço em execução, use o comando restart:

      • sudo systemctl restart application.service

      Se o aplicativo em questão for capaz de recarregar seus arquivos de configuração (sem reiniciar), você pode emitir o comando reload para iniciar esse processo:

      • sudo systemctl reload application.service

      Se não tiver certeza se o serviço possui a funcionalidade para recarregar sua configuração, emita o comando reload-or-restart. Isso irá recarregar a configuração em vigor, se disponível. Caso contrário, o serviço será reiniciado para que a nova configuração seja ativada:

      • sudo systemctl reload-or-restart application.service

      Habilitando e desabilitando serviços

      Os comandos acima são úteis para iniciar ou interromper serviços durante a sessão atual. Para dizer ao systemd para iniciar serviços automaticamente na inicialização do sistema, é necessário habilitá-los.

      Para iniciar um serviço na inicialização, use o comando enable:

      • sudo systemctl enable application.service

      Isso irá criar um link simbólico a partir da cópia do arquivo de serviço do sistema (geralmente em /lib/systemd/system ou /etc/systemd/system) para a localização em disco onde o systemd procura por arquivos de inicialização automática (geralmente etc/systemd/system/some_target.target.wants. Vamos abordar o que é um alvo mais adiante neste guia).

      Para impedir que o serviço seja iniciado automaticamente, digite:

      • sudo systemctl disable application.service

      Isso irá remover o link simbólico que indica que o serviço deve ser iniciado automaticamente.

      Esteja ciente de que habilitar um serviço não o inicia na sessão atual. Se quiser iniciar o serviço e também habilitá-lo na inicialização, será necessário emitir ambos os comandos start e enable.

      Verificando o status de serviços

      Para verificar o status de um serviço em seu sistema, use o comando status:

      • systemctl status application.service

      Isso irá mostrar-lhe o estado do serviço, a hierarquia de cgroup e as primeiras linhas de registro.

      Por exemplo, ao verificar o status de um servidor Nginx, pode ser que você veja um resultado como este:

      Output

      ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago Main PID: 495 (nginx) CGroup: /system.slice/nginx.service ├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; error_log stderr; └─496 nginx: worker process Jan 27 19:41:23 desktop systemd[1]: Starting A high performance web server and a reverse proxy server... Jan 27 19:41:23 desktop systemd[1]: Started A high performance web server and a reverse proxy server.

      Isso oferece uma visão geral interessante do status atual do aplicativo, notificando você acerca de qualquer problema ou ação que possa ser necessária.

      Há também métodos para verificar por estados específicos. Por exemplo, para verifciar se uma unidade está ativa (em execução), use o comando is-active:

      • systemctl is-active application.service

      Isso irá retornar o estado da unidade atual, que geralmente é active ou inactive. O código de saída será “0” se for ativo, tornando o resultado mais simples de se analisar em scripts do shell.

      Para ver se uma unidade está habilitada, use o comando is-enabled:

      • systemctl is-enabled application.service

      Isso irá mostrar se o serviço está enabled ou disabled e irá definir novamente o código de saída como “0” ou “1”, dependendo da resposta para a pergunta do comando.

      Uma terceira verificação é se a unidade está em um estado de falha. Ele indica se houve um problema ao iniciar a unidade em questão:

      • systemctl is-failed application.service

      Isso irá retornar active se a unidade estiver executando corretamente ou failed caso um erro tenha ocorrido. Se a unidade tiver sido intencionalmente interrompida, ela pode retornar unknown ou inactive. Um status de saída de “0” indica que uma falha ocorreu, enquanto um status de saída de “1” indica qualquer outro status.

      Visão geral do estado do sistema

      Os comandos mostrados até agora têm sido úteis para o gerenciamento de serviços únicos, mas não são muito úteis para explorar o estado atual do sistema. Existem diversos comandos do systemctl que fornecem essa informação.

      Listando as unidades atuais

      Para ver uma lista com todas as unidades ativas das quais o systemd sabe, podemos usar o comando list-units:

      Isso irá mostrar-lhe uma lista de todas as unidades que o systemd possui como ativa atualmente no sistema. O resultado se parecerá com este:

      Output

      UNIT LOAD ACTIVE SUB DESCRIPTION atd.service loaded active running ATD daemon avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack dbus.service loaded active running D-Bus System Message Bus dcron.service loaded active running Periodic Command Scheduler dkms.service loaded active exited Dynamic Kernel Modules System [email protected] loaded active running Getty on tty1 . . .

      O resultado possui as seguintes colunas:

      • UNIT: o nome da unidade de systemd
      • LOAD: se a configuração da unidade foi analisada pelo systemd. A configuração de unidades carregadas é mantida na memória.
      • ACTIVE: um estado resumido que diz se a unidade está ativa. Essa é geralmente uma maneira bastante simples de dizer se a unidade foi iniciada com sucesso ou não.
      • SUB: esse é um estado de nível mais baixo que indica informações mais detalhadas sobre a unidade. Isso muitas vezes varia dependendo do tipo de unidade, estado e do método em si com o qual a unidade é executada.
      • DESCRIPTION: uma breve descrição textual do que a unidade é/faz.

      Como o comando list-units mostra apenas unidades ativas por padrão, todas as entradas acima exibirão loaded na coluna LOAD e active na coluna ACTIVE. Essa exibição é na verdade o comportamento padrão do systemctl quando chamado sem comandos adicionais. Sendo assim, você irá ver a mesma coisa se chamar systemctl sem argumentos:

      Podemos dizer ao systemctl para mostrar outras informações adicionando sinalizadores adicionais. Por exemplo, para ver todas as unidades que o systemd carregou (ou tentou carregar), independentemente se estão ou não ativas, use o sinalizador --all, desta forma:

      • systemctl list-units --all

      Isso irá mostrar qualquer unidade que o systemd carregou ou tentou carregar, independentemente do seu estado atual no sistema. Algumas unidades tornam-se inativas após serem executadas, e algumas unidades que o systemd tentou carregar podem não ter sido encontradas em disco.

      Use outros sinalizadores para filtrar esses resultados. Por exemplo, é possível usar o sinalizador --state= para indicar os estados LOAD, ACTIVE ou SUB que desejamos ver. Será necessário manter o sinalizador --all para que o systemctl permita que unidades não ativas sejam exibidas:

      • systemctl list-units --all --state=inactive

      Outro filtro comum é o filtro --type=. Podemos dizer ao systemctl para exibir apenas unidades do tipo em que estamos interessados. Por exemplo, para ver apenas unidades de serviço ativas, podemos usar:

      • systemctl list-units --type=service

      Listando todos os arquivos de unidade

      O comando list-units exibe apenas unidades que o systemd tentou analisar e carregar na memória. Como o systemd irá ler apenas unidades as quais ele acha necessário, isso não incluirá necessariamente todas as unidades disponíveis no sistema. Para ver todos os arquivos de unidade disponíveis nos caminhos do systemd, incluindo aquelas que o systemd não tentou carregar, use o comando list-unit-files:

      • systemctl list-unit-files

      As unidades são representações de recursos sobre os quais o systemd sabe. Como o systemd não leu necessariamente todas as definições de unidade nesta visão, ele apresenta apenas informações sobre os arquivos em si. O resultado possui duas colunas: o arquivo de unidade e o estado.

      Output

      UNIT FILE STATE proc-sys-fs-binfmt_misc.automount static dev-hugepages.mount static dev-mqueue.mount static proc-fs-nfsd.mount static proc-sys-fs-binfmt_misc.mount static sys-fs-fuse-connections.mount static sys-kernel-config.mount static sys-kernel-debug.mount static tmp.mount static var-lib-nfs-rpc_pipefs.mount static org.cups.cupsd.path enabled . . .

      O estado normalmente será enabled, disabled, static ou masked. Neste contexto, estático significa que o arquivo de unidade não contém uma seção install, que é usada para habilitar uma unidade. Dessa forma, essas unidades não podem ser ativadas. Geralmente, isso significa que a unidade executa uma ação única ou é usada apenas como uma dependência de outra unidade e não deve ser executada sozinha.

      Vamos abordar o que masked significa daqui a pouco.

      Gerenciamento de unidades

      Até aqui, estivemos trabalhando com serviços e exibindo informações sobre a unidade e arquivos de unidade sobre os quais o systemd sabe. No entanto, é possível descobrir mais informações específicas sobre unidades usando alguns comandos adicionais.

      Exibindo um arquivo de unidade

      Para exibir o arquivo de unidade que o systemd carregou em seu sistema, use o comando cat (adicionado na versão 209 do systemd). Por exemplo, para ver o arquivo de unidade do daemon de planejamento atd, poderíamos digitar:

      • systemctl cat atd.service

      Output

      [Unit] Description=ATD daemon [Service] Type=forking ExecStart=/usr/bin/atd [Install] WantedBy=multi-user.target

      O resultado é o arquivo de unidade, da forma como é conhecido pelo processo do systemd atualmente em execução. Isso pode ser importante se você tiver arquivos de unidade modificados recentemente ou se estiver sobrepondo certas opções em um fragmento de arquivo de unidade (vamos falar disso mais tarde).

      Exibindo dependências

      Para ver a árvore de dependências de uma unidade, use o comando list-dependencies:

      • systemctl list-dependencies sshd.service

      Isso irá exibir uma hierarquia mapeando as dependências que devem ser tratadas para iniciar a unidade em questão. Dependências, neste contexto, incluem aquelas unidades que são exigidas ou procuradas pelas unidades acima dela.

      Output

      sshd.service ├─system.slice └─basic.target ├─microcode.service ├─rhel-autorelabel-mark.service ├─rhel-autorelabel.service ├─rhel-configure.service ├─rhel-dmesg.service ├─rhel-loadmodules.service ├─paths.target ├─slices.target . . .

      As dependências recursivas são exibidas apenas para unidades .target, que indicam estados do sistema. Para listar recursivamente todas as dependências, inclua o sinalizador --all.

      Para mostrar dependências reversas (unidades que dependem da unidade especificada), adicione o sinalizador --reverse ao comando. Outros sinalizadoras que são úteis são os sinalizadoras --before e --after, que podem ser usados para mostrar unidades que dependem da unidade especificada iniciando antes e depois de si mesmos, respectivamente.

      Verificando propriedades da unidade

      Para ver as propriedades de baixo nível de uma unidade, use o comando show. Ele irá exibir uma lista de propriedades que são definidas para a unidade especificada usando um formato key=value:

      • systemctl show sshd.service

      Output

      Id=sshd.service Names=sshd.service Requires=basic.target Wants=system.slice WantedBy=multi-user.target Conflicts=shutdown.target Before=shutdown.target multi-user.target After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice Description=OpenSSH server daemon . . .

      Se quiser exibir uma única propriedade, passe o sinalizador -p com o nome da propriedade. Por exemplo, para ver os conflitos que a unidade sshd.service possui, digite:

      • systemctl show sshd.service -p Conflicts

      Output

      Conflicts=shutdown.target

      Mascarando e desmascarando unidades

      Vimos na seção de gerenciamento de serviços como parar ou desativar um serviço. No entanto, o systemd também possui a capacidade de marcar uma unidade como absolutamente não iniciável, de modo automático ou manual, ligando-a ao /dev/null. Isso é chamado de mascarar a unidade, e é possível com o comando mask:

      • sudo systemctl mask nginx.service

      Isso irá impedir que o serviço Nginx seja iniciado, automaticamente ou manualmente, enquanto estiver mascarado.

      Se verificar o list-unit-files, verá que o serviço está agora listado como mascarado:

      • systemctl list-unit-files

      Output

      . . . kmod-static-nodes.service static ldconfig.service static mandb.service static messagebus.service static nginx.service masked quotaon.service static rc-local.service static rdisc.service disabled rescue.service static . . .

      Se você tentar iniciar o serviço, verá uma mensagem como esta:

      • sudo systemctl start nginx.service

      Output

      Failed to start nginx.service: Unit nginx.service is masked.

      Para desmascarar uma unidade, tornando-a disponível para uso novamente, use o comando unmask:

      • sudo systemctl unmask nginx.service

      Isso irá retornar a unidade ao seu estado anterior, permitindo que seja iniciada ou habilitada.

      Editando arquivos de unidade

      Embora o formato específico para arquivos de unidade esteja fora do âmbito deste tutorial, o systemctl fornece mecanismos integrados para editar e modificar arquivos de unidade, se for necessário fazer ajustes. Essa funcionalidade foi adicionada na versão 218do systemd.

      O comando edit, por padrão, irá abrir um trecho de código do arquivo de unidade para a unidade em questão:

      • sudo systemctl edit nginx.service

      Esse será um arquivo em branco que pode ser usado para substituir ou adicionar diretivas à definição da unidade. Um diretório será criado dentro do diretório /etc/systemd/system, que contém o nome da unidade com o .d anexado. Por exemplo, para o nginx.service, um diretório chamado nginx.service.d será criado.

      Dentro deste diretório, um trecho de código chamado override.conf será criado. Quando a unidade for carregada, o systemd irá mesclar, na memória, o trecho sobrescrito com o arquivo de unidade completo. As diretivas do trecho terão precedência sobre aquelas encontradas no arquivo de unidade original.

      Se quiser editar o arquivo de unidade completo ao invés de criar um fragmento, passe o sinalizador --full:

      • sudo systemctl edit --full nginx.service

      Isso irá carregar o arquivo de unidade atual no editor, onde pode ser modificado. Quando o editor for fechado, o arquivo alterado será escrito em /etc/systemd/system e terá precedência sobre a definição de unidade do sistema (geralmente encontrada em algum lugar em /lib/systemd/system).

      Para remover qualquer adição que tenha sido feita, exclua o diretório de configuração .d da unidade ou o arquivo de serviço modificado de /etc/systemd/system. Por exemplo, para remover um fragmento, podemos digitar:

      • sudo rm -r /etc/systemd/system/nginx.service.d

      Para remover um arquivo de unidade modificado completo, digitamos:

      • sudo rm /etc/systemd/system/nginx.service

      Depois de excluir o arquivo ou diretório, recarregue o processo do systemd para que ele não tente mais fazer referência a esses arquivos e volte a usar as cópias do sistema. Faça isso digitando:

      • sudo systemctl daemon-reload

      Os alvos são arquivos de unidade especiais que descrevem um estado do sistema ou um ponto de sincronização. Assim como outras unidades, os arquivos que definem alvos podem ser identificados por seu sufixo, que neste caso é .target. Os alvos não fazem muito por conta própria, mas são usados para agrupar outras unidades.

      Isso pode ser usado para trazer o sistema para determinados estados, da mesma forma que outros sistemas init usam os níveis de execução. Eles são usados como referência para quando certas funções estão disponíveis, permitindo especificar o estado desejado em vez das unidades individuais necessárias para produzir esse estado.

      Por exemplo, existe um swap.target que é usado para indicar que o swap está pronto para ser usado. Unidades que fazem parte deste processo podem sincronizar-se com esse alvo indicando em sua configuração que elas são WantedBy= ou RequiredBy= pelo swap.target. Unidades que exigem o swap para ficarem disponíveis podem especificar essa condição usando as especificações Wants=, Requires= e After= para indicar a natureza do seu relacionamento.

      Obtendo e definindo o alvo padrão

      O processo do systemd possui um alvo padrão usado por ele ao inicializar o sistema. Satisfazer a cascata de dependências a partir desse único alvo irá trazer o sistema para o estado desejado. Para encontrar o alvo padrão para o seu sistema, digite:

      Output

      multi-user.target

      Se quiser definir um alvo padrão diferente, use o set-default. Por exemplo, se você possui um desktop gráfico instalado e quer que o sistema seja inicializado nele por padrão, altere seu alvo padrão de acordo:

      • sudo systemctl set-default graphical.target

      Listando alvos disponíveis

      É possível obter uma lista dos alvos disponíveis em seu sistema digitando:

      • systemctl list-unit-files --type=target

      Ao contrário dos níveis de execução, vários alvos podem estar ativos ao mesmo tempo. Um alvo ativo indica que o systemd tentou iniciar todas as unidades ligadas ao alvo e não tentou destruí-las novamente. Para ver todos os alvos ativos, digite:

      • systemctl list-units --type=target

      Isolando alvos

      É possível iniciar todas as unidades associadas a um alvo e parar todas as unidades que não fazem parte da árvore de dependência. O comando que precisamos emitir para isso chama-se, apropriadamente, isolate. Isso é parecido com alterar o nível de execução em outros sistemas init.

      Por exemplo, se estiver operando em um ambiente gráfico com o graphical.target ativo, você pode desligar o sistema gráfico e colocar o sistema em um estado de linha de comando multiusuário isolando o multi-user.target. Como o graphical.target depende do multi-user.target, mas o contrário não é válido, todas as unidades gráficas serão interrompidas.

      Pode ser interessante dar uma olhada nas dependências do alvo que você está isolando antes de executar este procedimento, de forma a garantir que não estará impedindo serviços vitais:

      • systemctl list-dependencies multi-user.target

      Quando estiver satisfeito com as unidades que serão mantidas vivas, isole o alvo digitando:

      • sudo systemctl isolate multi-user.target

      Usando atalhos para eventos importantes

      Existem alvos definidos para eventos importantes, como desligar ou reinicializar o sistema. No entanto, o systemctl também possui alguns atalhos que adicionam outras funcionalidades adicionais.

      Por exemplo, para colocar o sistema em modo de resgate (único usuário), simplesmente use o comando rescue ao invés de isolate rescue.target:

      Isso irá fornecer a funcionalidade adicional de alertar todos os usuários conectados sobre o evento.

      Para parar o sistema, use o comando halt:

      Para iniciar um desligamento completo, use o comando poweroff:

      Uma reinicialização pode ser feita com o comando reboot:

      Todos esses comandos alertam usuários conectados que o evento está ocorrendo, o que não acontece ao apenas executar ou isolar o alvo. Observe que a maioria das máquinas irão vincular os comandos mais curtos e convencionais para essas operações de modo que funcionem corretamente com o systemd.

      Por exemplo, para reiniciar o sistema, costuma-se digitar:

      Conclusão

      A partir agora, você deve estar familiarizado com algumas das capacidades básicas do comando systemctl que permitem interagir e controlar sua instância do systemd. O utilitário systemctl será o seu ponto principal de interação para o gerenciamento do serviço e do estado do sistema.

      Embora o systemctl opere principalmente com o processo principal do systemd, existem outros componentes do ecossistema do systemd que são controlados por outros utilitários. Outras capacidades, como o gerenciamento de registro e sessões de usuário são controladas por daemons e utilitários de gerenciamento separados (journald/journalctl e logind/loginctl respectivamente). Gastar algum tempo para se familiarizar com essas outras ferramentas e daemons irá tornar o gerenciamento uma tarefa mais fácil.



      Source link

      Como gerenciar e utilizar acionadores de banco de dados do MySQL no Ubuntu 18.04


      O autor selecionou a Apache Software Foundation para receber uma doação como parte do programa Write for DOnations.

      Introdução

      No MySQL, um acionador é um comando SQL definido por usuário que é chamado automaticamente durante uma operação INSERT, DELETE, ou UPDATE. O código de acionador está associado a uma tabela e é destruído assim que uma tabela for descartada. Você pode especificar um momento de ação do acionador e definir se ele será ativado antes ou após o evento de banco de dados definido.

      Os acionadores possuem várias vantagens. Por exemplo, você pode usá-los para gerar o valor de uma coluna derivada durante uma instrução de INSERT. Outro caso de uso é a aplicação da integridade referencial, onde é possível utilizar um acionador para salvar um registro em várias tabelas relacionadas. Outros benefícios dos acionadores incluem o registro de ações do usuário para auditar tabelas, bem como cópias de dados em tempo real em diferentes esquemas de bancos de dados para fins de redundância, com o objetivo de evitar um único ponto de falha.

      Você também pode utilizar acionadores para manter as regras de validação no nível do banco de dados. Isso ajuda no compartilhamento da fonte de dados em vários aplicativos, sem quebrar a lógica de negócios. Isso também reduz bastante os testes de viagem de ida e volta para o servidor de banco de dados, o que, portanto, melhora o tempo de resposta dos seus aplicativos. Como o servidor de banco de dados executa os acionadores, eles podem aproveitar-se de recursos de servidor melhorados, como RAM e CPU.

      Neste tutorial, você criará, utilizará e excluirá vários tipos de acionadores no seu banco de dados do MySQL.

      Pré-requisitos

      Antes de começar, certifique-se de ter o seguinte:

      Passo 1 — Criando um banco de dados de amostra

      Neste passo, você criará um banco de dados de clientes de amostra com várias tabelas para demonstrar como os acionadores do MySQL funcionam.

      Para entender melhor sobre as consultas do MySQL, leia nossa Introdução às consultas no MySQL.

      Primeiro, faça login no seu servidor do MySQL como raiz:

      Digite sua senha raiz do MySQL quando solicitado e clique em ENTER para continuar. Quando você vir o prompt do mysql>, execute o seguinte comando para criar um banco de dados test_db:

      Output

      Query OK, 1 row affected (0.00 sec)

      Em seguida, mude para o test_db com:

      Output

      Database changed

      Você começará criando uma tabela de customers. Essa tabela terá os registros dos clientes, incluindo a customer_id, o customer_name e o level. Haverá dois níveis de clientes: BASIC e VIP.

      • Create table customers(customer_id BIGINT PRIMARY KEY, customer_name VARCHAR(50), level VARCHAR(50) ) ENGINE=INNODB;

      Output

      Query OK, 0 rows affected (0.01 sec)

      Agora, adicione alguns registros à tabela customers. Para fazer isso, execute os comandos um a um:

      • Insert into customers (customer_id, customer_name, level )values('1','JOHN DOE','BASIC');
      • Insert into customers (customer_id, customer_name, level )values('2','MARY ROE','BASIC');
      • Insert into customers (customer_id, customer_name, level )values('3','JOHN DOE','VIP');

      Você verá o seguinte resultado após executar cada um dos comandos INSERT:

      Output

      Query OK, 1 row affected (0.01 sec)

      Para garantir que os registros de amostra foram inseridos com sucesso, execute o comando SELECT:

      Output

      +-------------+---------------+-------+ | customer_id | customer_name | level | +-------------+---------------+-------+ | 1 | JOHN DOE | BASIC | | 2 | MARY ROE | BASIC | | 3 | JOHN DOE | VIP | +-------------+---------------+-------+ 3 rows in set (0.00 sec)

      Você criará também outra tabela para reter informações relacionadas sobre a conta customers. A tabela terá os campos customer_id e status_notes.

      Execute o seguinte comando:

      • Create table customer_status(customer_id BIGINT PRIMARY KEY, status_notes VARCHAR(50)) ENGINE=INNODB;

      Em seguida, você criará uma tabela de sales (vendas). Esta tabela terá os dados de vendas relacionados a diferentes clientes através da coluna customer_id:

      • Create table sales(sales_id BIGINT PRIMARY KEY, customer_id BIGINT, sales_amount DOUBLE ) ENGINE=INNODB;

      Output

      Query OK, 0 rows affected (0.01 sec)

      Você adicionará os dados da amostra aos dados de sales nos passos próximos, enquanto testa os acionadores. Em seguida, crie uma tabela audit_log para registrar as atualizações feitas para a tabela de sales quando você implementar o acionador AFTER UPDATE no Passo 5:

      • Create table audit_log(log_id BIGINT PRIMARY KEY AUTO_INCREMENT, sales_id BIGINT, previous_amount DOUBLE, new_amount DOUBLE, updated_by VARCHAR(50), updated_on DATETIME ) ENGINE=INNODB;

      Output

      Query OK, 0 rows affected (0.02 sec)

      Com o banco de dados test_db e as quatro tabelas em funcionamento, siga em frente para trabalhar com os vários acionadores do MySQL no seu banco de dados.

      Passo 2 — Criando um acionador antes de inserir

      Neste passo, você examinará a sintaxe de um acionador do MySQL, antes da aplicação dessa lógica para criar um acionador BEFORE INSERT, que valida o campo sales_amount quando os dados são inseridos na tabela de sales.

      A sintaxe geral para a criação de um acionador do MySQL é mostrada no exemplo a seguir:

      DELIMITER //
      CREATE TRIGGER [TRIGGER_NAME]
      [TRIGGER TIME] [TRIGGER EVENT]
      ON [TABLE]
      FOR EACH ROW
      [TRIGGER BODY]//
      DELIMITER ;
      

      A estrutura do acionador inclui:

      DELIMITER //: o delimitador padrão do MySQL é o ; — ele é necessário para modificá-lo para outra coisa, de modo a permitir que o MySQL trate as linhas seguintes como um comando até que ele atinja seu delimitador personalizado. Neste exemplo, o delimitador é alterado para // e, em seguida, o delimitador ; é redefinido no final.

      [TRIGGER_NAME]: um acionador deve ter um nome e é aqui que você inclui o valor.

      [TRIGGER TIME]: um acionador pode ser chamado durante diferentes intervalos de tempo. O MySQL permite que você defina se o acionador iniciará antes ou após uma operação de banco de dados.

      [TRIGGER EVENT]: os acionadores são chamados apenas por operações de INSERT, UPDATE e DELETE. Você pode utilizar qualquer valor aqui, dependendo do que quiser fazer.

      [TABLE]: qualquer acionador que você criar no seu banco de dados do MySQL deve estar associado a uma tabela.

      FOR EACH ROW: essa instrução diz ao MySQL para executar o código do acionador para cada linha que o acionador afeta.

      [TRIGGER BODY]​​​: o código que é executado quando o acionador é chamado tem o nome de trigger body. Pode ser uma única instrução do SQL ou vários comandos. Note que, se estiver executando várias instruções do SQL no corpo do acionador, você deve envolvê-las entre um bloco BEGIN... END.

      Nota: ao criar o corpo do acionador, você pode utilizar as palavras-chave OLD e NEW para acessar os valores de coluna antigos e novos inseridos durante uma operação INSERT, UPDATE e DELETE. Em um acionador de DELETE, apenas a palavra-chave OLD pode ser usada (que você usará no Passo 4).

      Agora, você criará seu primeiro acionador BEFORE INSERT. Este acionador estará associado à tabela de sales e será chamado antes de um registro ser inserido para validar o sales_amount. A função do acionador é a de verificar se o sales_amount que está sendo inserido no quadro de vendas é maior do que 10000 e de gerar um erro, caso isso seja verdadeiro.

      Certifique-se de estar logado no servidor do MySQL. Em seguida, digite os comandos do MySQL seguintes um de cada vez:

      • DELIMITER //
      • CREATE TRIGGER validate_sales_amount
      • BEFORE INSERT
      • ON sales
      • FOR EACH ROW
      • IF NEW.sales_amount>10000 THEN
      • SIGNAL SQLSTATE '45000'
      • SET MESSAGE_TEXT = 'Sale has exceeded the allowed amount of 10000.';
      • END IF//
      • DELIMITER ;

      Você está usando a instrução IF... THEN... END IF para avaliar se a quantidade que está sendo fornecida durante a instrução INSERT está dentro da sua faixa. O acionador consegue extrair o novo valor de sales_amount que está sendo fornecido, usando a palavra-chave NEW.

      Para gerar uma mensagem de erro genérica, use as linhas seguintes para informar o usuário sobre o erro:

      SIGNAL SQLSTATE '45000'
      SET MESSAGE_TEXT = 'Sale has exceeded the allowed amount of 10000.';
      

      Em seguida, insira um registro com um sales_amount de 11000 para a tabela de sales para verificar se o acionador interromperá a operação:

      • Insert into sales(sales_id, customer_id, sales_amount) values('1','1','11000');

      Output

      ERROR 1644 (45000): Sale has exceeded the allowed amount of 10000.

      Este erro mostra que o código do acionador está funcionando como esperado.

      Agora, teste um novo registro com um valor de 7500 para verificar se o comando será bem-sucedido:

      • Insert into sales(sales_id, customer_id, sales_amount) values('1','1','7500');

      Como o valor está dentro da faixa recomendada, você verá o seguinte resultado:

      Output

      Query OK, 1 row affected (0.01 sec)

      Para confirmar que os dados foram inseridos, execute o seguinte comando:

      O resultado confirma que os dados estão na tabela:

      Output

      +----------+-------------+--------------+ | sales_id | customer_id | sales_amount | +----------+-------------+--------------+ | 1 | 1 | 7500 | +----------+-------------+--------------+ 1 row in set (0.00 sec)

      Neste passo, você testou os acionadores para validar dados antes da inserção deles em um banco de dados.

      Em seguida, você trabalhará com o acionador AFTER INSERT para salvar informações relacionadas em tabelas diferentes.

      Passo 3 — Criando um acionador após inserir

      Os acionadores AFTER INSERT são executados quando os registros são inseridos com sucesso em uma tabela. Essa funcionalidade pode ser usada para executar outras lógicas relacionados a negócios de maneira automática. Por exemplo, em um aplicativo bancário, um acionador AFTER INSERT pode fechar uma conta de empréstimo quando um cliente terminar de pagar o empréstimo. O acionador pode monitorar todos os pagamentos inseridos em uma tabela de transação e fechar o empréstimo automaticamente assim que o saldo do empréstimo se tornar zero.

      Neste passo, você trabalhará com sua tabela de customer_status usando um acionador AFTER INSERT para digitar registros de clientes relacionados.

      Para criar o acionador AFTER INSERT, digite os comandos a seguir:

      • DELIMITER //
      • CREATE TRIGGER customer_status_records
      • AFTER INSERT
      • ON customers
      • FOR EACH ROW
      • Insert into customer_status(customer_id, status_notes) VALUES(NEW.customer_id, 'ACCOUNT OPENED SUCCESSFULLY')//
      • DELIMITER ;

      Output

      Query OK, 0 rows affected (0.00 sec)

      Aqui, você instruirá o MySQL para salvar outro registro para a tabela customer_status assim que um novo registro de cliente for inserido na tabela customers.

      Agora, insira um novo registro na tabela customers para confirmar que seu código do acionador será chamado:

      • Insert into customers (customer_id, customer_name, level )values('4','DAVID DOE','VIP');

      Output

      Query OK, 1 row affected (0.01 sec)

      Como o registro foi inserido com sucesso, verifique se um novo registro de status foi inserido na tabela customer_status:

      • Select * from customer_status;

      Output

      +-------------+-----------------------------+ | customer_id | status_notes | +-------------+-----------------------------+ | 4 | ACCOUNT OPENED SUCCESSFULLY | +-------------+-----------------------------+ 1 row in set (0.00 sec)

      O resultado confirma que o acionador foi executado com sucesso.

      O acionador AFTER INSERT é útil no monitoramento do ciclo de vida de um cliente. Em um ambiente de produção, as contas dos clientes podem ser submetidas a diferentes etapas, como a abertura da conta, a suspensão da conta e o fechamento da conta.

      Nos passos a seguir, você trabalhará com os acionadores de UPDATE.

      Passo 4 — Criando um acionador antes de atualizar

      Um acionador BEFORE UPDATE é semelhante ao acionador BEFORE INSERT—a diferença é o momento onde eles são chamados. Você pode utilizar o acionador BEFORE UPDATE para verificar uma lógica de negócios antes de um registro ser atualizado. Para testar isso, você utilizará a tabela customers, na qual você já inseriu alguns dados.

      Você tem dois níveis para seus clientes no banco de dados. Neste exemplo, assim que uma conta de cliente for atualizada para o nível VIP, a conta não poderá ser rebaixada para o nível BASIC. Para aplicar essa regra, você criará um acionador BEFORE UPDATE que executará antes da instrução UPDATE, como mostrado a seguir. Se um usuário de banco de dados tentar rebaixar um cliente do nível VIP para o nível BASIC, será acionada uma exceção definida pelo usuário.

      Digite os comandos SQL seguintes um de cada vez para criar o acionador BEFORE UPDATE:

      • DELIMITER //
      • CREATE TRIGGER validate_customer_level
      • BEFORE UPDATE
      • ON customers
      • FOR EACH ROW
      • IF OLD.level='VIP' THEN
      • SIGNAL SQLSTATE '45000'
      • SET MESSAGE_TEXT = 'A VIP customer can not be downgraded.';
      • END IF //
      • DELIMITER ;

      Use a palavra-chave OLD para capturar o nível que o usuário está fornecendo ao executar o comando UPDATE. Novamente, use a instrução IF... THEN… END IF para sinalizar uma instrução de erro genérica para o usuário.

      Em seguida, execute o comando SQL a seguir, que tenta rebaixar uma conta de cliente associada ao customer_id de 3:

      • Update customers set level='BASIC' where customer_id='3';

      Você verá o seguinte resultado, fornecendo o SET MESSAGE_TEXT:

      Output

      ERROR 1644 (45000): A VIP customer can not be downgraded.

      Se executar o mesmo comando para um cliente de nível BASIC e tentar atualizar a conta para o nível VIP, o comando será executado com sucesso:

      • Update customers set level='VIP' where customer_id='1';

      Output

      Rows matched: 1 Changed: 1 Warnings: 0

      Você usou o acionador BEFORE UPDATE para aplicar uma regra de negócios. Agora, siga em frente para usar um acionador AFTER UPDATE para log de auditoria.

      Passo 5 — Criando um acionador após atualizar

      Um acionador AFTER UPDATE é chamado assim que um registro de banco de dados for atualizado com sucesso. Este comportamento torna o acionador adequado para o log de auditoria. Em um ambiente de muitos usuários, o administrador pode querer exibir um histórico de usuários atualizando os registros em uma tabela específica para fins de auditoria.

      Você criará um acionador que registra a atividade de atualização da tabela sales. Nossa tabela audit_log terá as informações sobre os usuários do MySQL atualizando a tabela de sales, a date da atualização e os valores old e new da sales_amount.

      Para criar o acionador, execute os comandos SQL seguintes:

      • DELIMITER //
      • CREATE TRIGGER log_sales_updates
      • AFTER UPDATE
      • ON sales
      • FOR EACH ROW
      • Insert into audit_log(sales_id, previous_amount, new_amount, updated_by, updated_on) VALUES (NEW.sales_id,OLD.sales_amount, NEW.sales_amount,(SELECT USER()), NOW() )//
      • DELIMITER ;

      Insira um novo registro para a tabela audit_log. Use a palavra-chave NEW para recuperar o valor do sales_id e o novo sales_amount. Além disso, use a palavra-chave OLD para recuperar o sales_amount anterior, já que deseja registrar ambos os montantes para fins de auditoria.

      O comando SELECT USER() recupera o usuário atual que executa a operação e a instrução NOW() recupera o valor da data e hora atual do servidor MySQL.

      Agora, caso um usuário tente atualizar o valor de qualquer registro na tabela sales, o acionador log_sales_updates inserirá um novo registro para a tabela audit_log.

      Vamos criar um novo registro de vendas com uma sales_id aleatória de 5 e tentar atualizá-lo. Primeiro, insira o registro de vendas com:

      • Insert into sales(sales_id, customer_id, sales_amount) values('5', '2','8000');

      Output

      Query OK, 1 row affected (0.00 sec)

      Em seguida, atualize o registro:

      • Update sales set sales_amount='9000' where sales_id='5';

      Você verá o seguinte resultado:

      Output

      Rows matched: 1 Changed: 1 Warnings: 0

      Agora, execute o comando a seguir para verificar se o acionador AFTER UPDATE conseguiu registrar um novo registro na tabela audit_log:

      O acionador registrou a atualização Seu resultado mostra o sales_amount e o new amount previamente registrados com o usuário que atualizou os registros:

      Output

      +--------+----------+-----------------+------------+----------------+---------------------+ | log_id | sales_id | previous_amount | new_amount | updated_by | updated_on | +--------+----------+-----------------+------------+----------------+---------------------+ | 1 | 5 | 8000 | 9000 | root@localhost | 2019-11-07 09:28:36 | +--------+----------+-----------------+------------+----------------+---------------------+ 1 row in set (0.00 sec)

      Você também tem a data e hora que a atualização foi realizada, que são valiosos para fins de auditoria.

      Em seguida, você usará o acionador DELETE para aplicar a integridade da referenciação no nível de banco de dados.

      Passo 6 — Criando um acionador antes de excluir

      Acionadores do BEFORE DELETE são chamados antes que uma instrução DELETE seja executada em uma tabela. Normalmente, esses tipos de acionadores são usados para aplicar a integridade referencial em diferentes tabelas relacionadas. Por exemplo, cada registro da tabela de sales se relaciona a um customer_id da tabela customers. Se um usuário excluísse um registro da tabela customers que tem um registro relacionado na tabela sales, você não teria como saber qual era o cliente associado àquele registro.

      Para evitar isso, é possível criar um acionador BEFORE DELETE para aplicar sua lógica. Execute os comandos SQL a seguir, um de cada vez:

      • DELIMITER //
      • CREATE TRIGGER validate_related_records
      • BEFORE DELETE
      • ON customers
      • FOR EACH ROW
      • IF OLD.customer_id in (select customer_id from sales) THEN
      • SIGNAL SQLSTATE '45000'
      • SET MESSAGE_TEXT = 'The customer has a related sales record.';
      • END IF//
      • DELIMITER ;

      Agora, tente excluir um cliente que tenha um registro de vendas relacionado a ele:

      • Delete from customers where customer_id='2';

      Como resultado, você verá a seguinte saída:

      Output

      ERROR 1644 (45000): The customer has a related sales record.

      O acionador BEFORE DELETE pode evitar a exclusão acidental de informações relacionadas em um banco de dados.

      No entanto, em algumas situações, você pode querer excluir todos os registros associados a um registro em específico de diferentes tabelas relacionadas. Nesta situação, você usaria o acionador AFTER DELETE, que será testado no próximo passo.

      Passo 7 — Criando um acionador após excluir

      Os acionadores AFTER DELETE são ativados assim que um registro tenha sido excluído com sucesso. Um exemplo de como se pode utilizar um acionador AFTER DELETE é uma situação em que o nível de desconto que um determinado cliente recebe é determinado pelo número de vendas realizadas durante um período definido. Se alguns dos registros do cliente forem excluídos da tabela de sales, o nível de desconto de cliente terá que ser rebaixado.

      Outro uso do acionador AFTER DELETE é o de excluir as informações relacionadas de outra tabela assim que um registro de uma tabela base for excluído. Por exemplo, você definirá um acionador que exclui o registro de clientes se os registros de vendas com o customer_id relacionado forem excluídos da tabela de sales. Execute o comando a seguir para criar seu acionador:

      • DELIMITER //
      • CREATE TRIGGER delete_related_info
      • AFTER DELETE
      • ON sales
      • FOR EACH ROW
      • Delete from customers where customer_id=OLD.customer_id;//
      • DELIMITER ;

      Em seguida, execute o seguinte comando para excluir todos os registros de vendas associados a um customer_id de 2:

      • Delete from sales where customer_id='2';

      Output

      Query OK, 1 row affected (0.00 sec)

      Agora, verifique se há registros para o cliente na tabela de sales:

      • Select * from customers where customer_id='2';

      Você receberá um resultado em um Empty Set, já que o registro de cliente associado ao customer_id de 2 foi excluído pelo acionador:

      Output

      Empty set (0.00 sec)

      Agora, você usou cada uma das diferentes formas de acionadores para realizar funções específicas. Em seguida, você verá como remover um acionador do banco de dados caso não precise mais dele.

      Passo 8 — Excluindo acionadores

      De maneira similar a qualquer outro objeto, você pode excluir acionadores utilizando o comando DROP. A seguir temos a sintaxe para excluir um acionador:

      Drop trigger [TRIGGER NAME];
      

      Por exemplo, para excluir o último acionador AFTER DELETE que você criou, execute o comando a seguir:

      • Drop trigger delete_related_info;

      Output

      Query OK, 0 rows affected (0.00 sec)

      A necessidade de excluir acionadores surge quando você quiser recriar a estrutura deles. Em tal caso, você pode remover o acionador e redefinir um novo com os diferentes comandos de acionador.

      Conclusão

      Neste tutorial, você criou, utilizou e excluiu diferentes tipos de acionadores de um banco de dados do MySQL. Utilizando um exemplo de banco de dados relacionados a clientes, você implementou acionadores para diferentes casos de uso, como validação de dados, aplicação de lógica de negócios, log de auditoria e aplicação da integridade referencial.

      Para obter mais informações sobre como utilizar seu banco de dados do MySQL, confira o seguinte:



      Source link