One place for hosting & domains

      aplicativos

      Como servir aplicativos Flask com o Gunicorn e o Nginx no Ubuntu 20.04


      Introdução

      Neste guia, você construirá um aplicativo Python usando o microframework Flask no Ubuntu 20.04. A maior parte deste artigo será sobre como configurar o servidor do aplicativo Gunicorn, como iniciar o aplicativo e configurar o Nginx para atuar como um proxy reverso no front-end.

      Pré-requisitos

      Antes de iniciar este guia, você deve ter:

      • Um servidor com o Ubuntu 20.04 instalado e um usuário não root com privilégios sudo. Siga nosso guia de configuração inicial do servidor para orientação.
      • O Nginx instalado, seguindo os Passos 1 e 2 de Como instalar o Nginx no Ubuntu 20.04.
      • Um nome de domínio configurado para apontar para o seu servidor. Você pode comprar um no Namecheap ou obter um de graça no Freenom. Você pode aprender como apontar domínios para o DigitalOcean seguindo a relevante documentação para domínios e DNS. Certifique-se de criar os seguintes registros DNS:

        • Um registro A com your_domain apontando para o endereço IP público do seu servidor.
        • Um registro A com o www.your_domain apontando para o endereço de IP público do seu servidor.
      • Familiarize-se com a especificação do WSGI, que o servidor do Gunicorn usará para se comunicar com seu aplicativo Flask. Esta discussão aborda mais detalhadamente o WSGI.

      Passo 1 — Instalando os componentes dos repositórios do Ubuntu

      Nosso primeiro passo será instalar todas as partes que precisamos dos repositórios do Ubuntu. Isso inclui o pip, o gerenciador de pacotes Python que irá gerenciar nossos componentes Python. Também vamos obter os arquivos de desenvolvimento do Python necessários para construir alguns dos componentes do Gunicorn.

      Primeiramente, vamos atualizar o índice local de pacotes e instalar os pacotes que irão nos permitir construir nosso ambiente Python. Estes incluem o python3-pip, junto com alguns outros pacotes e ferramentas de desenvolvimento necessários para um ambiente de programação robusto:

      • sudo apt update
      • sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

      Com esses pacotes instalados, vamos seguir em frente para criar um ambiente virtual para nosso projeto.

      Passo 2 — Criando um Ambiente Virtual em Python

      Em seguida, vamos configurar um ambiente virtual para isolar nosso aplicativo Flask dos outros arquivos Python no sistema.

      Inicie instalando o pacote python3-venv, que instalará o módulo venv:

      • sudo apt install python3-venv

      Em seguida, vamos fazer um diretório pai para nosso projeto Flask. Acesse o diretório após criá-lo:

      • mkdir ~/myproject
      • cd ~/myproject

      Crie um ambiente virtual para armazenar os requisitos Python do projeto Flask digitando:

      • python3 -m venv myprojectenv

      Isso instalará uma cópia local do Python e do pip em um diretório chamado myprojectenv dentro do diretório do seu projeto.

      Antes de instalar aplicativos no ambiente virtual, você precisa ativá-lo. Faça isso digitando:

      • source myprojectenv/bin/activate

      Seu prompt mudará para indicar que você agora está operando no ambiente virtual. Ele se parecerá com isso: (myprojectenv)user@host:~/myproject$.

      Passo 3 — Configurando um aplicativo Flask

      Agora que você está no seu ambiente virtual, instale o Flask e o Gunicorn e comece a projetar seu aplicativo.

      Primeiramente, vamos instalar o wheel com a instância local do pip para garantir que nossos pacotes sejam instalados mesmo se estiverem faltando arquivos wheel:

      Nota


      Independentemente da versão do Python que você estiver usando, quando o ambiente virtual for ativado, você deve usar o comando pip (não o pip3).

      Em seguida, vamos instalar o Flask e o Gunicorn:

      • pip install gunicorn flask

      Criando um app de exemplo

      Agora que você tem o Flask disponível, você pode criar um aplicativo simples. O Flask é um microframework. Ele não inclui muitas das ferramentas que os frameworks mais completos talvez tenham. Ele existe, principalmente, como um módulo que você pode importar para seus projetos para ajudá-lo na inicialização de um aplicativo Web.

      Embora o seu aplicativo possa ser mais complexo, vamos criar nosso app Flask em um único arquivo, chamado myproject.py:

      • nano ~/myproject/myproject.py

      O código do aplicativo ficará neste arquivo. Ele importará o Flask e instanciará um objeto Flask. Você pode usar isto para definir as funções que devem ser executadas quando uma rota específica for solicitada:

      ~/myproject/myproject.py

      from flask import Flask
      app = Flask(__name__)
      
      @app.route("/")
      def hello():
          return "<h1 style="color:blue">Hello There!</h1>"
      
      if __name__ == "__main__":
          app.run(host="0.0.0.0")
      

      Isso define basicamente qual conteúdo apresentar quando o domínio raiz for acessado. Salve e feche o arquivo quando você terminar.

      Se você seguiu o guia de configuração inicial do servidor, você deverá ter um firewall UFW ativado. Para testar o aplicativo, será necessário permitir o acesso à porta 5000:

      Agora é possível testar seu app Flask digitando:

      Você verá um resultado como o seguinte, incluindo um aviso útil lembrando para não usar essa configuração de servidor na produção:

      Output

      * Serving Flask app "myproject" (lazy loading) * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: off * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

      Visite o endereço IP do seu servidor seguido de :5000 no seu navegador Web:

      http://your_server_ip:5000
      

      Você deve ver algo como isto:

      Flask sample app

      Quando terminar, tecle CTRL-C na janela do seu terminal para parar o servidor de desenvolvimento Flask.

      Criando o ponto de entrada da WSGI

      Em seguida, vamos criar um arquivo que servirá como o ponto de entrada para nosso aplicativo. Isso dirá ao nosso servidor do Gunicorn como interagir com o aplicativo.

      Vamos chamar o arquivo de wsgi.py:

      Neste arquivo, vamos importar a instância Flask do nosso aplicativo e então executá-lo:

      ~/myproject/wsgi.py

      from myproject import app
      
      if __name__ == "__main__":
          app.run()
      

      Salve e feche o arquivo quando você terminar.

      Passo 4 — Configurando o Gunicorn

      Seu aplicativo agora está gravado com um ponto de entrada estabelecido. Podemos agora seguir em frente para configurar o Gunicorn.

      Antes de continuar, devemos verificar se o Gunicorn pode atender o aplicativo corretamente.

      Podemos fazer essa verificação simplesmente passando o nome do nosso ponto de entrada para o Gunicorn. Criamos esse ponto de entrada como o nome do módulo (menos a extensão .py) mais o nome do objeto callable dentro do aplicativo. No nosso caso, trata-se do wsgi:app.

      Também vamos especificar a interface e a porta a vincular, de modo que o aplicativo seja iniciado em uma interface disponível publicamente:

      • cd ~/myproject
      • gunicorn --bind 0.0.0.0:5000 wsgi:app

      Deverá ver um resultado como o seguinte:

      Output

      [2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4 [2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419) [2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync [2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421

      Visite o endereço IP do seu servidor com :5000 anexado ao final no seu navegador Web novamente:

      http://your_server_ip:5000
      

      Você deve ver o resultado do seu aplicativo:

      Flask sample app

      Quando você tiver confirmado que ele está funcionando corretamente, pressione CTRL-C na janela do seu terminal.

      Acabamos agora o nosso ambiente virtual, para que possamos desativá-lo:

      Agora, qualquer comando Python voltará a usar o ambiente do sistema Python.

      Em seguida, vamos criar o arquivo da unidade de serviço systemd. Criar um arquivo de unidade systemd permitirá que o sistema init do Ubuntu inicie automaticamente o Gunicorn e atenda o aplicativo Flask sempre que o servidor inicializar.

      Crie um arquivo de unidade que termine com .service dentro do diretório /etc/systemd/system para começar:

      • sudo nano /etc/systemd/system/myproject.service

      Ali, vamos começar com a seção [Unit], que é usada para especificar os metadados e dependências. Vamos colocar uma descrição do nosso serviço aqui e dizer ao sistema init para iniciar isso somente após o objetivo da rede ter sido alcançado:

      /etc/systemd/system/myproject.service

      [Unit]
      Description=Gunicorn instance to serve myproject
      After=network.target
      

      Em seguida, vamos abrir a seção [Service]. Isso especificará o usuário e o grupo sob o qual que queremos que o processo seja executado. Vamos dar à nossa conta de usuário regular a propriedade sobre o processo, uma vez que ela possui todos os arquivos relevantes. Vamos também dar a propriedade sobre o grupo para o grupo www-data, de modo que o Nginx possa se comunicar facilmente com os processos do Gunicorn. Lembre-se de substituir o nome de usuário abaixo pelo seu nome de usuário:

      /etc/systemd/system/myproject.service

      [Unit]
      Description=Gunicorn instance to serve myproject
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      

      Em seguida, vamos mapear o diretório de trabalho e definir a variável de ambiente PATH para que o sistema init saiba que os executáveis do processo estão localizados dentro do nosso ambiente virtual. Vamos também especificar o comando para iniciar o serviço. Este comando fará o seguinte:

      • Iniciar três processos de trabalho (embora deva ajustar isso conforme necessário)
      • Criar e vincular a um arquivo de socket Unix, myproject.sock, dentro de nosso diretório de projeto. Vamos definir um valor de umask de 007 para que o arquivo socket seja criado dando acesso ao proprietário e ao grupo, ao mesmo tempo que restringe outros acessos
      • Especificar o nome do arquivo de ponto de entrada da WSGI, junto com o objeto callable do Python dentro daquele arquivo (wsgi:app)

      O systemd exige que seja dado o caminho completo para o executável do Gunicorn, que está instalado dentro do nosso ambiente virtual.

      Lembre-se de substituir o nome de usuário e os caminhos do projeto por seus próprios dados:

      /etc/systemd/system/myproject.service

      [Unit]
      Description=Gunicorn instance to serve myproject
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myproject
      Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
      ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
      

      Finalmente, vamos adicionar uma seção [Install]. Isso dirá ao systemd ao que vincular este serviço se nós o habilitarmos para iniciar na inicialização. Queremos que este serviço comece quando o sistema regular de vários usuários estiver funcionando:

      /etc/systemd/system/myproject.service

      [Unit]
      Description=Gunicorn instance to serve myproject
      After=network.target
      
      [Service]
      User=sammy
      Group=www-data
      WorkingDirectory=/home/sammy/myproject
      Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
      ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
      
      [Install]
      WantedBy=multi-user.target
      

      Com isso, nosso arquivo de serviço systemd está completo. Salve e feche-o agora.

      Podemos agora iniciar o serviço Gunicorn que criamos e habilitá-lo para que ele seja iniciado na inicialização:

      • sudo systemctl start myproject
      • sudo systemctl enable myproject

      Vamos verificar o status:

      • sudo systemctl status myproject

      Você deve ver um resultado como este:

      Output

      ● myproject.service - Gunicorn instance to serve myproject Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-05-20 14:15:18 UTC; 1s ago Main PID: 46430 (gunicorn) Tasks: 4 (limit: 2344) Memory: 51.3M CGroup: /system.slice/myproject.service ├─46430 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app ├─46449 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app ├─46450 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app └─46451 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app

      Se encontrar erros, certifique-se de resolvê-los antes de continuar com o tutorial.

      Passo 5 — Configurando o Nginx para solicitações de proxy

      Nosso servidor do aplicativo Gunicorn deve estar funcionando agora, esperando pedidos no arquivo de socket no diretório do projeto. Vamos agora configurar o Nginx para passar pedidos Web para aquele socket, fazendo algumas pequenas adições ao seu arquivo de configuração.

      Comece criando um novo arquivo de configuração do bloco do servidor no diretório sites-available do Nginx. Vamos chamá-lo de myproject para mantê-lo alinhado com o resto do guia:

      • sudo nano /etc/nginx/sites-available/myproject

      Abra um bloco de servidor e diga ao Nginx para escutar na porta padrão 80. Vamos também dizer a ele para usar este bloco para pedidos para o nome de domínio do nosso servidor:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name your_domain www.your_domain;
      }
      

      Em seguida, vamos adicionar um bloco de localização que corresponda a cada pedido. Dentro deste bloco, vamos incluir o arquivo proxy_params que especifica alguns parâmetros gerais de proxy que precisam ser configurados. Vamos então passar os pedidos para o socket que definimos usando a diretriz proxy_pass:

      /etc/nginx/sites-available/myproject

      server {
          listen 80;
          server_name your_domain www.your_domain;
      
          location / {
              include proxy_params;
              proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
          }
      }
      

      Salve e feche o arquivo quando terminar.

      Para habilitar a configuração do bloco do servidor Nginx que acabou de criar, vincule o arquivo ao diretório sites-enabled:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

      Com o arquivo naquele diretório, você pode testar quanto a erros de sintaxe:

      Se retornar sem indicar quaisquer problemas, reinicie o processo Nginx para ler a nova configuração:

      • sudo systemctl restart nginx

      Finalmente, vamos ajustar o firewall novamente. Já não precisamos de acesso através da porta 5000, então podemos remover essa regra. Podemos então conceder acesso total ao servidor Nginx:

      • sudo ufw delete allow 5000
      • sudo ufw allow 'Nginx Full'

      Agora, você consegue navegar até o nome de domínio do seu servidor no seu navegador Web:

      http://your_domain
      

      Você deve ver o resultado do seu aplicativo:

      Flask sample app

      Caso encontre quaisquer erros, tente verificar o seguinte:

      • sudo less /var/log/nginx/error.log: verifica os registros de erros do Nginx.
      • sudo less /var/log/nginx/access.log: verifica os registros de acesso do Nginx.
      • sudo journalctl -u nginx: verifica os registros de processo do Nginx.
      • sudo journalctl -u myproject: verifica os registros do Gunicorn do seu app Flask.

      Passo 6 — Protegendo o aplicativo

      Para garantir que o tráfego para seu servidor permaneça protegido, vamos obter um certificado SSL para seu domínio. Há várias maneiras de fazer isso, incluindo a obtenção de um certificado gratuito do Let’s Encrypt, gerando um certificado autoassinado ou comprando algum de outro provedor e configurando o Nginx para usá-lo, seguindo os Passos 2 a 6 de Como criar um certificado SSL autoassinado para o Nginx no Ubuntu 20.04. Vamos escolher a opção um por questão de conveniência.

      Instale o pacote Nginx do Certbot com o apt:

      • sudo apt install python3-certbot-nginx

      O Certbot oferece várias maneiras de obter certificados SSL através de plug-ins. O plug-in Nginx cuidará da reconfiguração do Nginx e recarregará a configuração sempre que necessário. Para usar este plug-in, digite o seguinte:

      • sudo certbot --nginx -d your_domain -d www.your_domain

      Esse comando executa o certbot com o plug-in --nginx, usando -d para especificar os nomes para os quais desejamos um certificado válido.

      Se essa é a primeira vez que você executa o certbot, você será solicitado a informar um endereço de e-mail e concordar com os termos de serviço. Após fazer isso, o certbot se comunicará com o servidor da Let’s Encrypt, executando posteriormente um desafio para verificar se você controla o domínio para o qual está solicitando um certificado.

      Se tudo correr bem, o certbot perguntará como você quer definir suas configurações de HTTPS:

      Output

      Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access. ------------------------------------------------------------------------------- 1: No redirect - Make no further changes to the webserver configuration. 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for new sites, or if you're confident your site works on HTTPS. You can undo this change by editing your web server's configuration. ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

      Select your choice then hit ​​​ENTER​​​​​. A configuração será atualizada e o Nginx recarregará para aplicar as novas configurações. O certbot será encerrado com uma mensagem informando que o processo foi concluído e onde os certificados estão armazenados:

      Output

      IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/your_domain/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/your_domain/privkey.pem Your cert will expire on 2020-08-18. To obtain a new or tweaked version of this certificate in the future, simply run certbot again with the "certonly" option. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le

      Se seguiu as instruções de instalação do Nginx nos pré-requisitos, a permissão do perfil HTTP redundante não é mais necessária:

      • sudo ufw delete allow 'Nginx HTTP'

      Para verificar a configuração, navegue novamente para seu domínio, usando https://:

      https://your_domain
      

      Você deve ver novamente o resultado do seu aplicativo, junto com o indicador de segurança do seu navegador, o qual deve indicar que o site está protegido.

      Conclusão

      Neste guia, você criou e protegeu um aplicativo Flask simples em um ambiente virtual Python. Você criou um ponto de entrada da WSGI para que qualquer servidor de aplicativo compatível com a WSGI possa interagir com ela, e então configurou o servidor de app Gunicorn para fornecer essa função. Depois, criou um arquivo de serviço systemd para iniciar automaticamente o servidor do aplicativo na inicialização. Você também criou um bloco de servidor Nginx que passa o tráfego Web do cliente para o servidor do aplicativo – retransmitindo pedidos externos – e protegeu o tráfego para seu servidor com o Let’s Encrypt.

      O Flask é um framework muito simples – mas extremamente flexível, destinado a fornecer funcionalidade a seus aplicativos sem ser restritivo demais em termos de estrutura e design. Você pode usar a pilha geral descrita neste guia para atender os aplicativos flask que projetar.



      Source link

      Compilando aplicativos em Go para diferentes Sistemas Operacionais e Arquiteturas


      No desenvolvimento de software, é importante considerar o sistema operacional e a arquitetura do processador subjacente para os quais você quer compilar seu binário. Como geralmente é lento ou impossível executar um binário em uma plataforma de SO/arquitetura, é uma prática comum compilar o seu binário final para muitas plataformas diferentes a fim de maximizar o público do seu programa. No entanto, isso pode ser difícil quando a plataforma que estiver usando para o desenvolvimento for diferente da plataforma na qual deseja implantar o seu programa. No passado, por exemplo, o desenvolvimento de um programa em Windows e a implantação em uma máquina Linux ou macOS envolveria a configuração de máquinas montadas para cada um dos ambientes para os quais quisesse binários. Você também precisaria manter suas ferramentas em sincronia, além de outras considerações que adicionariam custos e dificultariam a realização de testes e a distribuição.

      A linguagem Go resolve esse problema, criando o suporte para várias plataformas diretamente na ferramenta go build, assim como em todo o resto da cadeia de ferramentas do Go. Ao usar variáveis de ambiente e build tags (sinalizadores de compilação), você consegue controlar para qual SO e arquitetura o seu binário final será compilado, além de unir um fluxo de trabalho que pode alternar rapidamente a inclusão do código dependente de plataforma sem alterar sua base de códigos.

      Neste tutorial, você irá juntar um aplicativo exemplo que une strings a partir de um filepath, criar e incluir seletivamente snippets dependentes de plataforma e compilar binários para vários sistemas operacionais e arquiteturas de sistema em seu próprio sistema, mostrando a você como usar essa poderosa capacidade da linguagem de programação Go.

      Pré-requisitos

      Para seguir o exemplo neste artigo, será necessário:

      Possíveis plataformas para o GOOS e GOARCH

      Antes de mostrar como controlar o processo de compilação para compilar os binários para plataformas diferentes, vamos inspecionar primeiro para quais tipos de plataformas a linguagem Go consegue compilar e de que maneira a Go referencia tais plataformas utilizando as variáveis de ambiente GOOS e GOARCH.

      As ferramentas da Go têm um comando que pode imprimir uma lista das possíveis plataformas nais quais a Go consegue compilar. Essa lista pode mudar com cada nova versão da Go. Assim, as combinações discutidas aqui podem não ser as mesmas em outra versão da linguagem Go. No momento em que este tutorial é escrito, a versão da Go é a 1.13.

      Para encontrar essa lista com as possíveis plataformas, execute o seguinte:

      Você receberá um resultado similar ao seguinte:

      Output

      aix/ppc64 freebsd/amd64 linux/mipsle openbsd/386 android/386 freebsd/arm linux/ppc64 openbsd/amd64 android/amd64 illumos/amd64 linux/ppc64le openbsd/arm android/arm js/wasm linux/s390x openbsd/arm64 android/arm64 linux/386 nacl/386 plan9/386 darwin/386 linux/amd64 nacl/amd64p32 plan9/amd64 darwin/amd64 linux/arm nacl/arm plan9/arm darwin/arm linux/arm64 netbsd/386 solaris/amd64 darwin/arm64 linux/mips netbsd/amd64 windows/386 dragonfly/amd64 linux/mips64 netbsd/arm windows/amd64 freebsd/386 linux/mips64le netbsd/arm64 windows/arm

      Esse resultado é um conjunto de pares de chave-valor, por uma /. A primeira parte da combinação, antes da /, é o sistema operacional. Em Go, esses sistemas operacionais são valores possíveis para a variável de ambiente GOOS, pronuncia-se “goose”, que significa Go Operating System (Sistema Operacional Go). A segunda parte, após a /, é a arquitetura . Como antes, todos esses valores são possíveis para uma variável de ambiente: GOARCH. A pronúncia dessa variável é “gore-ch”, e significa Go Architecture (Arquitetura Go).

      Vamos detalhar uma dessas combinações para entender o que ela significa e como ela funciona, usando o linux/386 como exemplo. O par chave-valor começa com a variável GOOS, que, neste exemplo, seria o linux, referindo-se ao SO do Linux. Aqui, a GOARCH seria o 386, que significa microprocessador Intel 80386.

      Existem muitas plataformas disponíveis com o comando go build, mas na maior parte das vezes você vai acabar usando linux, windows ou darwin como um valor para o GOOS. Dentre elas, temos as três grandes plataformas de OS, quais sejam: Linux, Windows e macOS, o qual é baseado no sistema operacional Darwin e, por isso, é chamado de darwin. No entanto, o Go também pode incluir plataformas menos comuns, como a nacl, que representa o Cliente nativo do Google.

      Quando você executa um comando como o go build, o Go usa a plataforma atual do GOOS e da GOARCH para determinar como compilar o binário. Para descobrir a qual combinação sua plataforma corresponde, utilize o comando go env e passe o GOOS e a GOARCH como argumentos:

      Ao testar esse exemplo, executamos este comando no macOS de uma máquina com uma arquitetura AMD64. Dessa forma, iremos receber o seguinte resultado:

      Output

      darwin amd64

      Aqui, o resultado do comando nos diz que nosso sistema tem o GOOS=darwin e o GOARCH=amd64.

      Agora, você sabe qual deles é o GOOS e qual é o GOARCH no Go, bem como seus possíveis valores. Em seguida, você precisará de um programa para usar como exemplo de como usar essas variáveis de ambiente e os build tags para compilar binários em outras plataformas.

      Antes de começar a compilar binários para outras plataformas, vamos criar um programa de exemplo. Uma boa amostra para este propósito é a função Join no pacote path/filepath na biblioteca Go padrão. Essa função pega uma quantidade de strings e retorna uma string que é unida ao separador de caminho de arquivo correto.

      Este é um bom programa de exemplo porque a operação do programa depende do SO em que ele estiver executando. No Windows, o separador de caminho é uma barra invertida, , enquanto os sistemas baseados em Unix usam uma barra, /.

      Vamos começar a compilar um aplicativo que utilize o filepath.Join() e, mais tarde, você vai escrever sua própria implementação da função do Join() - que personaliza o código para os binários específicos de plataforma.

      Primeiro, crie uma pasta no seu diretório src com o nome do seu app:

      Acesse aquele diretório:

      Em seguida, crie um novo arquivo no seu editor de texto preferido chamado main.go. Para este tutorial, usaremos o Nano:

      Assim que o arquivo estiver aberto, adicione o seguinte código:

      src/app/main.go

      package main
      
      import (
        "fmt"
        "path/filepath"
      )
      
      func main() {
        s := filepath.Join("a", "b", "c")
        fmt.Println(s)
      }
      

      A função main() neste arquivo usa o filepath.Join() para concatenar três strings com o separador de caminho correto, dependente de plataforma.

      Salve e saia do arquivo e, em seguida, execute o programa:

      Ao executar esse programa, você receberá um resultado diferente, dependendo da plataforma que estiver usando. No Windows, você verá as strings separadas pela :

      Output

      abc

      Nos sistemas da Unix, como macOS e Linux, você receberá o seguinte:

      Output

      a/b/c

      Isso mostra que, devido aos diferentes protocolos de sistema de arquivos usados nesses sistemas operacionais, o programa terá que compilar um código diferente para as diferentes plataformas. Porém, uma vez que o programa já utiliza um separador de arquivos diferente de acordo com o SO, sabemos que o filepath.Join() já responde pela diferença na plataforma. Isso acontece porque a cadeia de ferramentas do Go detecta automaticamente o GOOS e a GOARCH da sua máquina e recorre dessa informação para usar o snippet do código com os build tags e o separador de arquivo corretos.

      Vamos considerar de onde a função filepath.Join() obtém o seu separador. Execute o comando a seguir para inspecionar o snippet relevante da biblioteca padrão do Go:

      • less /usr/local/go/src/os/path_unix.go

      Isso exibirá o conteúdo do path_unix.go. Procure pela seguinte parte do arquivo:

      /usr/local/go/os/path_unix.go

      . . .
      // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
      
      package os
      
      const (
        PathSeparator     = '/' // OS-specific path separator
        PathListSeparator = ':' // OS-specific path list separator
      )
      . . .
      

      Esta seção define o PathSeparator de todas as variedades de sistemas do tipo Unix compatíveis com o Go. Observe todos os build tags na parte superior - cada qual representando uma das possíveis plataformas GOOS associadas ao Unix. Quando o GOOS corresponder a esses termos, seu programa produzirá o separador de caminho de arquivo com estilo Unix.

      Pressione q para retornar à linha de comando.

      Em seguida, abra o arquivo que define o comportamento do filepath.Join() quando usado em Windows:

      • less /usr/local/go/src/os/path_windows.go

      Você verá o seguinte:

      /usr/local/go/os/path_unix.go

      . . .
      package os
      
      const (
              PathSeparator     = '\' // OS-specific path separator
              PathListSeparator = ';'  // OS-specific path list separator
      )
      . . .
      

      Embora o valor do PathSeparator seja \ aqui, o código irá renderizar somente uma única barra invertida () - necessária para os caminhos de arquivos do Windows, uma vez que a primeira barra invertida só é necessária como um caractere de escape.

      Note que, ao contrário do arquivo Unix, não há build tags na parte superior. Isso acontece porque o GOOS e a GOARCH também podem ser transmitidos para o go build, adicionando-se um sublinhado (_) e o valor da variável de ambiente como um sufixo do nome do arquivo. Nós vamos nos aprofundar sobre esse ponto na seção Usando sufixos de nome de arquivo no GOOS e na GOARCH. Aqui, a parte _windows do path_windows.go faz o arquivo agir como se ele tivesse o build tag // + build windows no parte superior do arquivo. Por causa disso, quando seu programa for executado em Windows, ele usará as constantes do PathSeparator e do PathListSeparator do snippet de código path_windows.go.

      Para retornar à linha de comando, saia do less pressionando q.

      Neste passo, você compilou um programa que mostrou como a linguagem Go converte o GOOS e a GOARCH automaticamente em build tags. Com isso em mente, você já pode atualizar o seu programa e escrever sua própria implementação do filepath.Join(), usando build tags para definir manualmente o PathSeparator correto para as plataformas Windows e Unix.

      Implementando uma função específica da Plataforma

      Agora que sabe como a biblioteca padrão do Go implementa o código específico da plataforma, você pode usar os build tags para fazer isso em seu próprio programa app. Para fazer isso, você irá escrever sua própria implementação do filepath.Join().

      Abra seu arquivo main.go:

      Substitua o conteúdo do main.go pelo seguinte, usando sua própria função chamada Join():

      src/app/main.go

      package main
      
      import (
        "fmt"
        "strings"
      )
      
      func Join(parts ...string) string {
        return strings.Join(parts, PathSeparator)
      }
      
      func main() {
        s := Join("a", "b", "c")
        fmt.Println(s)
      }
      

      A função Join pega um número de parts e as une usando o método strings.Join() do pacote strings para concatenar as parts usando o PathSeparator.

      Você ainda não definiu o PathSeparator. Assim, faça isso agora, em outro arquivo. Salve e saia do main.go, abra seu editor favorito e crie um novo arquivo chamado path.go:

      nano path.go
      

      Defina o PathSeparator e o configure como o separador de caminho de arquivo do Unix, /:

      src/app/path.go

      package main
      
      const PathSeparator = "/"
      

      Compile e execute o aplicativo:

      Você receberá o seguinte resultado:

      Output

      a/b/c

      Isso executa com sucesso a fim de obter o caminho de arquivo com estilo Unix. Mas isso ainda não é o que queremos: o resultado é sempre a/b/c, a despeito da plataforma na qual ele execute. Para adicionar na funcionalidade para criar os caminhos de arquivo com estilo Windows, você precisará adicionar uma versão do Windows do PathSeparator e dizer ao comando go build qual versão usar. Na próxima seção, você usará os build tags para realizar isso.

      Para considerar as plataformas Windows, agora você irá criar um arquivo alternativo para o path.go e usará build tags para garantir que os snippets de código somente executem quando o GOOS e a GOARCH forem a plataforma apropriada.

      Primeiro, porém, adicione o build tag ao path.go para dizer a ele que compile para tudo, exceto para o Windows. Abra o arquivo:

      Adicione o build tag - destacado a seguir, ao arquivo:

      src/app/path.go

      // +build !windows
      
      package main
      
      const PathSeparator = "/"
      

      Os build tags em Go permitem a inversão, ou seja, você pode instruir o Go a compilar esse arquivo para qualquer plataforma, exceto para o Windows. Para inverter um build tag, coloque um ! antes do tag.

      Salve e saia do arquivo.

      Agora, se você executasse esse programa no Windows, você receberia o seguinte erro:

      Output

      ./main.go:9:29: undefined: PathSeparator

      Neste caso, o Go não conseguiria incluir o path.go para definir o PathSeparator da variável.

      Agora que você garantiu que o path.go não irá executar quando o GOOS for o Windows, adicione um novo arquivo, o windows.go:

      No windows.go, defina o PathSeparator do Windows, bem como um build tag deixar que o comando go build saiba que se trata de uma implementação do Windows:

      src/app/windows.go

      // +build windows
      
      package main
      
      const PathSeparator = "\"
      

      Salve o arquivo e saia do editor de texto. O aplicativo agora pode compilar uma caminho para o Windows e outro para todas as outras plataformas.

      Ao mesmo tempo que os binários agora irão compilar corretamente para suas plataformas, existem mais alterações que você deverá fazer para compilar para uma plataforma à qual você não tenha acesso. Para fazer isso, no próximo passo você irá alterar duas suas variáveis de ambiente GOOS e GOARCH.

      Usando suas variáveis de ambiente locais GOOS e GOARCH

      Anteriormente, você executou o comando go env GOOS GOARCH para descobrir em qual SO e qual arquitetura estava trabalhando. Quando você executou o comando go env, ele procurou as duas variáveis de ambiente, GOOS e GOARCH; se ele as encontrasse, seus valores seriam usados, caso contrário, o Go as definiria com as informações da plataforma atual. Isso significa que você pode alterar o GOOS e a GOARCH para que eles não assumam sua SO e arquitetura locais como padrão.

      O comando go build se comporta de maneira similar ao comando go env. Você pode definir as variáveis de ambiente GOOS ou GOARCH para compilar uma plataforma diferente usando o go build.

      Se não estiver usando um sistema Windows, compile um binário windows do app, definindo a variável de ambiente GOOS para windows ao executar o comando go build:

      Agora, liste os arquivos no seu diretório atual:

      O resultado da ação de listar o diretório mostra que agora existe um arquivo executável do Windows, app.exe no diretório do projeto:

      Output

      app app.exe main.go path.go windows.go

      Usando o comando file, você pode obter mais informações sobre esse arquivo, confirmando sua compilação:

      Você receberá:

      Output

      app.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows

      Também é possível definir uma, ou ambas as variáveis de ambiente no momento da compilação. Execute o seguinte:

      • GOOS=linux GOARCH=ppc64 go build

      Seu executável app será substituído por um arquivo feito de uma arquitetura diferente. Execute o comando file neste binário:

      Você receberá um resultado como o seguinte:

      app: ELF 64-bit MSB executable, 64-bit PowerPC or cisco 7500, version 1 (SYSV), statically linked, not stripped
      

      Definindo suas variáveis de ambiente local GOOS e GOARCH, agora você poderá compilar binários para qualquer uma das plataformas compatíveis do Go, sem precisar de uma configuração ou preparação complicada. Em seguida, você usará as convenções de nome do arquivo para manter seus arquivos totalmente organizados e compilar em plataformas específicas - automaticamente, sem build tags.

      Usando os sufixos de nome do arquivo para GOOS e GOARCH

      Como você viu anteriormente, a biblioteca Go padrão faz intenso uso dos build tags para simplificar o código, separando as implementações de plataforma diferentes em arquivos diferentes. Quando você abriu o arquivo os/path_unix.go havia um build tag que listava todas as combinações possíveis que são consideradas plataformas do tipo Unix. No entanto, o arquivo os/path_windows.go não continha build tags, uma vez que o sufixo no nome do arquivo era o suficiente para dizer ao Go a qual plataforma o arquivo se destinava.

      Vejamos a sintaxe desse recurso. Ao nomear um arquivo .go, você pode adicionar o GOOS e a GOARCH como sufixos do nome do arquivo naquela ordem, separando os valores por sublinhados (_). Se você tivesse um arquivo Go chamado filename.go, poderia especificar o SO e a arquitetura, mudando o nome do arquivo para filename_GOOS_GOARCH.go. Por exemplo, se quisesse compilá-lo para o Windows com a arquitetura ARM 64-bit, você tornaria o nome do arquivo filename_windows_arm64.go​​​​​. Essa convenção de nomenclatura ajuda a manter o código totalmente organizado.

      Atualize seu programa para usar os sufixos do nome do arquivo, em vez dos build tags. Primeiro, renomeie os arquivos path.go e windows.go para usar a convenção usada no pacote os:

      • mv path.go path_unix.go
      • mv windows.go path_windows.go

      Com os dois nomes de arquivo alterados, você pode remover o build tag que você havia adicionado ao path_windows.go:

      Remova // +build windows para que seu arquivo se pareça com este:

      path_windows.go

      package main
      
      const PathSeparator = "\"
      

      Salve e saia do arquivo.

      Como o unix não é um GOOS válido, o sufixo _unix.go não tem significado para o compilador do Go. No entanto, ele transmite o objetivo pretendido do arquivo. Como o arquivo os/path_unix.go, seu arquivo path_unix.go ainda precisa usar build tags. Assim, mantenha esse arquivo inalterado.

      Ao usar as convenções de nome de arquivo, você recomeu os build tags desnecessários do seu código fonte, tornando o sistema de arquivos mais limpo e claro.

      Conclusão

      A capacidade de gerar binários para várias plataformas que não exijam dependências é uma característica poderosa da cadeia de ferramentas do Go. Neste tutorial, você usou essa capacidade, adicionando build tags e sufixos de nome de arquivo para marcar certos snippets de códigos para compilar somente para certas arquiteturas. Você criou seu próprio programa dependente de plataforma e manipulou as variáveis de ambiente GOOS e GOARCH para gerar binários para plataformas além da sua plataforma atual. Esta é uma habilidade valiosa, uma vez que se trata de uma prática comum para ter um processo de integração contínuo que executa automaticamente por essas variáveis de ambiente para compilar binários para todas as plataformas.

      Para obter outros estudos sobre o go build, consulte nosso tutorial Personalizando os binários em Go com os build tags. Se quiser aprender mais sobre a linguagem de programação Go, de um modo geral, confira a série completa sobre Como Codificar em Go.



      Source link