One place for hosting & domains

      Como Construir uma Rede Neural para Reconhecer Dígitos Manuscritos com o TensorFlow


      Introdução

      Redes neurais são usadas como um método de deep learning ou aprendizado profundo, um dos vários subcampos da inteligência artificial. Elas foram propostas pela primeira vez há cerca de 70 anos como uma tentativa de simular a maneira como o cérebro humano funciona, embora de uma forma muito mais simplificada. Os “neurônios” individuais são conectados em camadas, com pesos designados para determinar como o neurônio responde quando os sinais são propagados pela rede. Anteriormente, as redes neurais eram limitadas no número de neurônios que elas eram capazes de simular e, portanto, a complexidade do aprendizado que podiam alcançar. Mas nos últimos anos, devido aos avanços no desenvolvimento de hardware, pudemos construir redes muito profundas e treiná-las em enormes datasets ou conjuntos de dados para obter avanços na inteligência de máquinas.

      Essas inovações permitiram que as máquinas correspondessem e excedessem as capacidades dos humanos em realizar certas tarefas. Uma dessas tarefas é o reconhecimento de objetos. Embora as máquinas tenham sido historicamente incapazes de corresponder à visão humana, avanços recentes em deep learning tornaram possível construir redes neurais capazes de reconhecer objetos, rostos, textos e até mesmo emoções.

      Neste tutorial, você implementará uma pequena subseção de reconhecimento de objeto recognition—digit. Utilizando o TensorFlow, uma biblioteca Python open-source desenvolvida pelos laboratórios do Google Brain para pesquisa em deep learning, você pegará imagens desenhadas à mão dos números de 0 a 9 e construirá e treinará uma rede neural para reconhecer e prever o rótulo correto para o dígito exibido.

      Embora você não precise de experiência prévia em deep learning prático ou de uso do TensorFlow para acompanhar este tutorial, vamos assumir alguma familiaridade com termos e conceitos de machine learning, como treinamento e testes, recursos e rótulos, otimização e avaliação. Você pode aprender mais sobre esses conceitos em Uma Introdução ao Machine Learning.

      Pré-requisitos

      Para completar esse tutorial, você vai precisar de:

      Passo 1 — Configurando o Projeto

      Antes de desenvolver o programa de reconhecimento, você precisará instalar algumas dependências e criar um espaço de trabalho para armazenar seus arquivos.

      Usaremos um ambiente virtual do Python 3 para gerenciar as dependências do nosso projeto. Crie um novo diretório para o seu projeto e navegue até o novo diretório:

      • mkdir tensorflow-demo
      • cd tensorflow-demo

      Execute os seguintes comandos para configurar o ambiente virtual para este tutorial:

      • python3 -m venv tensorflow-demo
      • source tensorflow-demo/bin/activate

      Em seguida, instale as bibliotecas que você usará neste tutorial. Usaremos versões específicas dessas bibliotecas criando um arquivo requirements.txt no diretório do projeto, que especifica o requisito e a versão que precisamos. Crie o arquivo requirements.txt:

      Abra o arquivo em seu editor de textos e adicione as seguintes linhas para especificar as bibliotecas Image, NumPy, e TensorFlow e suas versões:

      requirements.txt

      image==1.5.20
      numpy==1.14.3
      tensorflow==1.4.0
      

      Salve o arquivo e saia do editor. Em seguida instale estas bibliotecas com o seguinte comando:

      • pip install -r requirements.txt

      Com as dependências instaladas, podemos começar a trabalhar no nosso projeto.

      Passo 2 — Importando o Dataset MNIST

      O dataset que estaremos utilizando neste tutorial é chamado de dataset MNIST, e ele é um clássico na comunidade de machine learning. Este dataset é composto de imagens de dígitos manuscritos, com 28x28 pixels de tamanho. Aqui estão alguns exemplos dos dígitos incluídos no dataset:

      Vamos criar um programa Python para trabalhar com este dataset. Usaremos um arquivo para todo o nosso trabalho neste tutorial. Crie um novo arquivo chamado main.py:

      Agora abra este arquivo no editor de textos de sua preferência e adicione esta linha de código ao arquivo para importar a biblioteca do TensorFlow:

      main.py

      import tensorflow as tf
      

      Adicione as seguintes linhas de código ao seu arquivo para importar o dataset MNIST e armazenar os dados da imagem na variável mnist:

      main.py

      from tensorflow.examples.tutorials.mnist import input_data
      mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) # y labels are oh-encoded
      

      Ao ler os dados, estamos usando one-hot-encoding para representar os rótulos (o dígito real desenhado, por exemplo "3") das imagens. O one-hot-encoding utiliza um vetor de valores binários para representar valores numéricos ou categóricos. Como nossos rótulos são para os dígitos de 0 a 9, o vetor contém dez valores, um para cada dígito possível. Um desses valores é definido como 1, para representar o dígito nesse índice do vetor, e o restante é difinido como 0. Por exemplo, o dígito 3 é representado usando o vetor [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]. Como o valor no índice 3 está armazenado como 1, o vetor representa o dígito 3.

      Para representar as imagens, os 28x28 pixels são achatados em um vetor 1D com 784 pixels de tamanho. Cada um dos 784 pixels que compõem a imagem é armazenado como um valor entre 0 e 255. Isso determina a escala de cinza do pixel, pois nossas imagens são apresentadas apenas em preto e branco. Portanto, um pixel preto é representado por 255 e um pixel branco por 0, com os vários tons de cinza em algum lugar entre eles.

      Podemos usar a variável mnist para descobrir o tamanho do dataset que acabamos de importar. Observando os num_examples para cada um dos três subconjuntos, podemos determinar que o dataset foi dividido em 55.000 imagens para treinamento, 5000 para validação e 10.000 para teste. Adicione as seguintes linhas ao seu arquivo:

      main.py

      
      n_train = mnist.train.num_examples # 55,000
      n_validation = mnist.validation.num_examples # 5000
      n_test = mnist.test.num_examples # 10,000
      

      Agora que temos nossos dados importados, é hora de pensar sobre a rede neural.

      Passo 3 — Definindo a Arquitetura da Rede Neural

      A arquitetura da rede neural refere-se a elementos como o número de camadas na rede, o número de unidades em cada camada e como as unidades são conectadas entre as camadas. Como as redes neurais são vagamente inspiradas no funcionamento do cérebro humano, aqui o termo unidade é usado para representar o que seria biologicamente um neurônio. Assim como os neurônios transmitem sinais pelo cérebro, as unidades tomam alguns valores das unidades anteriores como entrada, realizam uma computação e, em seguida, transmitem o novo valor como saída para outras unidades. Essas unidades são colocadas em camadas para formar a rede, iniciando no mínimo com uma camada para entrada de valores e uma camada para valores de saída. O termo hidden layer ou camada oculta é usado para todas as camadas entre as camadas de entrada e saída, ou seja, aquelas "ocultas" do mundo real.

      Arquiteturas diferentes podem produzir resultados drasticamente diferentes, já que o desempenho pode ser pensado como uma função da arquitetura entre outras coisas, como os parâmetros, os dados e a duração do treinamento.

      Adicione as seguintes linhas de código ao seu arquivo para armazenar o número de unidades por camada nas variáveis globais. Isso nos permite alterar a arquitetura de rede em um único lugar e, no final do tutorial, você pode testar por si mesmo como diferentes números de camadas e unidades afetarão os resultados de nosso modelo:

      main.py

      
      n_input = 784   # input layer (28x28 pixels)
      n_hidden1 = 512 # 1st hidden layer
      n_hidden2 = 256 # 2nd hidden layer
      n_hidden3 = 128 # 3rd hidden layer
      n_output = 10   # output layer (0-9 digits)
      

      O diagrama a seguir mostra uma visualização da arquitetura que projetamos, com cada camada totalmente conectada às camadas adjacentes:

      O termo "deep neural network" ou rede neural profunda se relaciona com o número de camadas ocultas, com "superficial" geralmente significando apenas uma camada oculta e "profunda", referindo-se a várias camadas ocultas. Fornecidos dados de treinamento suficientes, uma rede neural superficial com um número suficiente de unidades deve teoricamente ser capaz de representar qualquer função que uma rede neural profunda possa. Mas é mais eficiente computacionalmente usar uma rede neural profunda menor para realizar a mesma tarefa que exigiria uma rede superficial com exponencialmente mais unidades ocultas. Redes neurais superficiais também freqüentemente encontram overfitting, onde a rede essencialmente memoriza os dados de treinamento que viu e não é capaz de generalizar o conhecimento para novos dados. É por isso que as redes neurais profundas são mais comumente usadas: as várias camadas entre os dados brutos de entrada e o rótulo de saída permitem que a rede aprenda recursos em vários níveis de abstração, tornando a própria rede mais capaz de generalizar.

      Outros elementos da rede neural que precisam ser definidos aqui são os hiperparâmetros. Ao contrário dos parâmetros que serão atualizados durante o treinamento, esses valores são definidos inicialmente e permanecem constantes durante todo o processo. No seu arquivo, defina as seguintes variáveis e valores:

      main.py

      
      learning_rate = 1e-4
      n_iterations = 1000
      batch_size = 128
      dropout = 0.5
      

      A taxa de aprendizado, learningrate, representa o quanto os parâmetros serão ajustados em cada etapa do processo de aprendizado. Esses ajustes são um componente-chave do treinamento: depois de cada passagem pela rede, ajustamos os pesos ligeiramente para tentar reduzir a perda. Taxas de aprendizado maiores podem convergir mais rapidamente, mas também têm o potencial de ultrapassar os valores ideais à medida que são atualizados. O número de iterações, niterations, refere-se a quantas vezes passamos pela etapa de treinamento e o tamanho do lote ou batch_size se refere a quantos exemplos de treinamento estamos usando em cada etapa. A variável dropout representa um limiar no qual eliminamos algumas unidades aleatoriamente. Estaremos usando dropout em nossa última camada oculta para dar a cada unidade 50% de chance de ser eliminada em cada etapa de treinamento. Isso ajuda a evitar o overfitting.

      Agora já definimos a arquitetura de nossa rede neural e os hiperparâmetros que impactam o processo de aprendizagem. O próximo passo é construir a rede como um gráfico do TensorFlow.

      Passo 4 — Construindo o Gráfico do TensorFlow

      Para construir nossa rede, vamos configurará-la como um gráfico computacional para o TensorFlow executar. O conceito central do TensorFlow é o tensor, uma estrutura de dados semelhante a uma matriz ou lista inicializada, manipulada à medida que passa pelo gráfico e atualizada através do processo de aprendizado.

      Começaremos definindo três tensores como placeholders ou marcadores de posição, que são tensores nos quais alimentaremos os valores posteriormente. Adicione o seguinte ao seu arquivo:

      main.py

      
      X = tf.placeholder("float", [None, n_input])
      Y = tf.placeholder("float", [None, n_output])
      keep_prob = tf.placeholder(tf.float32) ^
      

      O único parâmetro que precisa ser especificado em sua declaração é o tamanho dos dados os quais estaremos alimentando. Para X usamos um formato [None, 784], onde None representa qualquer quantidade, pois estaremos alimentando em um número indefinido de imagens de 784 pixels. O formato de Y é [None, 10] pois iremos usá-lo para um número indefinido de saídas de rótulo, com 10 classes possíveis. O tensor keep_prob é usado para controlar a taxa de dropout, e nós o inicializamos como um placeholder ao invés de uma variável imutável porque queremos usar o mesmo tensor tanto para treinamento (quando dropout é definido para 0.5) quanto para testes (quando dropout é definido como 1.0).

      Os parâmetros que a rede atualizará no processo de treinamento são os valores weight e bias, portanto, precisamos definir um valor inicial em vez de um placeholder vazio. Esses valores são essencialmente onde a rede faz seu aprendizado, pois são utilizados nas funções de ativação dos neurônios, representando a força das conexões entre as unidades.

      Como os valores são otimizados durante o treinamento, podemos defini-los para zero por enquanto. Mas o valor inicial realmente tem um impacto significativo na precisão final do modelo. Usaremos valores aleatórios de uma distribuição normal truncada para os pesos. Queremos que eles estejam próximos de zero, para que possam se ajustar em uma direção positiva ou negativa, e um pouco diferente, para que gerem erros diferentes. Isso garantirá que o modelo aprenda algo útil. Adicione estas linhas:

      main.py

      
      weights = {
          'w1': tf.Variable(tf.truncated_normal([n_input, n_hidden1], stddev=0.1)),
          'w2': tf.Variable(tf.truncated_normal([n_hidden1, n_hidden2], stddev=0.1)),
          'w3': tf.Variable(tf.truncated_normal([n_hidden2, n_hidden3], stddev=0.1)),
          'out': tf.Variable(tf.truncated_normal([n_hidden3, n_output], stddev=0.1)),
      }
      

      Para o bias ou tendência, usamos um pequeno valor constante para garantir que os tensores se ativem nos estágios iniciais e, portanto, contribuam para a propagação. Os pesos e tensores de bias são armazenados em objetos de dicionário para facilitar o acesso. Adicione este código ao seu arquivo para definir cada bias:

      main.py

      
      biases = {
          'b1': tf.Variable(tf.constant(0.1, shape=[n_hidden1])),
          'b2': tf.Variable(tf.constant(0.1, shape=[n_hidden2])),
          'b3': tf.Variable(tf.constant(0.1, shape=[n_hidden3])),
          'out': tf.Variable(tf.constant(0.1, shape=[n_output]))
      }
      

      Em seguida, configure as camadas da rede definindo as operações que manipularão os tensores. Adicione estas linhas ao seu arquivo:

      main.py

      
      layer_1 = tf.add(tf.matmul(X, weights['w1']), biases['b1'])
      layer_2 = tf.add(tf.matmul(layer_1, weights['w2']), biases['b2'])
      layer_3 = tf.add(tf.matmul(layer_2, weights['w3']), biases['b3'])
      layer_drop = tf.nn.dropout(layer_3, keep_prob)
      output_layer = tf.matmul(layer_3, weights['out']) + biases['out']
      

      Cada camada oculta executará a multiplicação da matriz nas saídas da camada anterior e os pesos da camada atual e adicionará o bias a esses valores. Na última camada oculta, aplicaremos uma operação de eliminação usando nosso valor keep_prob de 0.5.

      O passo final na construção do gráfico é definir a função de perda que queremos otimizar. Uma escolha popular da função de perda nos programas do TensorFlow é a cross-entropy ou entropia cruzada, também conhecida como log-loss, que quantifica a diferença entre duas distribuições de probabilidade (as predições e os rótulos). Uma classificação perfeita resultaria em uma entropia cruzada de 0, com a perda completamente minimizada.

      Também precisamos escolher o algoritmo de otimização que será usado para minimizar a função de perda. Um processo denominado otimização gradiente descendente é um método comum para encontrar o mínimo (local) de uma função, tomando etapas iterativas ao longo do gradiente em uma direção negativa (descendente). Existem várias opções de algoritmos de otimização de gradiente descendente já implementados no TensorFlow, e neste tutorial vamos usar o otimizador Adam. Isso se estende à otimização de gradiente descendente usando o momento para acelerar o processo através do cálculo de uma média exponencialmente ponderada dos gradientes e usando isso nos ajustes. Adicione o seguinte código ao seu arquivo:

      main.py

      
      cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=output_layer))
      train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
      

      Agora acabamos de definir a rede e a construímos com o TensorFlow. O próximo passo é alimentar os dados através do gráfico para treiná-los e, em seguida, testar se realmente aprendeu alguma coisa.

      Passo 5 — Treinando e Testando

      O processo de treinamento envolve alimentar o dataset de treinamento através do gráfico e otimizar a função de perda. Toda vez que a rede itera um lote de mais imagens de treinamento, ela atualiza os parâmetros para reduzir a perda, a fim de prever com mais precisão os dígitos exibidos. O processo de teste envolve a execução do nosso dataset de teste através do gráfico treinado e o acompanhamento do número de imagens que são corretamente previstas, para que possamos calcular a precisão.

      Antes de iniciar o processo de treinamento, definiremos nosso método de avaliação da precisão para que possamos imprimi-lo em mini-lotes de dados enquanto treinamos. Estas declarações impressas nos permitem verificar que, da primeira iteração até a última, a perda diminui e a precisão aumenta; elas também nos permitem rastrear se executamos ou não repetições suficientes para alcançar um resultado consistente e ideal:

      main.py

      correct_pred = tf.equal(tf.argmax(output_layer, 1), tf.argmax(Y, 1))
      accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
      

      Em correct_pred, usamos a função arg_max para comparar quais imagens estão sendo previstas corretamente observando output_layer (predições) e Y (labels), e usamos a função equal para retornar isso como uma lista de Booleanos. Podemos, então, converter essa lista em floats e calcular a média para obter uma pontuação total da precisão.

      Agora estamos prontos para inicializar uma sessão para executar o gráfico. Nesta sessão, vamos alimentar a rede com nossos exemplos de treinamento e, uma vez treinados, alimentamos o mesmo gráfico com novos exemplos de teste para determinar a precisão do modelo. Adicione as seguintes linhas de código ao seu arquivo:

      main.py

      
      init = tf.global_variables_initializer()
      sess = tf.Session()
      sess.run(init)
      

      A essência do processo de treinamento em deep learning é otimizar a função de perda. Aqui, pretendemos minimizar a diferença entre os rótulos previstos das imagens e os rótulos verdadeiros das imagens. O processo envolve quatro etapas que são repetidas para um número definido de iterações:

      Em cada etapa de treinamento, os parâmetros são ligeiramente ajustados para tentar reduzir a perda para a próxima etapa. À medida que o aprendizado avança, devemos ver uma redução na perda e, eventualmente, podemos parar de treinar e usar a rede como um modelo para testar nossos novos dados.

      Adicione este código ao arquivo:

      main.py

      
      # train on mini batches
      for i in range(n_iterations):
          batch_x, batch_y = mnist.train.next_batch(batch_size)
          sess.run(train_step, feed_dict={X: batch_x, Y: batch_y, keep_prob:dropout})
      
          # print loss and accuracy (per minibatch)
          if i%100==0:
              minibatch_loss, minibatch_accuracy = sess.run([cross_entropy, accuracy], feed_dict={X: batch_x, Y: batch_y, keep_prob:1.0})
              print("Iteration", str(i), "t| Loss =", str(minibatch_loss), "t| Accuracy =", str(minibatch_accuracy))
      

      Após 100 iterações de cada etapa de treinamento em que alimentamos um mini-lote de imagens através da rede, imprimimos a perda e a precisão desse lote. Observe que não devemos esperar uma perda decrescente e uma precisão crescente aqui, pois os valores são por lote, não para o modelo inteiro. Usamos mini-lotes de imagens em vez de alimentá-las individualmente para acelerar o processo de treinamento e permitir que a rede veja vários exemplos diferentes antes de atualizar os parâmetros.

      Quando o treinamento estiver concluído, podemos executar a sessão nas imagens de teste. Desta vez estamos usando uma taxa de dropout keep_prob de 1.0 para garantir que todas as unidades estejam ativas no processo de teste.

      Adicione este código ao arquivo:

      main.py

      
      test_accuracy = sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels, keep_prob:1.0})
      print("nAccuracy on test set:", test_accuracy)
      

      Agora é hora de executar nosso programa e ver com que precisão nossa rede neural pode reconhecer esses dígitos manuscritos. Salve o arquivo main.py e execute o seguinte comando no terminal para executar o script:

      Você verá uma saída semelhante à seguinte, embora os resultados individuais de perda e precisão possam variar um pouco:

      Output

      Iteration 0 | Loss = 3.67079 | Accuracy = 0.140625 Iteration 100 | Loss = 0.492122 | Accuracy = 0.84375 Iteration 200 | Loss = 0.421595 | Accuracy = 0.882812 Iteration 300 | Loss = 0.307726 | Accuracy = 0.921875 Iteration 400 | Loss = 0.392948 | Accuracy = 0.882812 Iteration 500 | Loss = 0.371461 | Accuracy = 0.90625 Iteration 600 | Loss = 0.378425 | Accuracy = 0.882812 Iteration 700 | Loss = 0.338605 | Accuracy = 0.914062 Iteration 800 | Loss = 0.379697 | Accuracy = 0.875 Iteration 900 | Loss = 0.444303 | Accuracy = 0.90625 Accuracy on test set: 0.9206

      Para tentar melhorar a precisão do nosso modelo, ou para saber mais sobre o impacto dos hiperparâmetros de ajuste, podemos testar o efeito de alterar a taxa de aprendizado, o limite de dropout, o tamanho do lote e o número de iterações. Também podemos alterar o número de unidades em nossas camadas ocultas e alterar a quantidade das próprias camadas ocultas, para ver como diferentes arquiteturas aumentam ou diminuem a precisão do modelo.

      Para demonstrar que a rede está realmente reconhecendo as imagens desenhadas à mão, vamos testá-la em uma única imagem nossa.

      Primeiro, faça o download dessa amostra de imagem de teste ou abra um editor gráfico e crie sua própria imagem de 28x28 pixels de um dígito.

      Abra o arquivo main.py no seu editor e adicione as seguintes linhas de código ao topo do arquivo para importar duas bibliotecas necessárias para a manipulação de imagens.

      main.py

      
      import numpy as np
      from PIL import Image
      ...
      

      Em seguida, no final do arquivo, adicione a seguinte linha de código para carregar a imagem de teste do dígito manuscrito:

      main.py

      
      img = np.invert(Image.open("test_img.png").convert('L')).ravel()
      

      A função open da bibliotecaImage carrega a imagem de teste como um array 4D contendo os três canais de cores RGB e a transparência Alpha. Esta não é a mesma representação que usamos anteriormente ao ler o dataset com o TensorFlow, portanto, precisamos fazer algum trabalho extra para corresponder ao formato.

      Primeiro, usamos a função convert com o parâmetro L para reduzir a representação 4D RGBA para um canal de cor em escala de cinza. Aarmazenamos isso como um array numpy e o invertemos usando np.invert, porque a matriz atual representa o preto como 0 e o branco como 255, porém, precisamos do oposto. Finalmente, chamamos ravel para achatar o array.

      Agora que os dados da imagem estão estruturados corretamente, podemos executar uma sessão da mesma forma que anteriormente, mas desta vez apenas alimentando uma imagem única para teste. Adicione o seguinte código ao seu arquivo para testar a imagem e imprimir o rótulo de saída.

      [labe main.py]
      prediction = sess.run(tf.argmax(output_layer,1), feed_dict={X: [img]})
      print ("Prediction for test image:", np.squeeze(prediction))
      

      A função np.squeeze é chamada na predição para retornar o único inteiro da matriz (ou seja, para ir de [2] para 2). A saída resultante demonstra que a rede reconheceu essa imagem como o dígito 2.

      Output

      Prediction for test image: 2

      Você pode tentar testar a rede com imagens mais complexas - dígitos que se parecem com outros dígitos, por exemplo, ou dígitos que foram mal desenhados ou desenhados incorretamente - para ver como ela se sai.

      Conclusão

      Neste tutorial você treinou com sucesso uma rede neural para classificar o dataset MNIST com cerca de 92% de precisão e testou em uma imagem sua. O estado da arte em pesquisa atual alcança cerca de 99% neste mesmo problema, usando arquiteturas de rede mais complexas envolvendo camadas convolucionais. Elas usam a estrutura 2D da imagem para melhor representar o conteúdo, ao contrário do nosso método que achata todos os pixels em um vetor de 784 unidades. Você pode ler mais sobre esse tópico no website do TensorFlow, e ver os documentos de pesquisa detalhando os resultados mais precisos no wesite do MNIST.

      Agora que você sabe como construir e treinar uma rede neural, pode tentar usar essa implementação em seus próprios dados ou testá-la em outros datasets populares, como o Google StreetView House Numbers, ou o dataset CIFAR-10 para um reconhecimento de imagem mais genérico.

      Por Ellie Birbeck



      Source link

      Como Gerenciar um Banco de Dados SQL


      Um Guia de Consulta Rápida SQL

      Introdução

      Os bancos de dados SQL vêm instalados com todos os comandos necessários para adicionar, modificar, excluir e consultar seus dados. Este guia de consulta rápida fornece uma referência para alguns dos comandos SQL mais usados.

      Como Utilizar Este Guia:

      • Este guia está no formato de consulta rápida com trechos de linha de comando independentes

      • Salte para qualquer seção que seja relevante para a tarefa que você está tentando concluir

      • Quando você vir texto destacado nos comandos deste guia, tenha em mente que este texto deve se referir às colunas, tabelas e dados em seu próprio banco de dados.

      • Em todo este guia, os valores de dados de exemplo fornecidos são todos agrupados em apóstrofos ('). No SQL, é necessário envolver quaisquer valores de dados que consistam em strings em apóstrofos. Isso não é necessário para dados numéricos, mas também não causará problemas se você incluir apóstrofos.

      Por favor, observe que, embora o SQL seja reconhecido como padrão, a maioria dos programas de banco de dados SQL possui suas próprias extensões proprietárias. Este guia utiliza o MySQL como exemplo de sistema gerenciador de banco de dados relacional (SGBD), mas os comandos executados irão funcionar com outros programs de banco de dados relacionais, incluindo PostgreSQL, MariaDB, and SQLite. Onde existem diferenças significativas entre os SGDBs, incluímos os comandos alternativos.

      Abrindo o Prompt do Banco de Dados (usando Autenticação Socket/Trust)

      Por padrão no Ubuntu 18.04, o usuário root do MySQL pode se autenticar sem uma senha utilizando o seguinte comando:

      Para abrir um prompt no PostgreSQL, use o seguinte comando. Este exemplo irá logar você como o usuário postgres, que é a função de superusuário incluída, mas você pode substituir isso por qualquer função já criada:

      Abrindo o Prompt do Banco de Dados (usando Autenticação por Senha)

      Se seu usuário root do MySQL está configurado para se autenticar com uma senha, você pode fazer isso com o seguinte comando:

      Se você já tiver configurado uma conta de usuário não-root para seu banco de dados, você também poderá usar esse método para efetuar login como esse usuário:

      O comando acima irá solicitar a sua senha após executá-lo. Se voce gostaria de fornecer sua senha como parte do comando, siga imediatamente a opção -p com a sua senha, sem espaço entre elas:

      Criando um Banco de Dados

      O seguinte comando cria um banco de dados com configurações padrão.

      • CREATE DATABASE nome_do_banco_de_dados;

      Se você quer que seu banco de dados utilize um conjunto de caracteres e collation diferentes do padrão, você pode especificá-los usando esta sintaxe:

      • CREATE DATABASE nome_do_banco_de_dados CHARACTER SET character_set COLLATE collation;

      Listando Bancos de Dados

      Para ver quais bancos de dados existem em sua instalação de MySQL ou MariaDB, execute o seguinte comando:

      No PostgreSQL, você pode ver quais bancos de dados foram criados com o seguinte comando:

      Excluindo um Banco de Dados

      Para excluir um banco de dados, incluindo quaisquer tabelas e dados contidos nele, execute um comando que segue esta estrutura:

      • DROP DATABASE IF EXISTS banco_de_dados;

      Criando um Usuário

      Para criar um perfil de usuário para o seu banco de dados sem especificar nenhum privilégio para ele, execute o seguinte comando:

      • CREATE USER nome_do_usuário IDENTIFIED BY 'senha';

      O PostgreSQL usa uma sintaxe similar, mas ligeiramente diferente:

      • CREATE USER nome_do_usuário WITH PASSWORD 'senha';

      Se você quiser criar um novo usuário e conceder-lhe privilégios em um comando, você pode fazer isso usando um comando GRANT. O seguinte comando cria um novo usuário e concede a ele privilégios totais em todos os bancos de dados e tabelas do SGBD:

      • GRANT ALL PRIVILEGES ON *.* TO 'nome_do_usuário'@'localhost' IDENTIFIED BY 'senha';

      Observe a palavra-chave PRIVILEGES no comando GRANT anterior. na maioria dos SGBDs, esta palavra-chave é opcional, e esse comando pode ser escrito equivalentemente como:

      • GRANT ALL ON *.* TO 'nome_do_usuário'@'localhost' IDENTIFIED BY 'senha';

      Esteja ciente, porém, que a palavra-chave PRIVILEGES é necessária para a concessão de privilégios como este, quando o modo Strict SQL está ligado.

      Excluindo um Usuário

      Utilize a seguinte sintaxe para excluir um perfil de usuário do banco de dados:

      • DROP USER IF EXISTS nome_do_usuário;

      Observe que esse comando não excluirá por padrão nenhuma tabela criada pelo usuário excluído, e tentativas de acessar essas tabelas podem resultar em erros.

      Selecionando um Banco de Dados

      Antes de poder criar uma tabela, primeiro você precisa informar ao SGBD o banco de dados no qual você gostaria de criá-la. No MySQL e MariaDB, faça isto com a seguinte sintaxe:

      No PostgreSQL, você deve utilizar o seguinte comando para selecionar seu banco de dados desejado:

      Criando uma Tabela

      A seguinte estrutura de comando cria uma nova tabela com o nome tabela, e inclui duas colunas, cada uma com seu tipo de dado específico:

      • CREATE TABLE tabela ( coluna_1 coluna_1_tipo_de_dado, coluna_2 coluna_2_tipo_de_dado );

      Excluindo uma Tabela

      Para excluir uma tabela inteira, incluindo todos os seus dados, execute o seguinte:

      • DROP TABLE IF EXISTS tabela

      Inserindo Dados em uma Tabela

      Utilize a seguinte sintaxe para popular uma tabela com uma linha de dados:

      • INSERT INTO tabela ( coluna_A, coluna_B, coluna_C ) VALUES ( 'dado_A', 'dado_B', 'dado_C' );

      Você pode também popular uma tabela com várias linhas de dados usando um único comando, assim:

      • INSERT INTO tabela ( coluna_A, coluna_B, coluna_C ) VALUES ( 'dado_1A', 'dado_1B', 'dado_1C' ), ( 'dado_2A', 'dado_2B', 'dado_2C' ), ( 'dado_3A', 'dado_3B', 'dado_3C' );

      Excluindo Dados de uma Tabela

      Para excluir uma linha de dados de uma tabela, utilize a seguinte estrutura de comando. Observe que valor deve ser o valor contido na coluna especificada na linha que você quer excluir:

      • DELETE FROM tabela WHERE coluna='valor';

      Nota: Se você não incluir uma cláusula WHERE em um comando DELETE como no exemplo seguinte, ele excluirá todos os dados contidos em uma tabela, mas não as colunas ou a própria tabela:

      Alterando Dados em uma Tabela

      Use a seguinte sintaxe para atualizar os dados contidos em uma dada linha. Observe que a cláusula WHERE no final do comando informa ao SQL qual linha atualizar. valor é o valor contido na coluna_A que se alinha com a linha que você deseja alterar.

      Nota: Se você deixar de incluir uma cláusula WHERE em um comando UPDATE, o comando substituirá os dados contidos em todas as linhas da tabela.

      • UPDATE tabela SET coluna_1 = valor_1, coluna_2 = valor_2 WHERE coluna_A=valor;

      Inserindo uma Coluna

      A seguinte sintaxe de comando adicionará uma nova coluna a uma tabela:

      • ALTER TABLE tabela ADD COLUMN tipo_de_dado coluna;

      Excluindo uma Coluna

      Um comando seguindo essa estrutura excluirá uma coluna de uma tabela:

      • ALTER TABLE tabela DROP COLUMN coluna;

      Realizando Consultas Básicas

      Para visualizar todos os dados de uma única coluna em uma tabela, use a seguinte sintaxe:

      • SELECT coluna FROM tabela;

      Para consultar várias colunas da mesma tabela, separe os nomes das colunas com uma vírgula:

      • SELECT coluna_1, coluna_2 FROM tabela;

      Você também pode consultar todas as colunas de uma tabela, substituindo os nomes das colunas por um asterisco (*). No SQL, asteriscos agem como um curinga para representar "todos":

      Usando Cláusulas WHERE

      Você pode restringir os resultados de uma consulta adicionando a cláusula WHERE ao comando SELECT, assim:

      • SELECT coluna FROM tabela WHERE condições_que_se_aplicam;

      Por exemplo, você pode consultar todos os dados de uma única linha com uma sintaxe como a seguinte. Observe que valor deve ser um valor contido tanto na coluna especificada quanto na linha que você quer consultar:

      • SELECT * FROM tabela WHERE coluna = valor;

      Um operador de comparação em uma cláusula WHERE define como a coluna especificada deve ser comparada com o valor. Aqui estão alguns operadores comuns de comparação SQL:

      Operador O que ele faz
      = testa a igualdade
      != testa a desigualdade
      < testa menor que
      > testa maior que
      <= testa menor que ou igual a
      >= testa maior que ou igual a
      BETWEEN testa se um valor está dentro de um determinado intervalo
      IN testa se o valor de uma linha está contido em um conjunto de valores especificados
      EXISTS testa se existem linhas, dadas as condições especificadas
      LIKE testa se um valor corresponde a uma string especificada
      IS NULL testa valores NULL
      IS NOT NULL testa todos os valores que não sejam NULL

      O SQL permite o uso de caracteres curinga. Eles são úteis se você estiver tentando encontrar uma entrada específica em uma tabela, mas não tiver certeza de qual é exatamente essa entrada.

      Asteriscos (*) são marcadores que representam “todos”. Isso irá consultar todas as colunas de uma tabela:

      O símbolo de porcentagem (%) representa zero ou mais caracteres desconhecidos.

      • SELECT * FROM tabela WHERE coluna LIKE val%;

      Os underscores (_) são usados para representar um único caractere desconhecido:

      • SELECT * FROM tabela WHERE coluna LIKE v_lue;

      Contando Entradas em uma Coluna

      A função COUNT é utilizada para encontrar o número de entradas em uma determinada coluna. A seguinte sintaxe retornará o número total de valores contidos em coluna:

      • SELECT COUNT(coluna) FROM tabela;

      Você pode restringir os resultados de uma função COUNT adicionando a cláusula WHERE, assim:

      • SELECT COUNT(coluna) FROM table WHERE coluna=valor;

      Encontrando o Valor Médio em uma Coluna

      A função AVG é usada para encontrar o valor médio (nesse caso, a média) entre os valores contidos em uma coluna específica. Observe que a função AVG só funcionará com colunas contendo valores numéricos; quando usada em uma coluna contendo valores de string, pode retornar um erro ou 0:

      • SELECT AVG(coluna) FROM tabela;

      Encontrando a Soma de Valores em uma Coluna

      A função SUM é usado para encontrar a soma total de todos os valores numéricos contidos em uma coluna:

      • SELECT SUM(coluna) FROM tabela;

      Assim como na função AVG, se você executar a função SUM em uma coluna contendo valores de string, ela pode retornar um erro ou apenas 0, dependendo do seu SGBD.

      Encontrando o Maior Valor em uma Coluna

      Para encontrar o maior valor numérico em uma coluna ou o último valor em ordem alfabética, utilize a função MAX:

      • SELECT MAX(coluna) FROM tabela;

      Encontrando o Menor Valor em uma Coluna

      Para encontrar o menor valor numérico em uma coluna ou o primeiro valor em ordem alfabética, use a função MIN:

      • SELECT MIN(coluna) FROM tabela;

      Uma cláusula ORDER BY é usada para ordenar os resultados da consulta. A seguinte sintaxe de consulta retorna os valores de coluna1 e coluna2 e ordena os resultados pelos valores contidos em coluna_1 em ordem crescente ou, para valores de string, em ordem alfabética:

      • SELECT coluna_1, coluna_2 FROM tabela ORDER BY coluna_1;

      Para realizar a mesma ação, mas ordenar os resultados em ordem alfabética decrescente ou reversa, anexe a consulta com DESC:

      • SELECT coluna_1, coluna_2 FROM tabela ORDER BY coluna_1 DESC;

      A cláusula GROUP BY é semelhante à cláusula ORDER BY, mas é usada para ordenar os resultados de uma consulta que inclui uma função de agregação, como COUNT, MAX, MIN, ou SUM. Sozinhas, as funções de agregação descritas na seção anterior retornarão apenas um único valor. No entanto, você pode visualizar os resultados de uma função de agregação executada em cada valor correspondente em uma coluna, ao incluir uma cláusula GROUP BY.

      A seguinte sintaxe contará o número de valores correspondentes em coluna_2 e os agrupará em ordem crescente ou alfabética:

      • SELECT COUNT(coluna_1), coluna_2 FROM tabela GROUP BY coluna_2;

      Para realizar a mesma ação, mas ordenar os resultados em ordem alfabética decrescente ou reversa, adicione DESC à consulta:

      • SELECT COUNT(coluna_1), coluna_2 FROM tabela GROUP BY coluna_2 DESC;

      As cláusulas JOIN são usadas para criar result-sets ou conjuntos de resultados que combinam linhas de duas ou mais tabelas. Uma cláusula JOIN só funcionará se as duas tabelas tiverem uma coluna com nome e tipo de dados idênticos, como neste exemplo:

      • SELECT tabela_1.coluna_1, tabela_2.coluna_2 FROM tabela_1 JOIN tabela_2 ON tabela_1.coluna_comum=tabela_2.coluna_comum;

      Este é um exemplo de uma cláusula INNER JOIN. Um INNER JOIN retornará todos os registros que tiverem valores correspondentes nas duas tabelas, mas não mostrará registros que não tenham valores correspondentes.

      É possível retornar todos os registros de uma das duas tabelas, incluindo valores que não têm ocorrência correspondente na outra tabela, utilizando uma cláusula outer JOIN. As cláusulas outer JOIN são escritas ou como LEFT JOIN ou RIGHT JOIN.

      Uma cláusula LEFT JOIN retorna todos os registros da tabela da "esquerda" e apenas os registros correspondentes da tabela da "direita". No contexto das cláusulas outer JOIN, a tabela da esquerda é aquela referenciada na cláusula FROM, e a tabela da direita é qualquer outra tabela referenciada após a declaração JOIN. A consulta seguinte mostrará todos os registros de tabela_1 e apenas os valores correspondentes de tabela_2. Quaisquer valores que não tenham uma correspondência em tabela_2 aparecerão como NULL no result-set:

      • SELECT tabela_1.coluna_1, tabela_2.coluna_2 FROM tabela_1 LEFT JOIN tabela_2 ON tabela_1.coluna_comum=tabela_2.coluna_comum;

      Uma cláusula RIGHT JOIN funciona da mesma forma que um LEFT JOIN, mas imprime todos os resultados da tabela da direita e apenas os valores correspondentes da tabela da esquerda:

      • SELECT tabela_1.coluna_1, tabela_2.coluna_2 FROM tabela_1 RIGHT JOIN tabela_2 ON tabela_1.coluna_comum=tabela_2.coluna_comum;

      Um operador UNION é útil para combinar os resultados de dois (ou mais) comandos SELECT em um único result-set:

      • SELECT coluna_1 FROM tabela UNION SELECT coluna_2 FROM tabela;

      Além disso, a cláusula UNION pode combinar dois (ou mais) comandos SELECT consultando diferentes tabelas em um mesmo result-set:

      • SELECT coluna FROM tabela_1 UNION SELECT coluna FROM tabela_2;

      Conclusão

      Este guia aborda alguns dos comandos mais comuns no SQL usados para gerenciar bancos de dados, usuários e tabelas e consultar o conteúdo contido nessas tabelas. No entanto, existem muitas combinações de cláusulas e operadores que produzem result-set exclusivos. Se você está procurando um guia mais abrangente para trabalhar com SQL, recomendamos que você confira a Referência de SQL do Banco de Dados Oracle.

      Além disso, se houver comandos SQL comuns que você gostaria de ver neste guia, pergunte ou faça sugestões nos comentários abaixo.

      Por Mark Drake



      Source link

      Como Criar uma Imagem do Seu Ambiente Linux e Lançá-la na DigitalOcean


      Introdução

      O recurso Custom Images ou Imagens Personalizadas da DigitalOcean lhe permite trazer seu disco virtual personalizado de Linux e Unix-like de um ambiente local ou de outra plataforma de nuvem para a DigitalOcean e utilizá-lo para iniciar Droplets na DigitalOcean.

      Como descrito na documentação do Custom Images, os seguintes tipos de imagens são suportados nativamente pela ferramenta de upload do Custom Images:

      Embora imagens com formato ISO não sejam oficialmente suportadas, você pode aprender como criar e carregar uma imagem compatível usando o VirtualBox seguindo o tutorial How to Create a DigitalOcean Droplet from an Ubuntu ISO Format Image.

      Se você ainda não tem uma imagem compatível para carregar na DigitalOcean, você pode criar e comprimir uma imagem de disco do seu sistema Unix-like ou Linux, desde que ela tenha o software e os drivers de pré-requisitos instalados.

      Vamos começar assegurando que sua imagem atende ao requisitos do Custom Images. Para fazer isso, vamos configurar o sistema e instalar alguns pré-requisitos de software. Depois, vamos criar a imagem utilizando o utilitário de linha de comando dd e comprimí-la usando o gzip. Na sequência, vamos fazer o upload desse arquivo de imagem compactado para o DigitalOcean Spaces, de onde podemos importá-lo como uma Imagem Personalizada. Finalmente, vamos inicializar um droplet usando a imagem enviada

      Pré-requisitos

      Se possível, você deve usar uma das imagens fornecidas pela DigitalOcean como base, ou uma imagem de nuvem oficial fornecida pela distribuição como o Ubuntu Cloud. Então você pode instalar softwares e aplicaçoes em cima dessa imagem de base para fazer uma nova imagem usando ferramentas como o Packer e o VirtualBox. Muitos provedores de nuvem e ambientes de virtualização também fornecem ferramentas para exportar discos virtuais para um dos formatos compatíveis listados acima, assim, se possível, você deve usá-las para simplificar o processo de importação. Nos casos em que você precisa criar manualmente uma imagem de disco do seu sistema você pode seguir as instruções nesse guia. Observe que essas instruções só foram testadas com um sistema Ubuntu 18.04 e as etapas podem variar dependendo do sistema operacional e da configuração do seu servidor.

      Antes de começar com este tutorial, você deve ter o seguinte disponível para você:

      • Um sistema Linux ou Unix-like que atenda a todos os requisitos listados na documentação de produto do Custom Images. Por exemplo, seu disco de boot deve ter:

        • Um tamanho máximo de 100GB
        • Um tabela de partição MBR ou GPT com um gerenciador de boot grub
        • Drivers do VirtIO instalados
      • Um usuário não-root com privilégios administrativos disponível para você no sistema que você está fazendo imagem. Para criar um novo usuário e conceder a ele privilégios administrativos no Ubuntu 18.04, siga nosso tutorial de Configuração Inicial de Servidor com Ubuntu 18.04. Para aprender como fazer isto no Debian 9, consulte Configuração Inicial de Servidor com Debian 9.

      • Um dispositivo de armazenamento adicional usado para armazenar a imagem de disco criada neste guia, preferivelmente tão grande quanto o disco que está sendo copiado. Isso pode ser um volume de armazenamento em blocos anexado, um drive externo USB, um espaço em disco adicional, etc.

      • Um Space na DigitalOcean e o utilitário de transferência de arquivos s3cmd configurado para uso com o seu Space. Para aprender como criar um Space, consulte o Guia Rápido do Spaces. Para aprender como configurar o s3cmd para uso com o seu Space, consulte o Guia de Configuração do s3cmd 2.x.

      Passo 1 — Instalando o Cloud-Init e ativando o SSH

      Para começar, vamos instalar o pacote de inicialização do cloud-Init. O cloud-init é um conjunto de scripts que executam no boot para configurar certas propriedades da instância de nuvem como a localidade padrão, hostname, chaves SSH e dispositivos de rede.

      Os passos para a instalação do cloud-init vão variar dependendo do sistema operacional que você instalou. Em geral, o pacote cloud-init deve estar disponível no gerenciador de pacotes do seu SO, assim se você não estiver utilizando uma distribuição baseada no Debian, você deve substituir o apt nos seguintes passos pelo seu comando do gerenciador de pacotes específico da distribuição.

      Instalando o cloud-init

      Neste guia, vamos utilizar um servidor Ubuntu 18.04 e então usaremos o apt para baixar e instalar o pacote cloud-init. Observe que o cloud-init pode já estar instalado em seu sistema (algumas distribuições Linux instalam o cloud-initpor padrão). Para verificar, efetue o login em seu servidor e execute o seguinte comando:

      Se você vir a seguinte saída, o cloud-init já foi instalado no seu servidor e você pode continuar configurando-o para uso com a DigitalOcean:

      Output

      usage: /usr/bin/cloud-init [-h] [--version] [--file FILES] [--debug] [--force] {init,modules,single,query,dhclient-hook,features,analyze,devel,collect-logs,clean,status} ... /usr/bin/cloud-init: error: the following arguments are required: subcommand

      Se, em vez disso, você vir o seguinte, você precisa instalar o cloud-init:

      Output

      cloud-init: command not found

      Para instalar o cloud-init, atualize o índice de pacotes e em seguida instale o pacote usando o apt:

      • sudo apt update
      • sudo apt install cloud-init

      Agora que instalamos o cloud-init, vamos configurá-lo para uso com a DigitalOcean, assegurando que ele utilize o datasource ConfigDrive. O datasource do cloud-init determina como o cloud-init procurará e atualizará a configuração e os metadados da instância. Os Droplets da DigitalOcean usam o datasource ConfigDrive, por isso, vamos verificar se ele vem em primeiro lugar na lista de datasources que o cloud-init pesquisa sempre que o Droplet inicializa.

      Reconfigurando o cloud-init

      Por padrão, no Ubuntu 18.04, o cloud-init configura a si mesmo para utilizar o datasource NoCloud primeiro. Isso irá causar problemas ao executar a imagem na DigitalOcean, por isso precisamos reconfigurar o cloud-init para utilizar o datasource ConfigDdrive e garantir que o cloud-init execute novamente quando a imagem é lançada na DigitalOcean.

      A partir da linha de comando, navegue até o diretório /etc/cloud/cloud.cfg.d:

      • cd /etc/cloud/cloud.cfg.d

      Use o comando ls para listar os arquivos de configuração do cloud-init presentes dentro do diretório:

      Output

      05_logging.cfg 50-curtin-networking.cfg 90_dpkg.cfg curtin-preserve-sources.cfg README

      Dependendo da sua instalação, alguns desses arquivos podem não estar presentes. Se presente, exclua o arquivo 50-curtin-networking.cfg, que configura as interfaces de rede para seu servidor Ubuntu. Quando a imagem é lançada na DigitalOcean, o cloud-init irá executar e reconfigurar estas interfaces automaticamente, portanto esse arquivo não é necessário. Se esse arquivo não for excluído, o Droplet da DigitalOcean criado a partir dessa imagem Ubuntu terá suas interfaces configuradas incorretamente e não serão acessíveis pela internet:

      • sudo rm 50-curtin-networking.cfg

      Em seguida, vamos executar dpkg-reconfigure cloud-init para remover o datasource NoCloud, garantindo que o cloud-init procure e localize o datasource ConfigDrive usado na DigitalOcean:

      • sudo dpkg-reconfigure cloud-init

      Você deve ver o seguinte menu gráfico:

      O datasource NoCloud está inicialmente destacado. Pressione ESPAÇO para desmarcá-lo e, em seguida, pressione ENTER.

      Finalmente, navegue até /etc/netplan:

      Remova o arquivo 50-cloud-init.yaml, que foi gerado a partir do arquivo de rede cloud-init que removemos anteriormente:

      • sudo rm 50-cloud-init.yaml

      A etapa final é garantir que limpemos a configuração da execução inicial do cloud-init para que ela seja executada novamente quando a imagem for lançada na DigitalOcean.

      Para fazer isso, execute cloud-init clean:

      Neste ponto você instalou e configurou o cloud-init para uso com a DigitalOcean. Agora você pode seguir para ativar o acesso SSH ao seu droplet.

      Ativar o Acesso SSH

      Depois que você instalou e configurou o cloud-init, o próximo passo é assegurar que você tenha um usuário e senha de administrador não-root disponível para você em sua máquina, conforme descrito nos pré-requisitos. Este passo é essencial para diagnosticar quaisquer erros que possam surgir após o upload da sua imagem e o lançamento do seu droplet. Se uma configuração de rede preexistente ou uma configuração incorreta do cloud-init tornar o seu Droplet inacessível na rede, você pode utilizar esse usuário em combinação ao Console do Droplet da DigitalOcean para acessar seu sistema e diagnosticar quaisquer problemas que possam ter surgido.

      Depois que você tiver configurado seu usuário administrativo não-root, a etapa final é garantir que você tenha um servidor SSH instalado e executando. O SSH geralmente vem pré-instalado em muitas distribuições populares do Linux. O procedimento para verificar se um processo está executando irá variar dependendo do sistema operacional do seu servidor. Se você não tiver certeza de como fazer isso, consulte a documentação do seu sistema operacional sobre o gerenciamento de serviços. No Ubuntu, você pode verificar que o SSH está funcionando utilizando este comando:

      Você deve ver a seguinte saída:

      Output

      ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2018-10-22 19:59:38 UTC; 8 days 1h ago Docs: man:sshd(8) man:sshd_config(5) Process: 1092 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS) Main PID: 1115 (sshd) Tasks: 1 (limit: 4915) Memory: 9.7M CGroup: /system.slice/ssh.service └─1115 /usr/sbin/sshd -D

      Se o SSH não estiver em execução, você pode instalá-lo usando o apt (nas distribuições baseadas em Debian):

      • sudo apt install openssh-server

      Por padrão, o servidor SSH vai iniciar no boot a menos que esteja configurado de outra forma. Isso é desejável ao executar o sistema na nuvem, já que a DigitalOcean pode copiar automaticamente sua chave pública e conceder acesso SSH imediato ao seu Droplet após a criação.

      Depois que você criou um usuário administrativo não-root, ativou o SSH, e instalou o cloud-init, você está pronto para continuar criando uma imagem do seu disco de boot.

      Passo 2 — Criando uma Imagem de Disco

      Neste passo, vamos criar uma imagem de disco de formato RAW usando o utilitário de linha de comando dd, e compactá-lo usando o gzip. Vamos então carregar a imagem para o Spaces da DigitalOcean usando o s3cmd.

      Para começar, efetue login em seu servidor, e inspecione o arranjo de dispositivos de bloco para o seu sistema usando lsblk:

      Você deverá ver algo como o seguinte:

      Output

      NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT loop0 7:0 0 12.7M 1 loop /snap/amazon-ssm-agent/495 loop1 7:1 0 87.9M 1 loop /snap/core/5328 vda 252:0 0 25G 0 disk └─vda1 252:1 0 25G 0 part / vdb 252:16 0 420K 1 disk

      Nesse caso, observamos que nosso disco principal de boot é o /dev/vda, um disco de 25GB, e a partição primária, montada no /, é a /dev/vda1. Na maioria dos casos o disco contendo a partição montada no / será o disco de origem para a imagem. Vamos usar o dd para criar uma imagem do /dev/vda.

      Neste ponto, você deve decidir onde você quer armazenar a imagem de disco. Uma opção é anexar outro dispositivo de armazenamento em bloco, de preferência tão grande quanto o disco que você está fazendo a imagem. Em seguida, você pode salvar a imagem neste disco temporário anexado e enviá-la para o Spaces da DigitalOcean.

      Se você tem acesso físico ao servidor, você pode adicionar um drive adicional à máquina ou anexar outro dispositivo de armazenamento, como um disco USB externo.

      Outra opção, que iremos demonstrar nesse guia, é copiar a imagem por SSH para uma máquina local, a partir da qual você pode enviá-la para o Spaces.

      Independentemente do método escolhido, verifique se o dispositivo de armazenamento no qual você salvou a imagem compactada tem espaço livre suficiente. Se o disco que você está fazendo imagem está quase vazio, você pode esperar que o arquivo de imagem compactado seja significativamente menor que o disco original.

      Atenção: Antes de rodar o seguinte comando dd, certifique-se de que todos os aplicativos críticos tenham sido parados e seu sistema esteja o mais folgado possível. Copiar um disco sendo usado ativamente pode resultar em alguns arquivos corrompidos, portanto, certifique-se de interromper qualquer operação que use muitos dados e encerre o máximo possível de aplicativos em execução.

      Opção 1: Criando a Imagem Localmente

      A sintaxe para o comando dd que vamos executar é a seguinte:

      • dd if=/dev/vda bs=4M conv=sparse | pv -s 25G | gzip > /mnt/tmp_disk/ubuntu.gz

      Neste caso, estamos selecionando /dev/vda como o disco de entrada para se fazer imagem, e definindo o tamanho dos blocos de entrada/saída para 4MB (sendo que o padrão é 512 bytes). Isso geralmente acelera um pouco as coisas. Além disso, estamos usando a flag conv=sparse para minimizar o tamanho do arquivo de saída pulando o espaço vazio. Para aprender mais sobre parâmetros do dd, consulte a sua manpage.

      Em seguida, fazemos um pipe da saída para o utilitário de visualização de pipe pv para que possamos acompanhar o progresso da transferência visualmente (esse pipe é opcional e requer a instalação do pv usando o gerenciador de pacotes). Se você sabe o tamanho do disco inicial (nesse caso é 25GB), você pode adicionar -s 25G ao pipe do pv para ter uma estimativa de quando a transferência será concluída.

      Fazemos então um pipe de tudo isso para o gzip e salvamos em um arquivo chamado ubuntu.gz no volume de armazenamento de bloco temporário que anexamos ao servidor. Substitua /mnt/tmp_disk com o caminho para o dispositivo de armazenamento externo que você anexou ao seu servidor.

      Opção 2: Criando a Imagem via SSH

      Em vez de provisionar armazenamento adicional para sua máquina remota, você também pode executar a cópia via SSH se tiver espaço em disco suficiente disponível na sua máquina local. Observe que, dependendo da largura de banda disponível para você, isso pode ser lento e você pode incorrer em custos adicionais para a transferência de dados pela rede.

      Para copiar e compactar o disco via SSH, execute o seguinte comando em sua máquina local:

      • ssh usuário_remoto@ip_do_seu_servidor "sudo dd if=/dev/vda bs=4M conv=sparse | gzip -1 -" | dd of=ubuntu.gz

      Neste caso, estamos fazendo SSH para o nosso servidor remoto executando o comando dd lá, e fazendo um pipe da saída para o gzip. Em seguida, transferimos a saída do gzip pela rede e a salvamos localmente como ubuntu.gz. Certifique-se de que você tenha o utilitário dd disponível em sua máquina local antes de executar esse comando:

      Output

      /bin/dd

      Crie o arquivo de imagem compactado usando qualquer um dos métodos acima. Isso pode levar várias horas, dependendo do tamanho do disco que você está criando e do método que você está usando para criar a imagem.

      Depois de criar o arquivo de imagem compactado, você pode passar a enviá-lo para seus Spaces da DigitalOcean usando o s3cmd.

      Passo 3 — Fazendo Upload da Imagem para Spaces e Custom Images

      Conforme descrito nos pré-requisitos, você deve ter o s3cmd instalado e configurado para uso com seu Space da DigitalOcean na máquina que contém sua imagem compactada.

      Localize o arquivo de imagem compactado e faça o upload dele para seu Space usando o s3cmd:

      Nota: Você deve substituir your_space_name pelo nome do seu Space e não a sua URL. Por exemplo, se a URL do seu Space é https://example-space-name.nyc3.digitaloceanspaces.com, então o nome do seu Space é example-space-name.

      • s3cmd put /caminho_da_imagem/ubuntu.gz s3://your_space_name

      Quando o upload estiver concluído, navegue até seu Space usando o Painel de Controle da DigitalOcean, e localize a imagem na lista de arquivos. Tornaremos a imagem publicamente acessível temporariamente para que o Custom Images possa acessá-la e salvar uma cópia.

      À direita da lista de imagens, clique no menu suspenso More e, em seguida, clique em Manage Permissions:

      Em seguida, clique no botão de opção ao lado de Public e clique em Update para tornar a imagem publicamente acessível.

      Atenção: Sua imagem estará temporariamente acessível publicamente para qualquer pessoa com o caminho do seu Space durante este processo. Se você gostaria de evitar tornar sua imagem temporariamente pública, você pode criar sua Imagem Personalizada usando a API da DigitalOcean. Certifique-se de definir sua imagem como Private usando o procedimento acima depois que sua imagem for transferida com sucesso para o Custom Images.

      Busque a URL do Spaces para sua imagem passando o mouse sobre o nome da imagem no Painel de controle, e clique em Copy URL na janela que aparece.

      Agora, navegue para Images na barra de navegação à esquerda, e depois para Custom Images.

      A partir daqui, envie sua imagem usando esta URL, conforme detalhado na Documentação de Produto do Custom Images.

      Você pode então criar um Droplet a partir desta imagem. Observe que você precisa adicionar uma chave SSH ao Droplet na criação. Para aprender como fazer isso, consulte How to Add SSH Keys to Droplets.

      Uma vez que o seu Droplet inicializa, se você puder fazer SSH nele, você lançou com sucesso a sua Imagem Personalizada como um Droplet da DigitalOcean.

      Fazendo Debug

      Se você tentar fazer SSH no seu Droplet e não conseguir conectar, certifique-se de que sua imagem atenda aos requisitos listados e tenha o cloud-init e o SSH instalados e configurados corretamente. Se você ainda não conseguir acessar o Droplet, você pode tentar utilizar o Console do Droplet da DigitalOcean e o usuário não-root que você criou anteriormente para explorar o sistema e fazer o debug das configurações de sua rede, do cloud-init e do SSH. Outra maneira de fazer o debug de sua imagem é usar uma ferramenta de virtualização como o Virtualbox para inicializar sua imagem de disco dentro de uma máquina virtual, e fazer o debug da configuração do seu sistema a partir da VM.

      Conclusão

      Neste guia, você aprendeu como criar uma imagem de disco de um sistema Ubuntu 18.04 usando o utilitário de linha de comando dd e fazer o upload dela para a DigitalOcean como uma Custom Image ou Imagem Personalizada a partir da qual você pode lançar Droplets.

      As etapas neste guia podem variar dependendo do seu sistema operacional, do hardware existente e da configuração do kernel, mas, em geral, as imagens criadas a partir de distribuições populares do Linux devem funcionar usando esse método. Certifique-se de seguir cuidadosamente as etapas de instalação e configuração do cloud-init e de garantir que o sistema atenda a todos os requisitos listados na seção pré-requisitos acima.

      Para aprender mais sobre Custom Images, consulte a documentação de produto do Custom Images.

      Por Hanif Jetha



      Source link