One place for hosting & domains

      automatizar

      Como usar o Cron para automatizar tarefas no CentOS 8


      Shaun Lewis escreveu uma versão anterior deste tutorial.

      Introdução

      O Cron é um programa daemon de agendamento de trabalhos baseado em tempo, encontrado em sistemas operacionais do tipo Unix, incluindo as distribuições do Linux. O Cron executa em segundo plano e tarefas agendadas com o cron, conhecidas como “cron jobs” (trabalhos do cron), são executadas automaticamente, o que torna o cron útil para automatizar tarefas relacionadas à manutenção.

      Este guia fornece uma visão geral sobre como programar tarefas usando a sintaxe especial do cron. Ele também revisa alguns atalhos que você pode usar para tornar as agendas de trabalho mais fáceis de escrever e de entender.

      Pré-requisitos

      Para completar este guia, você precisará de acesso a um computador que executa em CentOS 8. Pode ser sua máquina local, uma máquina virtual ou um servidor virtual privado.

      Independentemente do tipo de computador que você usar para acompanhar este guia, ele deverá possuir um usuário não raiz com privilégios administrativos configurados. Para configurar isso, siga as instruções de nosso Guia de configuração inicial de servidor para o CentOS 8.

      Instalando o Cron

      Por padrão, quase toda distribuição do Linux tem alguma forma do cron instalada. No entanto, se estiver usando uma máquina com CentOS na qual o cron não estiver instalado, instale-o usando o comando dnf.

      Antes de instalar o cron em uma máquina CentOS, atualize o índice de pacotes local do computador:

      Então, instale o daemon cron com o seguinte comando:

      • sudo dnf install crontabs

      Esse comando solicitará que você confirme se deseja instalar o pacote crontabs e suas dependências. Faça isso pressionando y e, depois, ENTER.

      Isso instalará o cron em seu sistema, mas será necessário iniciar o daemon manualmente. Você também precisará garantir que ele esteja configurado para executar sempre que o servidor for iniciado. Você pode realizar ambas essas ações com o comando systemctl.

      Para iniciar o daemon cron, execute o seguinte comando:

      • sudo systemctl start crond.service

      Para definir o cron para executar sempre que o servidor for iniciado, digite:

      • sudo systemctl enable crond.service

      Depois disso, o cron estará instalado no seu sistema, pronto para que você comece a agendar trabalhos.

      Entendendo como o Cron funciona

      Os trabalhos do cron são registrados e gerenciados em um arquivo especial conhecido como crontab. Cada perfil de usuário no sistema pode ter seu próprio arquivo crontab – onde o usuário poderá agendar trabalhos – que fica armazenado em /var/spool/cron/.

      Para agendar um trabalho, simplesmente abra seu crontab para edição e adicione uma tarefa escrita na forma de uma expressão cron. A sintaxe para expressões cron pode ser dividida em dois elementos: o agendamento e o comando a executar.

      O comando pode ser praticamente qualquer comando que você executaria normalmente na linha de comando. O componente de agendamento da sintaxe é dividido em 5 campos diferentes, os quais vêm escritos na seguinte ordem:

      Campo Valores permitidos
      minuto 0-59
      hora 0-23
      Dia do mês 1-31
      mês 1-12 ou JAN-DEC
      Dia da semana 0-6 ou SUN-SAT

      Juntas, as tarefas agendadas em um arquivo crontab são estruturadas da seguinte forma:

      minute hour day_of_month month day_of_week command_to_run
      

      Apresentamos aqui um exemplo funcional de uma expressão cron. Essa expressão executa o comando curl http://www.google.com, toda terça-feira, às 5:30 PM:

      30 17 * * 2 curl http://www.google.com
      

      Também existem alguns caracteres especiais que você pode incluir no componente de agendamento de uma expressão cron para facilitar o agendamento:

      • *: em expressões cron, um asterisco é uma variável curinga que representa “todos”. Assim, uma tarefa agendada com * * * * * ... será executada a cada minuto, de cada hora, de cada dia, de cada mês.
      • ,: vírgulas separar os valores do agendamento para formar uma lista. Se quiser executar uma tarefa no início e na metade de cada hora, em vez de escrever duas tarefas separadas (por exemplo, 0 * * * * ... e 30 * * * * ...), poderia conseguir a mesma funcionalidade com um (0,30 * * * * ...).
      • -: um hífen representa um intervalo de valores no campo da agenda. Em vez de ter 30 tarefas agendadas separadamente em relação a um comando que você quer executar nos primeiros 30 minutos de cada hora (como em 0 * * * * ..., 1 * * * * ..., 2 * * * * ... e assim por diante), bastaria que você as agendasse como 0-29 * * * * ....
      • /: utilize uma barra com um asterisco para expressar um valor de etapa. Por exemplo, em vez de escrever oito tarefas cron separadas para executar um comando a cada três horas (como em: 0 0 * * * ..., 0 3 * * * ..., 0 6 * * * ... e assim por diante), você poderia agendá-las para executar da seguinte maneira: 0 */3 * * * ....

      Nota: você não pode expressar valores de etapa de modo arbitrário; você só pode usar números inteiros que se dividam de maneira uniforme no intervalo permitido pelo campo em questão. Por exemplo, no campo “horas”, você só poderia usar uma barra antes de 1, 2, 3, 4, 6, 8 ou 12.

      Apresentamos a seguir, outros exemplos de como usar o componente de agendamento do cron:

      • * * * * * – Executa o comando a cada minuto.
      • 12 * * * * – Executa o comando 12 minutos após cada hora.
      • 0,15,30,45 * * * * – Executa o comando a cada 15 minutos.
      • */15 * * * * – Executa o comando a cada 15 minutos.
      • 0 4 * * * – Executar o comando todo dia às 4:00 AM.
      • 0 4 * * 2-4 – Executar o comando toda terça-feira, quarta-feira e quinta-feira às 4:00 AM.
      • 20,40 */8 * 7-12 * – Executar o comando no vigésimo e quadragésimo minuto de cada oitava hora, todos os dias dos últimos 6 meses do ano.

      Se acha isso tudo um pouco confuso ou se quiser ajuda sobre como escrever os agendamentos de suas próprias tarefas cron, o Cronitor fornece um editor de expressão da agenda do cron bastante útil, chamado “Crontab Guru”, que você pode usar para verificar se seus agendamentos do cron são válidos.

      Gerenciando os crontabs

      Assim que tiver escolhido uma agenda e souber o trabalho que deseja executar, você precisará colocá-lo em um lugar onde seu daemon consiga lê-lo.

      Como mencionado anteriormente, um crontab é um arquivo especial que mantém a agenda de trabalhos que o cron executará. No entanto, esses agendamentos não foram planejados para edição direta. Em vez disso, é recomendável que você utilize o comando crontab. Isso permite que você edite o crontab do perfil do seu usuário sem alterar seus privilégios com o sudo. O comando crontab também revelará se há erros de sintaxe no crontab, ao passo que editá-lo diretamente não revelará.

      É possível editar seu crontab com o seguinte comando:

      Isso abrirá seu crontab no editor de texto padrão do seu perfil de usuário.

      Nota: em novos servidores CentOS 8, por padrão, o comando crontab -e abrirá o crontab do seu usuário com o vi. O vi é um editor de texto extremamente eficaz e flexível; porém, para os usuários que não têm experiência com ele, o vi pode parecer um pouco lento.

      Se quiser usar um editor de texto mais acessível como seu editor padrão do crontab, instale e configure o nano como tal.

      Para tanto, instale o nano com o dnf:

      Quando solicitado, pressione y e, depois, ENTER para confirmar que deseja instalar o nano.

      Para definir o nano como o seu editor visual padrão de perfil de usuário, abra o arquivo .bash_profile para edição. Agora que o instalou, você pod fazer o seguinte com o nano:

      No final do arquivo, adicione a seguinte linha:

      ~/.bash_profile

      . . .
      export VISUAL="nano"
      

      Isso define a variável de ambiente VISUAL para o nano. A VISUAL é uma variável de ambiente Unix que muitos programas — incluindo o crontab — invocam para editar um arquivo. Após adicionar essa linha, salve e feche o arquivo, pressionando CTRL + X, Y e, depois, ENTER.

      Em seguida, recarregue o .bash_profile para que o shell capte a nova mudança:

      Assim que estiver no editor, você pode preencher sua agenda com cada trabalho em uma nova linha. Caso contrário, você pode salvar e fechar o crontab por enquanto. Se você tiver aberto o seu crontab com o vi – o editor de texto padrão do CentOS 8, você pode salvar e fechar o crontab, pressionando ESC para garantir que esteja no modo de comando do vi. Em seguida, digite :x e pressione ENTER.

      Observe que,nos sistemas Linux, há outro crontab armazenado no diretório /etc/. Trata-se de um crontab que abrange o sistema todo e que tem um campo adicional para o perfil de usuário sob o qual cada trabalho do cron deve ser executado. Este tutorial se concentra em crontabs específicos do usuário. Porém, se você quisesse editar o crontab no âmbito do sistema, poderia fazer isso com o seguinte comando:

      Se quiser visualizar o conteúdo do seu crontab, sem editá-lo, você pode usar o seguinte comando:

      É possível apagar seu crontab com o seguinte comando:

      Aviso: o comando a seguir não irá pedir que você confirme se deseja apagar seu crontab. Apenas execute-o caso tenha certeza de que deseja apagá-lo.

      Esse comando excluirá o crontab do usuário imediatamente. No entanto, você pode incluir o sinalizador -i para fazer com que o comando peça para você confirmar se realmente deseja excluir o crontab do usuário:

      Output

      crontab: really delete sammy's crontab?

      Quando solicitado, você deve digitar y para excluir o crontab ou n para cancelar a exclusão.

      Gerenciando o resultado do trabalho do cron

      Como os trabalhos do cron são executados em segundo plano, nem sempre fica aparente se eles foram executados com sucesso. Agora que sabe como usar o comando crontab e como agendar um trabalho do cron, você pode começar a experimentar maneiras diferentes de redirecionar o resultado dos trabalhos do cron para ajudar você a monitorar se eles foram executados com sucesso.

      Se tiver um agente de transferência de mensagens — como o Sendmail — instalado e configurado corretamente no seu servidor, você pode enviar o resultado das tarefas do cron para o endereço de e-mail associado ao seu perfil de usuário do Linux. Também é possível especificar manualmente um endereço de e-mail, colocando uma definição MAILTO no topo do crontab.

      Por exemplo, você poderia adicionar as linhas a seguir a um crontab. Tais linhas incluem uma instrução MAILTO, seguida de um exemplo de endereço de e-mail, uma diretiva SHELL que indica o shell a executar (bash, neste exemplo), uma diretiva HOME apontando para o caminho no qual procurar o binário do cron e uma única tarefa do cron:

      . . .
      
      MAILTO="example@digitalocean.com"
      SHELL=/bin/bash
      HOME=/
      
      * * * * * echo ‘Run this command every minute’
      

      Esse trabalho em particular retornará “Run this command every minute” (Executar este comando a cada minuto) e tal resultado será enviado por e-mail a cada minuto para o endereço especificado após a diretiva MAILTO.

      Também é possível redirecionar o resultado de uma tarefa do cron para um arquivo de registro ou para um local vazio para evitar receber um e-mail com o resultado.

      Para anexar o resultado de um comando agendado a um arquivo de registro, adicione >> ao final do comando, seguido do nome e local de um arquivo de registro de sua escolha, como no exemplo abaixo:

      * * * * * echo ‘Run this command every minute’ >> /directory/path/file.log
      

      Vamos supor que você queira usar o cron para executar um script, mas mantê-lo em execução em segundo plano. Para fazer isso, poderia redirecionar o resultado do script para um local vazio, como /dev/null, o que excluirá prontamente quaisquer dados escritos nele. Por exemplo, o trabalho do cron a seguir executa um script PHP em segundo plano:

      * * * * * /usr/bin/php /var/www/domain.com/backup.php > /dev/null 2>&1
      

      Este trabalho do cron também redireciona o erro padrão — representado por 2 — para o resultado padrão (>&1). Como o resultado padrão já está sendo redirecionado para /dev/null, isso permite essencialmente que o script seja executado silenciosamente. Mesmo se o crontab possuir uma instrução MAILTO, o resultado do comando não será enviado para o endereço de e-mail especificado.

      Restringindo o acesso

      É possível gerenciar quais usuários têm permissão para usar o comando crontab com os arquivos cron.allow e cron.deny, sendo que ambos ficam armazenados no diretório /etc/. Se o arquivo cron.deny existir, qualquer usuário listado nele estará impedido de editar seu crontab. Se o cron.allow existir, apenas os usuários listados nele poderão editar seus crontabs. Se ambos os arquivos existirem e o mesmo usuário estiver listado em cada um deles, o arquivo cron.allow irá substituir o cron.deny e o usuário conseguirá editar seu crontab.

      Por exemplo, para negar acesso a todos os usuários e depois dar acesso ao usuário ishmael, você poderia usar a seguinte sequência de comandos:

      • sudo echo ALL >>/etc/cron.deny
      • sudo echo ishmael >>/etc/cron.allow

      Primeiro, bloqueamos todos os usuários, anexando ALL ao arquivo cron.deny. Em seguida, ao adicionar o nome de usuário ao arquivo cron.allow, damos acesso ao perfil do usuário ishmael para executar trabalhos do cron.

      Note que se um usuário tiver privilégios sudo, ele pode editar o crontab de outro usuário com o seguinte comando:

      No entanto, se o cron.deny existir e o usuário estiver listado nele, mas não estiver listado no cron.allow, você receberá o seguinte erro após executar o comando anterior:

      Output

      The user user cannot use this program (crontab)

      Por padrão, a maioria dos daemons cron presumirão que todos os usuários têm acesso ao cron, a menos que o cron.allow ou o cron.deny existirem.

      Sintaxe especial

      Também existem vários comandos abreviados que você pode usar no seu arquivo crontab para ajudar a simplificar o agendamento de trabalhos. São essencialmente atalhos para o equivalente numérico do agendamento especificado:

      Atalho Abreviação para
      @hourly 0 * * * *
      @daily 0 0 * * *
      @weekly 0 0 * * 0
      @monthly 0 0 1 * *
      @yearly 0 0 1 1 *

      Nota: nem todos os daemons cron podem analisar essa sintaxe (especialmente versões mais antigas); assim, verifique novamente se a sintaxe funciona antes de confiar nela.

      Além disso, a abreviação @reboot irá executar qualquer comando que venha depois dela, sempre que o servidor for iniciado:

      @reboot echo "System start up"
      

      Usar esses atalhos sempre que possível pode ajudar a facilitar a interpretação do agendamento de tarefas no seu crontab.

      Conclusão

      O Cron é um utilitário flexível e eficaz, que pode reduzir a carga de trabalho de muitas tarefas associadas à administração do sistema. Quando combinado com scripts de shell, é possível automatizar tarefas que normalmente são tediosas ou complicadas.



      Source link

      Como automatizar suas implantações Node.js para produção com o Shipit no CentOS 7


      O autor selecionou a Fundação Electronic Frontier para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O Shipit é uma ferramenta de automação e implantação universal para desenvolvedores do Node.js. Ela possui um fluxo de tarefas baseado no pacote popular Orchestrator, comandos de login e SSH interativo através do OpenSSH, além de uma API extensível. Os desenvolvimentos podem usar o Shipit para automatizar os fluxos de trabalho de compilação e DE implantação para uma ampla gama de aplicativos Node.js.

      O fluxo de trabalho do Shipit permite que os desenvolvedores não apenas configurem tarefas, mas também especifiquem a ordem na qual são executadas; se devem ser executadas de maneira sincronizada ou não e em qual ambiente.

      Neste tutorial, você instalará e configurará o Shipit para implantar um aplicativo Node.js a partir do seu ambiente de desenvolvimento local para o seu ambiente de produção. Você usará o Shipit para implantar seu aplicativo e configurar o servidor remoto desta forma:

      • transferindo os arquivos do aplicativo Node.js do seu ambiente local para o ambiente de produção (usando o rsync, git e ssh).
      • instalando as dependências do seu aplicativo (módulos de nó)
      • configurando e gerenciando os processos Node.js em execução no servidor remoto com o PM2.

      Pré-requisitos

      Antes de iniciar este tutorial, você precisará do seguinte:

      • Dois servidores CentOS 7 (neste tutorial, eles serão chamados de app e web), configurados com rede privada, seguindo as instruções do tutorial Como configurar um aplicativo Node.js para produção no CentOS 7.
      • Nginx (no seu servidor web), protegido com o protocolo TLS/SSL como mostrado no tutorial Como proteger o Nginx com o Let’s Encrypt no CentOS 7. Note que, se você estiver seguindo as instruções dos pré-requisitos em ordem cronológica, para o seu servidor web você só terá que realizar os passos 1, 4 e 6.
      • Node.js e npm instalados em seu ambiente de desenvolvimento. Este tutorial usa a versão 10.17.0. Para instalar essa versão em macOS ou Ubuntu 18.04, siga os passos descritos no artigo sobre Como instalar o Node.js e criar um ambiente de desenvolvimento local em macOS ou a seção intitulada Instalando usando um PPA, do artigo sobre Como instalar o Node.js no Ubuntu 18.04. Por ter o Node.js instalado, você também tem o npm instalado; este tutorial usa a versão 6.11.3.
      • Um computador de desenvolvimento local com o rsync e git instalados.
      • Uma conta junto ao GitHub ou outro provedor de serviços git hospedados. Este tutorial usará o GitHub.

      Nota: os usuários do Windows terão que instalar o Subsistema Windows para o Linux para executar os comandos neste guia.

      Passo 1 — Configurando o repositório remoto

      O Shipit exige um repositório Git para a sincronização entre a máquina de desenvolvimento local e o servidor remoto. Neste passo, você criará um repositório remoto no Github.com. Embora cada provedor seja ligeiramente diferente, os comandos são de certo modo transferíveis.

      Para criar um repositório, abra o Github.com em seu navegador Web e faça login. Você notará que, no canto superior de todas as páginas, existe um símbolo de adição +. Clique no + e, em seguida, clique em Novo repositório.

      Github-novo-repositório

      Digite um nome curto e fácil de lembrar para o seu repositório como ,por exemplo, hello-world. Note que, independentemente do nome que escolher aqui, ele será replicado como a pasta do projeto a partir da qual você irá trabalhar em sua máquina local.

      Github-nome-repositório

      De maneira opcional, adicione uma descrição do seu repositório.

      Github-descrição-repositório

      Defina a visibilidade do seu repositório de acordo com sua preferência, como sendo pública ou privada.

      Certifique-se de que o repositório seja inicializado com um .gitignore, selecionando Node na lista suspensa Add .gitignore. Este passo é importante para evitar que arquivos desnecessários (como a pasta node_modules) sejam adicionados ao seu repositório.

      Github-nó-gitignore

      Clique no botão Criar repositório.

      Agora, o repositório precisa ser clonado do Github.com para sua máquina local.

      Abra seu terminal e navegue até o local onde quer armazenar todos os seus arquivos do projeto Node.js. Note que este processo criará uma subpasta dentro do diretório atual. Para clonar o repositório para sua máquina local, execute o seguinte comando:

      • git clone https://github.com/your-github-username/your-github-repository-name.git

      Você precisará substituir o your-github-username e your-github-repository-name para que reflitam seu nome de usuário do Github e o nome do repositório anteriormente fornecido.

      Nota: caso tenha habilitado a autenticação de dois fatores (2FA) no Github.com, ao acessar o Github na linha de comando, você deverá usar um token de acesso pessoal ou uma chave SSH, em vez de sua senha. A página de ajuda do Github relacionada à 2FA fornece mais informações.

      Você verá um resultado parecido com este:

      Output

      Cloning into 'your-github-repository-name'... remote: Enumerating objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3 Unpacking objects: 100% (3/3), done.

      Vá até o repositório, executando o seguinte comando:

      • cd your-github-repository-name

      Dentro do repositório, há um arquivo e uma pasta únicos, sendo ambos arquivos usados pelo Git para gerenciar o repositório. Você pode verificar isso com:

      Você verá um resultado parecido com este:

      Output

      total 8 0 drwxr-xr-x 4 asciant staff 128 22 Apr 07:16 . 0 drwxr-xr-x 5 asciant staff 160 22 Apr 07:16 .. 0 drwxr-xr-x 13 asciant staff 416 22 Apr 07:16 .git 8 -rw-r--r-- 1 asciant staff 914 22 Apr 07:16 .gitignore

      Agora que você configurou um repositório git funcional, irá criar o arquivo shipit.js que gerencia o seu processo de implantação.

      Passo 2 — Integrando o Shipit a um projeto Node.js

      Neste passo, você criará um projeto Node.js como exemplo e, depois, adicionará os pacotes do Shipit. Este tutorial fornece um app exemplo — o servidor web Node.js que aceita solicitações HTTP e responde com um Hello World em texto simples. Para criar o aplicativo, execute o seguinte comando:

      Adicione o seguinte código de aplicativo exemplo ao hello.js (atualizando a variável APP_PRIVATE_IP_ADDRESS com o endereço IP da rede privada do servidor do seu app):

      hello.js

      var http = require('http');
      http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Hello Worldn');
      }).listen(8080, 'APP_PRIVATE_IP_ADDRESS');
      console.log('Server running at http://APP_PRIVATE_IP_ADDRESS:8080/');
      

      Agora, crie seu arquivo package.json para seu aplicativo:

      Esse comando cria um arquivo package.json, que você usará para configurar seu aplicativo Node.js. No próximo passo, você adicionará dependências a esse arquivo com a interface de linha de comando npm.

      Output

      Wrote to ~/hello-world/package.json: { "name": "hello-world", "version": "1.0.0", "description": "", "main": index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      Em seguida, instale os pacotes npm necessários com o seguinte comando:

      • npm install --save-dev shipit-cli shipit-deploy shipit-shared

      Aqui, você usará o sinalizador --save-dev, uma vez que os pacotes do Shipit somente são necessários em sua máquina local. Você verá um resultado parecido com este:

      Output

      + shipit-shared@4.4.2 + shipit-cli@4.2.0 + shipit-deploy@4.1.4 updated 4 packages and audited 21356 packages in 11.671s found 62 low severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details

      Isso também adicionou os três pacotes ao seu arquivo package.json como dependências de desenvolvimento:

      package.json

      . . .
        "devDependencies": {
          "shipit-cli": "^4.2.0",
          "shipit-deploy": "^4.1.4",
          "shipit-shared": "^4.4.2"
        },
      . . .
      

      Com seu ambiente local configurado, agora você pode prosseguir com a preparação do servidor app remoto para implantações baseadas no Shipit.

      Passo 3 — Preparando o servidor app remoto

      Neste passo, você usará o ssh para se conectar ao seu servidor app e instalar sua dependência remota rsync. O Rsync é um utilitário para transferir e sincronizar arquivos de modo eficiente entre os discos do computador local e os computadores em rede, comparando os tempos de modificação e os tamanhos dos arquivos.

      O Shipit usa o rsync para transferir e sincronizar arquivos entre seu computador local e o servidor app remoto. Você não emitirá qualquer comando diretamente no rsync; o Shipit fará isso por você.

      Nota: o tutorial Como configurar um aplicativo Node.js para produção no CentOS 7 possibilitou que você ficasse com dois servidores, app e web. Esses comandos devem ser executados apenas no app.

      Conecte-se ao seu servidor app remoto via ssh:

      • ssh deployer@your_app_server_ip

      Instale o rsync no seu servidor, executando o seguinte comando:

      Confirme a instalação com:

      Você verá uma linha semelhante no resultado deste comando:

      Output

      rsync version 3.1.2 protocol version 31 . . .

      Você pode encerrar sua sessão ssh, digitando exit.

      Com o rsync instalado e disponível na linha de comando, você pode prosseguir com as tarefas de implantação e sua relação com eventos.

      Passo 4 — Configurando e executando tarefas de implantação

      Tanto events quanto tasks são componentes chave das implantações Shipit. É importante entender como eles complementam a implantação do seu aplicativo. Os eventos desencadeados pelo Shipit representam pontos específicos no ciclo de vida da implantação. Suas tarefas executarão em reposta a esses eventos, com base na sequência do clico de vida do Shipit.

      Um exemplo comum de onde esse sistema de tarefa/evento é útil em um aplicativo Node.js é na instalação das dependências do app (node_modules), no servidor remoto. Mais adiante neste passo, você fará o Shipit escutar para o evento updated (que é emitido depois que os arquivos do aplicativo são transferidos) e executar uma tarefa para instalar as dependências do aplicativo (npm install) no servidor remoto.

      Para escutar eventos e executar tarefas, o Shipit precisa de um arquivo de configuração que possua informações sobre seu servidor remoto (o servidor app) e registre ouvintes de eventos e os comandos a serem executados por essas tarefas. Esse arquivo fica no seu computador de desenvolvimento local, no diretório do seu aplicativo Node.js.

      Para começar, crie esse arquivo, incluindo informações sobre seu servidor remoto, os ouvintes de eventos nos quais quer se inscrever e algumas definições das suas tarefas. Crie o shipitfile.js no diretório raiz do seu aplicativo, em sua máquina local, executando o seguinte comando:

      Agora que você criou um arquivo, ele precisa ser preenchido com as informações iniciais do ambiente que o Shipit precisa. Basicamente, esse é o local do seu repositório Git remoto e, mais importante que tudo, do endereço IP público e da conta de usuário SSH do seu servidor app.

      Adicione essa configuração inicial e atualize as linhas destacadas para que correspondam ao seu ambiente:

      shipitfile.js

      module.exports = shipit => {
        require('shipit-deploy')(shipit);
        require('shipit-shared')(shipit);
      
        const appName = 'hello';
      
        shipit.initConfig({
          default: {
            deployTo: '/home/sammy/your-domain',
            repositoryUrl: 'https://git-provider.tld/YOUR_GIT_USERNAME/YOUR_GIT_REPO_NAME.git',
            keepReleases: 5,
            shared: {
              overwrite: true,
              dirs: ['node_modules']
            }
          },
          production: {
            servers: 'sammy@YOUR_APP_SERVER_PUBLIC_IP'
          }
        });
      
        const path = require('path');
        const ecosystemFilePath = path.join(
          shipit.config.deployTo,
          'shared',
          'ecosystem.config.js'
        );
      
        // Our listeners and tasks will go here
      
      };
      

      Atualizando as variables no seu método shipit.initConfig dá ao Shipit uma configuração específica para sua implantação. Essas variáveis representam o seguinte para o Shipit:

      • deployTo: é o diretório onde o Shipit implantará o código do seu aplicativo no servidor remoto. Aqui, você usa a pasta /home/ para um usuário não raiz com privilégios sudo (/home/sammy) uma vez que é segura e evitará problemas de permissão. O componente /your-domain é uma convenção de nomenclatura para distinguir a pasta das demais na pasta inicial do usuário.
      • repositoryUrl: é a URL do repositório completo do Git. O Shipit usará essa URL para garantir que os arquivos do projeto estejam em sincronia antes da implantação.
      • keepReleases: é o número de lançamentos a ser mantido no servidor remoto. Um release (lançamento) é uma pasta com data que contém os arquivos do seu aplicativo no momento do lançamento. Eles podem ser úteis para rollback (reverter) uma implantação.
      • shared: é a configuração que corresponde aos keepReleases que permite que os diretórios sejam shared (compartilhados) entre os lançamentos. Nessa instância, temos uma única pasta node_modules, que é compartilhada entre todos os lançamentos.
      • production: representa um servidor remoto para o qual implantar seu aplicativo. Nessa instância, você tem um servidor (servidor app) único, ao qual você dá o nome de production, com o servers: configuração que correspondendo ao seu user SSH e ao public ip address do SSH. O nome production corresponde ao comando de implantação do Shipit usado ao final deste tutorial (npx shipit server name deploy ou, no seu caso, npx shipit production deploy).

      No repositório Github para o Shipit, você pode encontrar mais informações sobre a o objeto de Configuração da implantação do Shipit.

      Antes de continuar a atualizar seu shipitfile.js, vamos analisar o seguinte exemplo de trecho de código para entender as tarefas do Shipit:

      Example event listener

      shipit.on('deploy', () => { shipit.start('say-hello'); }); shipit.blTask('say-hello', async () => { shipit.local('echo "hello from your local computer"') });

      Esse é um exemplo de tarefa que utiliza o método shipit.on para se inscrever no evento deploy (implantar). Essa tarefa esperará que o evento deploy seja emitido pelo ciclo de vida do Shipit. Depois, quando o evento é recebido, a tarefa executa o método shipit.start, que diz ao Shipit para start (iniciar) a tarefa say-hello.

      O método shipit.on aceita dois parâmetros, o nome do evento para escutar e a função de callback a ser executada quando o evento for recebido.

      Sob a declaração do método shipit.on, a tarefa é definida com o método shipit.blTask. Isso cria uma tarefa do Shipit que irá bloquear outras tarefas durante sua execução (é uma tarefa síncrona). O método shipit.blTask também aceita dois parâmetros, o nome da tarefa que está definindo e uma função de callback para ser executada quando a tarefa for ativada pelo shipit.start.

      Dentro da função de callback dessa tarefa exemplo (say-hello), o método shipit.local executa um comando na máquina local. O comando local ecoa "hello from your local computer" no resultado do terminal.

      Se quisesse executar um comando no servidor remoto, usaria o método shipit.remote. Os dois métodos, shipit.local e shipit.remote, fornecem uma API para emitir comandos tanto localmente quanto remotamente como parte de uma implantação.

      Agora, atualize o shipitfile.js para incluir ouvintes de eventos para se inscrever no ciclo de vida do Shipit com shipit.on. Adicione os ouvintes de eventos ao seu shipitfile.js, inserindo-os após o espaço reservado para comentário da configuração inicial // Our tasks will go here:

      shipitfile.js

      . . .
        shipit.on('updated', () => {
          shipit.start('npm-install', 'copy-config');
        });
      
        shipit.on('published', () => {
          shipit.start('pm2-server');
        });
      

      Esses dois métodos estão escutando os eventos updated e published que são emitidos como parte do ciclo de vida da implantação do Shipit. Quando os eventos forem recebidos, cada qual irá iniciar tarefas usando o método shipit.start, assim como na tarefa exemplo.

      Agora que você agendou os ouvintes, adicionará a tarefa correspondente. Adicione a seguinte tarefa ao seu shipitfile.js, inserindo-a após seus ouvintes de eventos:

      shipitfile.js

      . . .
      shipit.blTask('copy-config', async () => {
      
      const fs = require('fs');
      
      const ecosystem = `
      module.exports = {
      apps: [
        {
          name: '${appName}',
          script: '${shipit.releasePath}/hello.js',
          watch: true,
          autorestart: true,
          restart_delay: 1000,
          env: {
            NODE_ENV: 'development'
          },
          env_production: {
            NODE_ENV: 'production'
          }
        }
      ]
      };`;
      
        fs.writeFileSync('ecosystem.config.js', ecosystem, function(err) {
          if (err) throw err;
          console.log('File created successfully.');
        });
      
        await shipit.copyToRemote('ecosystem.config.js', ecosystemFilePath);
      });
      

      Primeiro, você declara uma tarefa chamada copy-config. Essa tarefa cria um arquivo local chamado ecosystem.config.js e, depois, copia esse arquivo para o seu servidor remoto app. O PM2 usa esse arquivo para gerenciar seu aplicativo Node.js. Ela fornece as informações necessárias do caminho do arquivo para o PM2 para garantir que ele esteja executando seus arquivos mais recentemente implantados. Mais adiante no processo de compilação, você criará uma tarefa que executa o PM2 com o ecosystem.config.js como configuração.

      Caso seu aplicativo precise de variáveis de ambiente (como uma string de conexão com banco de dados), você pode declará-las tanto localmente em env: quanto no servidor remoto em env_production: da mesma maneira que você definiu a variável NODE_ENV nesses objetos.

      Adicione a próxima tarefa ao seu shipitfile.js após a tarefa copy-config:

      shipitfile.js

      . . .
      shipit.blTask('npm-install', async () => {
        shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
      });
      

      Em seguida, declare uma tarefa chamada npm-install. Essa tarefa usa um terminal bash remoto (via shipit.remote) para instalar as dependências do app (pacotes npm).

      Adicione a última tarefa ao seu shipitfile.js depois da tarefa npm-install:

      shipitfile.js

      . . .
      shipit.blTask('pm2-server', async () => {
        await shipit.remote(`pm2 delete -s ${appName} || :`);
        await shipit.remote(
          `pm2 start ${ecosystemFilePath} --env production --watch true`
        );
      });
      

      Por fim, declare uma tarefa chamada pm2-server. Essa tarefa também usa um terminal bash remoto para primeiro impedir o PM2 de gerenciar sua implantação anterior pelo comando delete e, em seguida, iniciar uma nova instância do seu servidor Node.js, fornecendo o arquivo ecosystem.config.js como uma variável. Além disso, você também avisa o PM2 que ele deve usar variáveis de ambiente a partir do bloco production na sua configuração inicial e pede ao PM2 para monitorar o aplicativo, reiniciando-o caso falhe.

      O arquivo completo do shipitfile.js:

      shipitfile.js

      module.exports = shipit => {
        require('shipit-deploy')(shipit);
        require('shipit-shared')(shipit);
      
        const appName = 'hello';
      
        shipit.initConfig({
          default: {
            deployTo: '/home/deployer/example.com',
            repositoryUrl: 'https://git-provider.tld/YOUR_GIT_USERNAME/YOUR_GIT_REPO_NAME.git',
            keepReleases: 5,
            shared: {
              overwrite: true,
              dirs: ['node_modules']
            }
          },
          production: {
            servers: 'deployer@YOUR_APP_SERVER_PUBLIC_IP'
          }
        });
      
        const path = require('path');
        const ecosystemFilePath = path.join(
          shipit.config.deployTo,
          'shared',
          'ecosystem.config.js'
        );
      
        // Our listeners and tasks will go here
        shipit.on('updated', async () => {
          shipit.start('npm-install', 'copy-config');
        });
      
        shipit.on('published', async () => {
          shipit.start('pm2-server');
        });
      
        shipit.blTask('copy-config', async () => {
          const fs = require('fs');
          const ecosystem = `
      module.exports = {
        apps: [
          {
            name: '${appName}',
            script: '${shipit.releasePath}/hello.js',
            watch: true,
            autorestart: true,
            restart_delay: 1000,
            env: {
              NODE_ENV: 'development'
            },
            env_production: {
              NODE_ENV: 'production'
            }
          }
        ]
      };`;
      
          fs.writeFileSync('ecosystem.config.js', ecosystem, function(err) {
            if (err) throw err;
            console.log('File created successfully.');
          });
      
          await shipit.copyToRemote('ecosystem.config.js', ecosystemFilePath);
        });
      
        shipit.blTask('npm-install', async () => {
          shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
        });
      
        shipit.blTask('pm2-server', async () => {
          await shipit.remote(`pm2 delete -s ${appName} || :`);
          await shipit.remote(
            `pm2 start ${ecosystemFilePath} --env production --watch true`
          );
        });
      };
      

      Salve e saia do arquivo quando estiver pronto.

      Com seu shipitfile.js configurado, ouvintes de eventos e as tarefas finalizadas associadas, você pode prosseguir com a implantação para o servidor app.

      Passo 5 — Implantando seu aplicativo

      Neste passo, você implantará seu aplicativo remotamente e testará se a implantação disponibilizou seu aplicativo na internet.

      Como o Shipit clona os arquivos do projeto do repositório remoto do Git, você precisa mandar seus arquivos do aplicativo local Node.js da sua máquina local para o Github. Navegue até o diretório do seu aplicativo do projeto Node.js (onde seu hello.js e shipitfile.js estão localizados) e execute o seguinte comando:

      O comando git status mostra o estado do diretório de trabalho e a área de preparação. Ele permite que você veja quais alterações foram preparadas, quais não foram e quais arquivos o Git não está rastreando. Seus arquivos não estão rastreados e aparecem em vermelho no resultado:

      Output

      On branch master Your branch is up to date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed) hello.js package-lock.json package.json shipitfile.js nothing added to commit but untracked files present (use "git add" to track)

      Você pode adicionar esses arquivos ao seu repositório com o seguinte comando:

      Esse comando não gera nenhum resultado, embora caso fosse executar o git status novamente, os arquivos apareceriam em verde, com uma nota avisando que existem alterações a serem confirmadas.

      Você pode criar uma confirmação, executando o seguinte comando:

      • git commit -m "Our first commit"

      O resultado desse comando fornece algumas informações específicas do Git sobre os arquivos.

      Output

      [master c64ea03] Our first commit 4 files changed, 1948 insertions(+) create mode 100644 hello.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 shipitfile.js

      Agora, tudo o que resta é mandar sua confirmação para o repositório remoto, para que o Shipit clonar para o seu servidor app durante a implantação. Execute o seguinte comando:

      O resultado inclui informações sobre a sincronização com o repositório remoto:

      Output

      Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 8 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 15.27 KiB | 7.64 MiB/s, done. Total 6 (delta 0), reused 0 (delta 0) To github.com:Asciant/hello-world.git e274312..c64ea03 master -> master

      Para implantar seu aplicativo, execute o seguinte comando:

      • npx shipit production deploy

      O resultado desse comando (que é grande demais para ser incluído por completo) fornece detalhes sobre as tarefas que estão sendo executadas e o resultado da função específica. O resultado que se segue à tarefa pm2-server mostra que o app Node.js foi iniciado:

      Output

      Running 'deploy:init' task... Finished 'deploy:init' after 432 μs . . . Running 'pm2-server' task... Running "pm2 delete -s hello || :" on host "centos-ap-app.asciant.com". Running "pm2 start /home/deployer/example.com/shared/ecosystem.config.js --env production --watch true" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com [PM2][WARN] Node 4 is deprecated, please upgrade to use pm2 to have all features @centos-ap-app.asciant.com [PM2][WARN] Applications hello not running, starting... @centos-ap-app.asciant.com [PM2] App [hello] launched (1 instances) @centos-ap-app.asciant.com ┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────┬──────────┐ @centos-ap-app.asciant.com │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ @centos-ap-app.asciant.com ├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────┼──────────┤ @centos-ap-app.asciant.com │ hello │ 0 │ 1.0.0 │ fork │ 4177 │ online │ 0 │ 0s │ 0% │ 4.5 MB │ deployer │ enabled │ @centos-ap-app.asciant.com └──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────┴──────────┘ @centos-ap-app.asciant.com Use `pm2 show <id|name>` to get more details about an app Finished 'pm2-server' after 5.27 s Running 'deploy:clean' task... Keeping "5" last releases, cleaning others Running "(ls -rd /home/deployer/example.com/releases/*|head -n 5;ls -d /home/deployer/example.com/releases/*)|sort|uniq -u|xargs rm -rf" on host "centos-ap-app.asciant.com". Finished 'deploy:clean' after 1.81 s Running 'deploy:finish' task... Finished 'deploy:finish' after 222 μs Finished 'deploy' [ deploy:init, deploy:fetch, deploy:update, deploy:publish, deploy:clean, deploy:finish ]

      Para visualizar seu aplicativo como um usuário visualizaria, você pode digitar a URL your-domain do seu site em seu navegador para acessar o servidor web. Isso servirá o aplicativo Node.js, por proxy reverso, no servidor app, onde seus arquivos foram implantados.

      Você verá uma saudação Hello World.

      Nota: após a primeira implantação, seu repositório Git irá rastrear um arquivo recém-criado, chamado ecosystem.config.js. Como esse arquivo será recompilado a cada implantação, podendo conter segredos do aplicativo compilado, ele deve ser adicionado ao arquivo .gitignore, no diretório raiz do aplicativo em sua máquina local, antes da sua próxima confirmação do git.

      .gitignore

      . . .
      # ecosystem.config
      ecosystem.config.js
      

      Você implantou seu aplicativo Node.js em seu servidor app, que se refere à sua nova implantação. Com tudo em funcionamento, você pode prosseguir com o monitoramento dos processos do seu aplicativo.

      Passo 6 — Monitorando seu aplicativo

      O PM2 é uma ótima ferramenta para gerenciar seus processos remotos, mas também fornece recursos para monitorar o desempenho desses processos do aplicativo.

      Conecte-se ao seu servidor app remoto via SSH com este comando:

      • ssh deployer@your_app_server_ip

      Para obter informações específicas relacionadas aos seus processos gerenciados pelo PM2, execute o seguinte:

      Você verá um resultado parecido com este:

      Output

      ┌─────────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬──────┬───────────┬──────────┬──────────┐ │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├─────────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼──────┼───────────┼──────────┼──────────┤ │ hello │ 0 │ 0.0.1 │ fork │ 3212 │ online │ 0 │ 62m │ 0.3% │ 45.2 MB │ deployer │ enabled │ └─────────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴──────┴───────────┴──────────┴──────────┘

      Você verá um resumo das informações que o PM2 coletou. Para ver informações detalhadas, execute:

      O resultado dá mais detalhes sobre as informações do resumo fornecidas pelo comando pm2 list. Ele também fornece informações sobre vários comandos auxiliares e fornece os locais dos arquivos de registro:

      Output

      Describing process with id 0 - name hello ┌───────────────────┬─────────────────────────────────────────────────────────────┐ │ status │ online │ │ name │ hello │ │ version │ 1.0.0 │ │ restarts │ 0 │ │ uptime │ 82s │ │ script path │ /home/deployer/example.com/releases/20190531213027/hello.js │ │ script args │ N/A │ │ error log path │ /home/deployer/.pm2/logs/hello-error.log │ │ out log path │ /home/deployer/.pm2/logs/hello-out.log │ │ pid path │ /home/deployer/.pm2/pids/hello-0.pid │ │ interpreter │ node │ │ interpreter args │ N/A │ │ script id │ 0 │ │ exec cwd │ /home/deployer │ │ exec mode │ fork_mode │ │ node.js version │ 4.2.3 │ │ node env │ production │ │ watch & reload │ ✔ │ │ unstable restarts │ 0 │ │ created at │ 2019-05-31T21:30:48.334Z │ └───────────────────┴─────────────────────────────────────────────────────────────┘ Revision control metadata ┌──────────────────┬────────────────────────────────────────────────────┐ │ revision control │ git │ │ remote url │ N/A │ │ repository root │ /home/deployer/example.com/releases/20190531213027 │ │ last update │ 2019-05-31T21:30:48.559Z │ │ revision │ 62fba7c8c61c7769022484d0bfa46e756fac8099 │ │ comment │ Our first commit │ │ branch │ master │ └──────────────────┴────────────────────────────────────────────────────┘ Divergent env variables from local env ┌───────────────────────────┬───────────────────────────────────────┐ │ XDG_SESSION_ID │ 15 │ │ HOSTNAME │ N/A │ │ SELINUX_ROLE_REQUESTED │ │ │ TERM │ N/A │ │ HISTSIZE │ N/A │ │ SSH_CLIENT │ 44.222.77.111 58545 22 │ │ SELINUX_USE_CURRENT_RANGE │ │ │ SSH_TTY │ N/A │ │ LS_COLORS │ N/A │ │ MAIL │ /var/mail/deployer │ │ PATH │ /usr/local/bin:/usr/bin │ │ SELINUX_LEVEL_REQUESTED │ │ │ HISTCONTROL │ N/A │ │ SSH_CONNECTION │ 44.222.77.111 58545 209.97.167.252 22 │ └───────────────────────────┴───────────────────────────────────────┘ . . .

      O PM2 também fornece uma ferramenta de monitoramento dentro do terminal, que pode ser acessada com:

      O resultado desse comando é um painel interativo, onde o pm2 fornece informações de processo, registros, métricas e metadados em tempo real. Este painel pode ajudar no monitoramento de recursos e registros de erro:

      Output

      ┌─ Process list ────────────────┐┌─ Global Logs ─────────────────────────────────────────────────────────────┐ │[ 0] hello Mem: 22 MB ││ │ │ ││ │ │ ││ │ └───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘ ┌─ Custom metrics (http://bit.l─┐┌─ Metadata ────────────────────────────────────────────────────────────────┐ │ Heap Size 10.73 ││ App Name hello │ │ Heap Usage 66.14 ││ Version N/A │ │ Used Heap Size 7.10 ││ Restarts 0 │ │ Active requests 0 ││ Uptime 55s │ │ Active handles 4 ││ Script path /home/asciant/hello.js │ │ Event Loop Latency 0.70 ││ Script args N/A │ │ Event Loop Latency p95 ││ Interpreter node │ │ ││ Interpreter args N/A │ └───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘

      Com uma compreensão sobre como você pode monitorar seus processos com o PM2, você pode prosseguir e ver como o Shipit pode ajudar na reversão para uma implantação anterior em funcionamento.

      Termine sua sessão ssh no seu servidor app executando exit.

      Passo 7 — Revertendo uma implantação problemática

      Às vezes, as implantações revelam bugs imprevistos, ou problemas que fazem com que seu site falhe. Os desenvolvedores e mantenedores do Shipit previram esse problema e proporcionaram a capacidade de se fazer a reversão para implantações anteriores (em funcionamento) do seu aplicativo.

      Para garantir que sua configuração PM2 permaneça, adicione outro ouvinte de eventos ao shipitfile.js no evento rollback (reversão):

      shipitfile.js

      . . .
        shipit.on('rollback', () => {
          shipit.start('npm-install', 'copy-config');
        });
      

      Adicione um ouvinte ao evento rollback para executar suas tarefas npm-install e copy-config. Isso é necessário, pois, ao contrário do evento published, o evento updated não é executado pelo ciclo de vida do Shipit quando se reverte uma implantação. Adicionar esse ouvinte de eventos garante que seu gerenciador de processos PM2 apontará para a implantação mais recente, mesmo no caso de uma reversão.

      Esse processo é semelhante ao da implantação, com uma pequena alteração no comando. Para tentar reverter para uma implantação anterior, execute o seguinte:

      • npx shipit production rollback

      Assim como o comando deploy, o rollback fornece detalhes sobre o processo de reversão e as tarefas que estão sendo executadas:

      Output

      Running 'rollback:init' task... Get current release dirname. Running "if [ -h /home/deployer/example.com/current ]; then readlink /home/deployer/example.com/current; fi" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com releases/20190531213719 Current release dirname : 20190531213719. Getting dist releases. Running "ls -r1 /home/deployer/example.com/releases" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com 20190531213719 @centos-ap-app.asciant.com 20190531213519 @centos-ap-app.asciant.com 20190531213027 Dist releases : ["20190531213719","20190531213519","20190531213027"]. Will rollback to 20190531213519. Finished 'rollback:init' after 3.96 s Running 'deploy:publish' task... Publishing release "/home/deployer/example.com/releases/20190531213519" Running "cd /home/deployer/example.com && if [ -d current ] && [ ! -L current ]; then echo "ERR: could not make symlink"; else ln -nfs releases/20190531213519 current_tmp && mv -fT current_tmp current; fi" on host "centos-ap-app.asciant.com". Release published. Finished 'deploy:publish' after 1.8 s Running 'pm2-server' task... Running "pm2 delete -s hello || :" on host "centos-ap-app.asciant.com". Running "pm2 start /home/deployer/example.com/shared/ecosystem.config.js --env production --watch true" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com [PM2][WARN] Node 4 is deprecated, please upgrade to use pm2 to have all features @centos-ap-app.asciant.com [PM2][WARN] Applications hello not running, starting... @centos-ap-app.asciant.com [PM2] App [hello] launched (1 instances) @centos-ap-app.asciant.com ┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────┬──────────┐ @centos-ap-app.asciant.com │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ @centos-ap-app.asciant.com ├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────┼──────────┤ @centos-ap-app.asciant.com │ hello │ 0 │ 1.0.0 │ fork │ 4289 │ online │ 0 │ 0s │ 0% │ 4.5 MB │ deployer │ enabled │ @centos-ap-app.asciant.com └──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────┴──────────┘ @centos-ap-app.asciant.com Use `pm2 show <id|name>` to get more details about an app Finished 'pm2-server' after 5.55 s Running 'deploy:clean' task... Keeping "5" last releases, cleaning others Running "(ls -rd /home/deployer/example.com/releases/*|head -n 5;ls -d /home/deployer/example.com/releases/*)|sort|uniq -u|xargs rm -rf" on host "centos-ap-app.asciant.com". Finished 'deploy:clean' after 1.82 s Running 'rollback:finish' task... Finished 'rollback:finish' after 615 μs Finished 'rollback' [ rollback:init, deploy:publish, deploy:clean, rollback:finish ]

      Você configurou o Shipit para manter 5 versões de lançamento, através da configuração de keepReleases: 5 no shipitfile.js. O Shipit monitora essas versões internamente para garantir a capacidade de reverter quando necessário. O Shipit também fornece uma maneira conveniente de identificar as versões, criando um diretório nomeado na forma de um carimbo de data/hora (YYYYMMDDHHmmss – Exemplo: /home/deployer/your-domain/releases/20190420210548).

      Se quisesse personalizar ainda mais o processo de reversão, você poderia ouvir eventos específicos para a operação de reversão. Na sequência, você poderá usar esses eventos para executar tarefas que irão complementar sua reversão. Você pode consultar a lista de eventos fornecida no detalhamento do ciclo de vida do Shipit e configurar as tarefas/ouvintes dentro do seu shipitfile.js.

      Capacidade de reversão significa que sempre será possível oferecer aos seus usuários uma versão do seu aplicativo que funcione, mesmo se uma implantação introduzir erros/problemas inesperados.

      Conclusão

      Neste tutorial, você configurou um fluxo de trabalho que permite que crie uma alternativa altamente personalizável da Plataforma como um Serviço, tudo a partir de alguns servidores. Esse fluxo de trabalho leva em consideração implantações e configurações personalizadas, o monitoramento de processos com o PM2, a possibilidade de dimensionar e adicionar serviços, servidores adicionais ou ambientes à implantação, quando necessário.

      Se estiver interessado em continuar no desenvolvimento de suas habilidades com o Node.js, confira o material sobre Node.js da DigitalOcean, bem como a série sobre Como programar no Node.js.



      Source link

      Cómo automatizar implementaciones de producción de Node.js con Shipit en CentOS 7


      El autor seleccionó la Electronic Frontier Foundation para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Shipit es una herramienta universal de automatización e implementación para desarrolladores de Node.js. Incluye un flujo de tareas basado en el popular paquete Orchestrator, comandos de inicio de sesión y SSH interactivos a través de OpenSSH y una API extensible. Los desarrolladores pueden usar Shipit a fni de automatizar flujos de trabajo de compilación e implementación para una amplia variedad de aplicaciones de Node.js.

      El flujo de trabajo de Shipit no solo permite a los desarrolladores configurar tareas, sino también especificar su orden de ejecución; si deben ejecutarse de forma sincrónica o asincrónica y en qué entorno.

      En este tutorial, instalará y configurará Shipit para implementar una aplicación de Node.js de su entorno de desarrollo local en su entorno de producción. Usará Shipit para implementar su aplicación y configurar el servidor remoto haciendo lo siguiente:

      • transfiriendo los archivos de su aplicación de Node.js de su entorno local al entorno de producción (con rsync, git y ssh);
      • instando las dependencias de su aplicación (módulos de nodos);
      • configurando y administrando los procesos de Node.js que se ejecutan en el servidor remoto con PM2.

      Requisitos previos

      Antes de iniciar este tutorial, necesitará lo siguiente:

      Nota: Los usuarios de Windows deberán instalar el subsistema de Windows para Linux para ejecutar los comandos de esta guía.

      Paso 1: Configurar el repositorio remoto

      En Shipit se requiere un repositorio de Git para la sincronía entre la máquina de desarrollo local y el servidor remoto. En este paso, creará un repositorio remoto en Github.com. Si bien cada proveedor es ligeramente diferente, los comandos pueden ser transferibles.

      Para crear un repositorio, abra Github.com en su navegador web e inicie sesión. Verá un símbolo + en la esquina superior derecha de cualquier página. Haga clic en + y luego en New repository.

      Github-new-repository

      Ingrese un nombre corto y recordable para su repositorio; por ejemplo, hello-world. Tenga en cuenta que cualquier nombre que elija aquí se replicará como la carpeta del proyecto a partir de la que trabajará en su máquina local.

      Github-repository-name

      De manera opcional, puede añadir una descripción de su repositorio.

      Github-repository-description

      Según su preferencia, fije la visibilidad de su repositorio de modo que sea público o privado.

      Asegúrese de que este se inicialice con .gitignore; seleccione Node en la lista desplegable Add .gitignore. Este paso es importante para evitar que se añadan archivos innecesarios (por ejemplo, la carpeta node_modules) a su repositorio.

      Github-gitignore-node

      Haga clic en el botón Create repository.

      Ahora, el repositorio debe clonarse de Github.com y enviarse a su equipo local.

      Abra su terminal y diríjase a la ubicación en la que desee almacenar todos los archivos de su proyecto de Node.js. Tenga en cuenta que en este proceso se creará una subcarpeta dentro del directorio actual. Para clonar el repositorio en su máquina local, ejecute el siguiente comando:

      • git clone https://github.com/your-github-username/your-github-repository-name.git

      Deberá sustituir your-github-username y your-github-repository-name para reflejar su nombre de usuario de Github y el nombre del repositorio previamente suministrado.

      Nota: Si habilitó la autenticación de dos factores (2FA) en Github.com, debe usar un token de acceso personal o una clave SSH en lugar de su contraseña cuando acceda a Github en la línea de comandos. En la página de ayuda de Github relacionada con 2FA se proporciona más información.

      Verá un resultado similar a lo siguiente:

      Output

      Cloning into 'your-github-repository-name'... remote: Enumerating objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3 Unpacking objects: 100% (3/3), done.

      Diríjase al repositorio ejecutando el siguiente comando:

      • cd your-github-repository-name

      En el repositorio se encuentra un solo archivo y una carpeta, ambos son archivos que Git utiliza para administrar el repositorio. Puede verificar esto con lo siguiente:

      Visualizará un resultado similar al siguiente:

      Output

      total 8 0 drwxr-xr-x 4 asciant staff 128 22 Apr 07:16 . 0 drwxr-xr-x 5 asciant staff 160 22 Apr 07:16 .. 0 drwxr-xr-x 13 asciant staff 416 22 Apr 07:16 .git 8 -rw-r--r-- 1 asciant staff 914 22 Apr 07:16 .gitignore

      Ahora que configuró un repositorio git funcional, creará el archivo shipit.js que administra su proceso de implementación.

      Paso 2: Integrar Shipit a un proyecto de Node.js

      En este paso, creará un proyecto de ejemplo de Node.js y luego agregará los paquetes de Shipit. En este tutorial se ofrece una aplicación de ejemplo: el servidor web Node.js que acepta solicitudes HTTP y responde con Hello World en texto simple. Para crear la aplicación, ejecute el siguiente comando:

      Añada el siguiente código de aplicación de ejemplo a hello.js (actualizando la variable APP_PRIVATE_IP_ADDRESS de modo que sea la dirección IP privada de su servidor app):

      hello.js

      var http = require('http');
      http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Hello Worldn');
      }).listen(8080, 'APP_PRIVATE_IP_ADDRESS');
      console.log('Server running at http://APP_PRIVATE_IP_ADDRESS:8080/');
      

      Ahora, cree el archivo package.json para su aplicación:

      Con este comando se crea un archivo package.json, que usará para configurar su aplicación Node.js. En el siguiente paso, agregará dependencias a este archivo con la interfaz de línea de comandos npm.

      Output

      Wrote to ~/hello-world/package.json: { "name": "hello-world", "version": "1.0.0", "description": "", "main": index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      A continuación, instale los paquetes npm necesarios con el siguiente comando:

      • npm install --save-dev shipit-cli shipit-deploy shipit-shared

      Aquí se utiliza el indicador --save-dev, ya que los paquetes de Shipit solo son necesarios en su equipo local. Visualizará un resultado similar al siguiente:

      Output

      + shipit-shared@4.4.2 + shipit-cli@4.2.0 + shipit-deploy@4.1.4 updated 4 packages and audited 21356 packages in 11.671s found 62 low severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details

      Con esto también se añadieron los tres paquetes a su archivo package.json como dependencias de desarrollo:

      package.json

      . . .
        "devDependencies": {
          "shipit-cli": "^4.2.0",
          "shipit-deploy": "^4.1.4",
          "shipit-shared": "^4.4.2"
        },
      . . .
      

      Ahora que configuró su entorno local, podrá proceder a preparar el servidor app remoto para las implementaciones basadas en Shipit.

      Paso 3: Preparar el servidor app remoto

      En este paso, usará ssh para establecer conexión con el servidor app e instalará la dependencia remota rsync. Rsync es una utilidad que permite transferir y sincronizar de manera eficiente archivos entre unidades de máquinas locales y en computadoras en red mediante la comparación de fechas de modificación y tamaños de archivos.

      En Shipit se utiliza rsync para transferir y sincronizar archivos entre su equipo local y el servidor app remoto. No emitirá comandos para rsync de forma directa; Shipit lo hará por usted.

      Nota: A través de Cómo configurar una aplicación de Node.js para la producción en CentOS 7, obtuvo dos servidores app y web. Estos comandos deben ejecutarse únicamente en app.

      Establezca conexión con su servidor app remoto a través de ssh:

      • ssh deployer@your_app_server_ip

      Instale rsync en su servidor ejecutando el siguiente comando:

      Confirme la instalación con lo siguiente:

      Verá una línea similar en el resultado de este comando:

      Output

      rsync version 3.1.2 protocol version 31 . . .

      Puede cerrar su sesión ssh escribiendo exit.

      Con rsync instalado y disponible en la línea de comandos, puede proceder con las tareas de implementación y su relación con los eventos.

      Paso 4: Configurar y ejecutar tareas de implementación

      Tanto los eventos como las tareas son componentes claves de las implementaciones de Shipit y es importante comprender la forma en que complementan la implementación de su aplicación. Los eventos desencadenados por Shipit representan puntos específicos en el ciclo de vida de la implementación. Sus tareas se ejecutarán en respuesta a estos eventos, según la secuencia del ciclo de vida de Shipit.

      Un ejemplo común de la utilidad de este sistema de tareas y eventos en una aplicación de Node.js se encuentra en la instalación de las dependencias de la aplicación (node_modules) en el servidor remoto. Más adelante en este paso, hará que en Shipit se escuche el evento updated (emitido después de que los archivos de la aplicación se transfieren) y ejecutará una tarea para instalar las dependencias de la aplicación (npm install) en el servidor remoto.

      Para escuchar los eventos y ejecutar tareas, Shipit necesita un archivo de configuración que contenga información sobre su servidor remoto (app) y registre las escuchas de eventos y los comandos que estas tareas ejecutarán. Este archivo reside en su máquina de desarrollo local, dentro del directorio de su aplicación de Node.js.

      Para comenzar, cree este archivo; incluyea información sobre su servidor remoto, las escuchas de eventos a las que desee suscribirse y algunas definiciones de sus tareas. Cree shipitfile.js dentro del directorio root de su aplicación, en su máquina local, ejecutando el siguiente comando:

      Ahora que creó un archivo, este debe completarse con la información inicial de entorno que Shipit requiere. Esta consiste principalmente en la ubicación de su repositorio Git remoto y, lo que es más importante, la dirección IP pública y la cuenta de usuario SSH de su servidor app.

      Añada esta configuración inicial y actualice las líneas resaltadas para que coincidan con su entorno:

      shipitfile.js

      module.exports = shipit => {
        require('shipit-deploy')(shipit);
        require('shipit-shared')(shipit);
      
        const appName = 'hello';
      
        shipit.initConfig({
          default: {
            deployTo: '/home/sammy/your-domain',
            repositoryUrl: 'https://git-provider.tld/YOUR_GIT_USERNAME/YOUR_GIT_REPO_NAME.git',
            keepReleases: 5,
            shared: {
              overwrite: true,
              dirs: ['node_modules']
            }
          },
          production: {
            servers: 'sammy@YOUR_APP_SERVER_PUBLIC_IP'
          }
        });
      
        const path = require('path');
        const ecosystemFilePath = path.join(
          shipit.config.deployTo,
          'shared',
          'ecosystem.config.js'
        );
      
        // Our listeners and tasks will go here
      
      };
      

      La actualización de las variables en su método shipit.initConfig proporciona a Shipit la configuración específica para su implementación. Estas representan lo siguiente para Shipit:

      • deployTo: es el directorio en el que Shipit implementará el código de su aplicación en el servidor remoto. En este caso, se utiliza la carpeta /home/ para un usuario no root con privilegios sudo (/home/sammy) debido a que es segura y evitará problemas con los permisos. El componente /your-domain es una convención de nomenclatura para distinguir la carpeta de otras dentro de la carpeta de inicio del usuario.
      • repositoryUrl: es la URL para el repositorio completo de Git; en Shipit se utilizará esta URL para garantizar que los archivos del proyecto se encuentren en sincronización antes de la implementación.
      • keepReleases: es el número de versiones que se deben mantener en el servidor remoto. release es una carpeta fechada que contiene los archivos de su aplicación en el momento de su lanzamiento. Puede ser útil para un rollback de una implementación.
      • shared: es la configuración que se corresponde con keepReleases y permite que los directorios sean shared entre las versiones. En este caso, tenemos una sola carpeta node_modules que comparten todas las versiones.
      • production: representa un servidor remoto para la implementación de su aplicación. En este caso, tiene un único servidor (app) al que asignó el nombre production y la configuración los servers: coincide con su public ip address y user de SSH. El nombre production se corresponde con el comando de implementación de Shipit utilizado al final de este tutorial (npx shipit server name deploy o, en su caso, npx shipit production deploy).

      Se puede encontrar más información sobre el objeto de configuración de implementación de Shipit en el repositorio Shipit de Github.

      Antes de continuar con la actualización de su shipitfile.js, revisaremos el siguiente fragmento de código de ejemplo para entender las tareas de Shipit:

      Example event listener

      shipit.on('deploy', () => { shipit.start('say-hello'); }); shipit.blTask('say-hello', async () => { shipit.local('echo "hello from your local computer"') });

      Esta es una tarea de ejemplo que utiliza el método shipit.on para suscribirse al evento deploy. Esta tarea se esperará que el ciclo de vida de Shipit emita el evento deploy; luego, cuando se reciba el evento, en la tarea se ejecutará el método shipit.start que indica a Shipit que aplique start a la tarea say-hello.

      En el método shipit.on se toman dos parámetros: el nombre del evento que se escuchará y la función de devolución de llamada que se ejecutará cuando se reciba el evento.

      En la declaración del método shipit.on, la tarea se define con el método shipit.blTask. Esto crea una nueva tarea Shipit que bloqueará otras tareas durante su ejecución (es una tarea sincrónica). En el método shipit.blTask también se toman dos parámetros: el nombre de la tarea que define y una función de devolución de llamada que se ejecutará una vez que shipit.start active la tarea.

      En la función de devolución de llamada de este ejemplo (say-hello), método shipit.local ejecuta un comando en la máquina local. En el comando local se emite “hello from your local computer” en el resultado de la terminal.

      Si quisiera ejecutar un comando en el servidor remoto, usaría el método shipit.remote. Los dos métodos, shipit.local y shipit.remote, proporcionan una API para emitir comandos de forma local o remota como parte de una implementación.

      Ahora, actualice shipitfile.js para incluir las escuchas de eventos a fin de suscribirse al ciclo de vida de Shipit con shipit.on. Añada las escuchas de eventos a su shipitfile.js, e insértelos conforme al marcador de posición de comentarios de la configuración inicial // Our tasks will go here:

      shipitfile.js

      . . .
        shipit.on('updated', () => {
          shipit.start('npm-install', 'copy-config');
        });
      
        shipit.on('published', () => {
          shipit.start('pm2-server');
        });
      

      Estos dos métodos escuchan los eventos updated y published que se emiten como parte del ciclo de vida de implementación de Shipit. Cuando se reciba el evento, cada uno iniciará tareas usando el método shipit.start, en un proceso similar al de la tarea de ejemplo.

      Ahora que programó las escuchas, agregará la tarea correspondiente. Añada la siguiente tarea a su shipitfile.js; insértelas después de las escuchas de eventos:

      shipitfile.js

      . . .
      shipit.blTask('copy-config', async () => {
      
      const fs = require('fs');
      
      const ecosystem = `
      module.exports = {
      apps: [
        {
          name: '${appName}',
          script: '${shipit.releasePath}/hello.js',
          watch: true,
          autorestart: true,
          restart_delay: 1000,
          env: {
            NODE_ENV: 'development'
          },
          env_production: {
            NODE_ENV: 'production'
          }
        }
      ]
      };`;
      
        fs.writeFileSync('ecosystem.config.js', ecosystem, function(err) {
          if (err) throw err;
          console.log('File created successfully.');
        });
      
        await shipit.copyToRemote('ecosystem.config.js', ecosystemFilePath);
      });
      

      Primero declara una tarea llamada copy-config. En esta tarea se crea un archivo local llamado ecosystem.config.js y luego se copia ese archivo a su servidor de app remoto. En PM2, este archivo se utiliza para administrar su aplicación de Node.js. Proporciona a PM2 la información necesaria sobre rutas de archivos para garantizar que se ejecuten los últimos archivos que implementó. Más adelante, en el proceso de compilación, creará una tarea que ejecuta PM2 con ecosystem.config.js como configuración.

      Si en su aplicación se necesitan variables de entorno (como una cadena de conexión de base de datos), puede declararlas de forma local, en env:, o en el servidor remoto, en env_production:, aplicando el mismo método con el que estableció la variable Node_ENV en estos objetos.

      Añada la siguiente tarea a su shipitfile.js después de la tarea copy-config:

      shipitfile.js

      . . .
      shipit.blTask('npm-install', async () => {
        shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
      });
      

      A continuación, declare una tarea llamada npm-install. En esta tarea se utiliza una terminal bash remota (a través de shipit.remote) para instalar las dependencias de la aplicación (paquetes npm).

      Añada la última tarea a su shipitfile.js después de la tarea npm-install:

      shipitfile.js

      . . .
      shipit.blTask('pm2-server', async () => {
        await shipit.remote(`pm2 delete -s ${appName} || :`);
        await shipit.remote(
          `pm2 start ${ecosystemFilePath} --env production --watch true`
        );
      });
      

      Por último, declare una tarea llamada pm2-server. En esta tarea, también se utiliza una terminal bash remota para primero evitar que PM2 administre su implementación anterior a través del comando delete y luego iniciar una nueva instancia de su servidor Node.js proporcionando el archivo ecosystem.config.js como una variable. También se notifica a PM2 que debe usar variables de entorno del bloque production en su configuración inicial y se solicita, también a PM2, que controle la aplicación y la reinicie si falla.

      El archivo shipitfile.js completo:

      shipitfile.js

      module.exports = shipit => {
        require('shipit-deploy')(shipit);
        require('shipit-shared')(shipit);
      
        const appName = 'hello';
      
        shipit.initConfig({
          default: {
            deployTo: '/home/deployer/example.com',
            repositoryUrl: 'https://git-provider.tld/YOUR_GIT_USERNAME/YOUR_GIT_REPO_NAME.git',
            keepReleases: 5,
            shared: {
              overwrite: true,
              dirs: ['node_modules']
            }
          },
          production: {
            servers: 'deployer@YOUR_APP_SERVER_PUBLIC_IP'
          }
        });
      
        const path = require('path');
        const ecosystemFilePath = path.join(
          shipit.config.deployTo,
          'shared',
          'ecosystem.config.js'
        );
      
        // Our listeners and tasks will go here
        shipit.on('updated', async () => {
          shipit.start('npm-install', 'copy-config');
        });
      
        shipit.on('published', async () => {
          shipit.start('pm2-server');
        });
      
        shipit.blTask('copy-config', async () => {
          const fs = require('fs');
          const ecosystem = `
      module.exports = {
        apps: [
          {
            name: '${appName}',
            script: '${shipit.releasePath}/hello.js',
            watch: true,
            autorestart: true,
            restart_delay: 1000,
            env: {
              NODE_ENV: 'development'
            },
            env_production: {
              NODE_ENV: 'production'
            }
          }
        ]
      };`;
      
          fs.writeFileSync('ecosystem.config.js', ecosystem, function(err) {
            if (err) throw err;
            console.log('File created successfully.');
          });
      
          await shipit.copyToRemote('ecosystem.config.js', ecosystemFilePath);
        });
      
        shipit.blTask('npm-install', async () => {
          shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
        });
      
        shipit.blTask('pm2-server', async () => {
          await shipit.remote(`pm2 delete -s ${appName} || :`);
          await shipit.remote(
            `pm2 start ${ecosystemFilePath} --env production --watch true`
          );
        });
      };
      

      Guarde y cierre el archivo cuando esté listo.

      Con su shipitfile.js configurado, las escuchas de eventos y las tareas asociadas completadas, puede proceder con la implementación en el servidor app.

      Paso 5: Implementar su aplicación

      En este paso, implementará su aplicación de forma remota y verificará que la implementación haya permitido la disponibilidad de su aplicación en Internet.

      Debido a que en Shipit se clonan los archivos de proyecto del repositorio remoto de Git, debe mover los archivos locales de su aplicación de Node.js de su máquina local a Github. Diríjase al directorio de la aplicación de su proyecto de Node.js (donde se ubican hello.js y shiptitfile.js) y ejecute el siguiente comando:

      Con el comando git status se muestra el estado del directorio de trabajo y el área de ensayos. Le permite ver los cambios que se prepararon o no, y los archivos que no se sometieron a seguimiento a través de Git. Sus archivos no se encuentran bajo seguimiento y aparecen en rojo en el resultado:

      Output

      On branch master Your branch is up to date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed) hello.js package-lock.json package.json shipitfile.js nothing added to commit but untracked files present (use "git add" to track)

      Puede añadir estos archivos a su repositorio con el siguiente comando:

      Con este comando no se produce ningún resultado, pero si ejecutara git status de nuevo los archivos se mostrarían en verde con una nota que señalaría la necesidad de confirmar cambios.

      Puede crear una confirmación ejecutando el siguiente comando:

      • git commit -m "Our first commit"

      En el resultado de este comando se proporciona información específica de Git sobre los archivos.

      Output

      [master c64ea03] Our first commit 4 files changed, 1948 insertions(+) create mode 100644 hello.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 shipitfile.js

      Lo único que queda por hacer ahora es enviar su confirmación al repositorio remoto para que Shipit realice una clonación a su servidor app durante la implementación. Ejecute el siguiente comando:

      En el resultado, se incluye información acerca de la sincronización con el repositorio remoto:

      Output

      Enumerating objects: 7, done. Counting objects: 100% (7/7), done. Delta compression using up to 8 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 15.27 KiB | 7.64 MiB/s, done. Total 6 (delta 0), reused 0 (delta 0) To github.com:Asciant/hello-world.git e274312..c64ea03 master -> master

      Para implementar su aplicación, ejecute el siguiente comando:

      • npx shipit production deploy

      En el resultado de este comando (que es demasiado largo para incluirlo en su totalidad) se proporcionan detalles sobre las tareas que se ejecutan y el resultado de la función específica. En el resultado que se observa a continuación para la tarea pm2-server se muestra que la aplicación Node.js se ha iniciado:

      Output

      Running 'deploy:init' task... Finished 'deploy:init' after 432 μs . . . Running 'pm2-server' task... Running "pm2 delete -s hello || :" on host "centos-ap-app.asciant.com". Running "pm2 start /home/deployer/example.com/shared/ecosystem.config.js --env production --watch true" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com [PM2][WARN] Node 4 is deprecated, please upgrade to use pm2 to have all features @centos-ap-app.asciant.com [PM2][WARN] Applications hello not running, starting... @centos-ap-app.asciant.com [PM2] App [hello] launched (1 instances) @centos-ap-app.asciant.com ┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────┬──────────┐ @centos-ap-app.asciant.com │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ @centos-ap-app.asciant.com ├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────┼──────────┤ @centos-ap-app.asciant.com │ hello │ 0 │ 1.0.0 │ fork │ 4177 │ online │ 0 │ 0s │ 0% │ 4.5 MB │ deployer │ enabled │ @centos-ap-app.asciant.com └──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────┴──────────┘ @centos-ap-app.asciant.com Use `pm2 show <id|name>` to get more details about an app Finished 'pm2-server' after 5.27 s Running 'deploy:clean' task... Keeping "5" last releases, cleaning others Running "(ls -rd /home/deployer/example.com/releases/*|head -n 5;ls -d /home/deployer/example.com/releases/*)|sort|uniq -u|xargs rm -rf" on host "centos-ap-app.asciant.com". Finished 'deploy:clean' after 1.81 s Running 'deploy:finish' task... Finished 'deploy:finish' after 222 μs Finished 'deploy' [ deploy:init, deploy:fetch, deploy:update, deploy:publish, deploy:clean, deploy:finish ]

      Para ver su aplicación como la vería un usuario, puede ingresar la URL de su sitio web your-domain en su navegador a fin de acceder a su servidor web. Esto proporcionará la aplicación de Node.js, a través de un proxy inverso, en el servidor app en el que se implementaron sus archivos.

      Verá un saludo Hello World.

      Nota: Después de la primera implementación, en su repositorio de Git se hará un seguimiento de un archivo nuevo llamado ecosystem.config.js. Debido a que este archivo se reconstruye en cada implementación y puede contener secretos de la aplicación compilados, se debe añadir al archivo .gitignore en el directorio root de la aplicación de su máquina local antes de su próxima confirmación de git.

      .gitignore

      . . .
      # ecosystem.config
      ecosystem.config.js
      

      Implementó su aplicación Node.js en el servidor app, que hace referencia a su nueva implementación. Con todo configurado y en funcionamiento, puede proceder con la supervisión de los procesos de su aplicación.

      Paso 6: Controlar su aplicación

      PM2 es una excelente herramienta para administrar sus procesos remotos, pero también incluye funciones para controlar el rendimiento de estos procesos de aplicación.

      Establezca conexión con su servidor app remoto mediante SSH con el siguiente comando:

      • ssh deployer@your_app_server_ip

      Para obtener información específica relacionada con los procesos administrados de PM2, ejecute lo siguiente:

      Verá un resultado similar a lo siguiente:

      Output

      ┌─────────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬──────┬───────────┬──────────┬──────────┐ │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├─────────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼──────┼───────────┼──────────┼──────────┤ │ hello │ 0 │ 0.0.1 │ fork │ 3212 │ online │ 0 │ 62m │ 0.3% │ 45.2 MB │ deployer │ enabled │ └─────────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴──────┴───────────┴──────────┴──────────┘

      Verá un resumen de la información recopilada por PM2. Para ver información detallada, puede ejecutar lo siguiente:

      En el resultado, se amplía la información del resumen proporcionada por el comando pm2 list. También proporciona información sobre varios comandos suplementarios y también la ubicación de los archivos de registro:

      Output

      Describing process with id 0 - name hello ┌───────────────────┬─────────────────────────────────────────────────────────────┐ │ status │ online │ │ name │ hello │ │ version │ 1.0.0 │ │ restarts │ 0 │ │ uptime │ 82s │ │ script path │ /home/deployer/example.com/releases/20190531213027/hello.js │ │ script args │ N/A │ │ error log path │ /home/deployer/.pm2/logs/hello-error.log │ │ out log path │ /home/deployer/.pm2/logs/hello-out.log │ │ pid path │ /home/deployer/.pm2/pids/hello-0.pid │ │ interpreter │ node │ │ interpreter args │ N/A │ │ script id │ 0 │ │ exec cwd │ /home/deployer │ │ exec mode │ fork_mode │ │ node.js version │ 4.2.3 │ │ node env │ production │ │ watch & reload │ ✔ │ │ unstable restarts │ 0 │ │ created at │ 2019-05-31T21:30:48.334Z │ └───────────────────┴─────────────────────────────────────────────────────────────┘ Revision control metadata ┌──────────────────┬────────────────────────────────────────────────────┐ │ revision control │ git │ │ remote url │ N/A │ │ repository root │ /home/deployer/example.com/releases/20190531213027 │ │ last update │ 2019-05-31T21:30:48.559Z │ │ revision │ 62fba7c8c61c7769022484d0bfa46e756fac8099 │ │ comment │ Our first commit │ │ branch │ master │ └──────────────────┴────────────────────────────────────────────────────┘ Divergent env variables from local env ┌───────────────────────────┬───────────────────────────────────────┐ │ XDG_SESSION_ID │ 15 │ │ HOSTNAME │ N/A │ │ SELINUX_ROLE_REQUESTED │ │ │ TERM │ N/A │ │ HISTSIZE │ N/A │ │ SSH_CLIENT │ 44.222.77.111 58545 22 │ │ SELINUX_USE_CURRENT_RANGE │ │ │ SSH_TTY │ N/A │ │ LS_COLORS │ N/A │ │ MAIL │ /var/mail/deployer │ │ PATH │ /usr/local/bin:/usr/bin │ │ SELINUX_LEVEL_REQUESTED │ │ │ HISTCONTROL │ N/A │ │ SSH_CONNECTION │ 44.222.77.111 58545 209.97.167.252 22 │ └───────────────────────────┴───────────────────────────────────────┘ . . .

      Además, PM2 proporciona una herramienta de supervisión en terminal a la que es posible acceder con lo siguiente:

      Como resultado de este comando se obtiene un panel interactivo, en el cual pm2 proporciona registros, métricas, metadatos e información sobre procesos en tiempo real. Este panel puede ser útil para controlar los recursos y registros de errores:

      Output

      ┌─ Process list ────────────────┐┌─ Global Logs ─────────────────────────────────────────────────────────────┐ │[ 0] hello Mem: 22 MB ││ │ │ ││ │ │ ││ │ └───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘ ┌─ Custom metrics (http://bit.l─┐┌─ Metadata ────────────────────────────────────────────────────────────────┐ │ Heap Size 10.73 ││ App Name hello │ │ Heap Usage 66.14 ││ Version N/A │ │ Used Heap Size 7.10 ││ Restarts 0 │ │ Active requests 0 ││ Uptime 55s │ │ Active handles 4 ││ Script path /home/asciant/hello.js │ │ Event Loop Latency 0.70 ││ Script args N/A │ │ Event Loop Latency p95 ││ Interpreter node │ │ ││ Interpreter args N/A │ └───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘

      Al comprender la forma en la que puede supervisar sus procesos con PM2, ahora puede considerar la forma en la que Shipit puede asistir en la reversión a una implementación funcional anterior.

      Finalice su sesión ssh en su servidor app ejecutando exit.

      Paso 7: Revertir una implementación defectuosa

      En las implementaciones, de tanto en tanto se exhiben errores imprevistos o problemas que pueden causar fallas en su sitio. Los desarrolladores y los encargados de mantenimiento de Shipit previeron esto y proporcionaron la capacidad de restablecer la implementación (funcional) anterior de su aplicación.

      Para garantizar que su configuración de PM2 persista, añada otra escucha de eventos a shipitfile.js en el evento rollback.

      shipitfile.js

      . . .
        shipit.on('rollback', () => {
          shipit.start('npm-install', 'copy-config');
        });
      

      Debe añadir una escucha al evento rollback para ejecutar sus tareas npm-install y copy-config. Esto se requiere porque, a diferencia del evento published, el evento updated no se ejecuta a través del ciclo de vida de Shipit cuando se revierte una implementación. Añadir esta escucha garantiza que su administrador de procesos PM2 se oriente hacia la implementación más reciente, incluso en caso de una reversión.

      Este proceso es similar a la implementación, con un pequeño cambio de comando. Para intentar restablecer a una implementación anterior, puede ejecutar lo siguiente:

      • npx shipit production rollback

      Al igual que el comando deploy, rollback proporciona detalles sobre el proceso de reversión y las tareas que se ejecutan:

      Output

      Running 'rollback:init' task... Get current release dirname. Running "if [ -h /home/deployer/example.com/current ]; then readlink /home/deployer/example.com/current; fi" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com releases/20190531213719 Current release dirname : 20190531213719. Getting dist releases. Running "ls -r1 /home/deployer/example.com/releases" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com 20190531213719 @centos-ap-app.asciant.com 20190531213519 @centos-ap-app.asciant.com 20190531213027 Dist releases : ["20190531213719","20190531213519","20190531213027"]. Will rollback to 20190531213519. Finished 'rollback:init' after 3.96 s Running 'deploy:publish' task... Publishing release "/home/deployer/example.com/releases/20190531213519" Running "cd /home/deployer/example.com && if [ -d current ] && [ ! -L current ]; then echo "ERR: could not make symlink"; else ln -nfs releases/20190531213519 current_tmp && mv -fT current_tmp current; fi" on host "centos-ap-app.asciant.com". Release published. Finished 'deploy:publish' after 1.8 s Running 'pm2-server' task... Running "pm2 delete -s hello || :" on host "centos-ap-app.asciant.com". Running "pm2 start /home/deployer/example.com/shared/ecosystem.config.js --env production --watch true" on host "centos-ap-app.asciant.com". @centos-ap-app.asciant.com [PM2][WARN] Node 4 is deprecated, please upgrade to use pm2 to have all features @centos-ap-app.asciant.com [PM2][WARN] Applications hello not running, starting... @centos-ap-app.asciant.com [PM2] App [hello] launched (1 instances) @centos-ap-app.asciant.com ┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────┬──────────┐ @centos-ap-app.asciant.com │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ @centos-ap-app.asciant.com ├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────┼──────────┤ @centos-ap-app.asciant.com │ hello │ 0 │ 1.0.0 │ fork │ 4289 │ online │ 0 │ 0s │ 0% │ 4.5 MB │ deployer │ enabled │ @centos-ap-app.asciant.com └──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────┴──────────┘ @centos-ap-app.asciant.com Use `pm2 show <id|name>` to get more details about an app Finished 'pm2-server' after 5.55 s Running 'deploy:clean' task... Keeping "5" last releases, cleaning others Running "(ls -rd /home/deployer/example.com/releases/*|head -n 5;ls -d /home/deployer/example.com/releases/*)|sort|uniq -u|xargs rm -rf" on host "centos-ap-app.asciant.com". Finished 'deploy:clean' after 1.82 s Running 'rollback:finish' task... Finished 'rollback:finish' after 615 μs Finished 'rollback' [ rollback:init, deploy:publish, deploy:clean, rollback:finish ]

      Configuró Shipit para mantener 5 versiones a través del ajuste keepReleases: 5 en shipitfile.js. Shipit realiza un seguimiento interno de estas versiones para garantizar que la reversión sea posible cuando se necesite. Shipit también proporciona una alternativa práctica para identificar las versiones creando un directorio con el nombre de una marca de tiempo (AAAAMMDDHHmmss; por ejemplo, /home/deployer/your-domain/releases/20190420210548).

      Si desea personalizar aún más el proceso de reversión, puede escuchar eventos específicos de la operación de reversión. Luego, puede utilizarlos para ejecutar tareas que complementarán su reversión. Puede consultar la lista de eventos proporcionada en el desglose del ciclo de vida de Shipit, y configurar las tareas y escuchas dentro de su shipitfile.js.

      La capacidad de reversión implica que siempre puede proporcionar a sus usuarios una versión funcional de su aplicación, incluso si en una implementación se producen errores o problemas inesperados.

      Conclusión

      A lo largo de este tutorial, configuró un flujo de trabajo que le permite crear una alternativa sumamente personalizable a las plataformas como servicio, todo ello desde algunos servidores. Este flujo de trabajo permite personalizar la implementación y la configuración, controlar procesos con PM2, escalar y agregar servicios, o contar con servidores o entornos adicionales en la implementación cuando sea necesario.

      Si está interesado en continuar desarrollando sus aptitudes para Node.js, consulte el contenido de Node.js de DigtalOcean y la serie Cómo producir código en Node.js.



      Source link