Curso de Linux - Parte III - Shell script

Nessa aula 3 do mini curso de Linux do LKCAMP que tem como título “Desenvolva” vamos aprender um pouco mais sobre Shell script e git. Ela foi dividida em duas partes e nesse post iniciaremos com alguns conceitos de scripts em Shell.


O que é um Shell?

Primeiramente é importante entendermos o que é um Shell: ele nada mais é do que um programa que interpreta os comandos do usuário e permite acessar os recursos do Kernel. Ele pode ser em forma de terminal (CLI - Command Line Interface) ou de interface gráfica (GUI - Graphic User Interface). Em sistemas baseados em UNIX o mais comum é utilizarmos o Bash (Bourne-Again Shell). Esse será o Shell utilizado daqui para frente na criação de nosso script.


O que é um Shell script?

Agora que sabemos o que é um Shell, podemos entender o que é um Shell script: um programa escrito utilizando a linguagem do Shell, com extensão .sh. Seu objetivo é eliminar ao máximo a interação humana, sendo assim possível automatizar processos com uma espécie de “roteiro” para o Bash, com uma sequência pré definida de comandos a serem realizados.

Scripts em Shell são muito úteis para economizar tempo em tarefas rotineiras, que precisariam ser realizadas manualmente com certa frequência.

O Bash pode ser executado em dois modos: o modo interativo e o modo não interativo. Simplificadamente, o modo interativo é quando os comandos são executados com a interação de um usuário (por exemplo inserindo dados pelo teclado). Já no modo não interativo o Shell é executado a partir de uma automação (como um script).

Sintaxe da linguagem de script Bash

Seleção do Shell (Shebang)

A primeira coisa a se fazer quando vamos escrever um Shell script é selecionar qual é o Shell que irá interpretar os comandos. Isso é feito com a combinação dos símbolos “#!” e em seguida o caminho do Shell na máquina. No nosso caso, o caminho do Bash. Esse comando é conhecido como “Shebang”.

Variáveis

Assim como toda linguagem de programação, no Bash também podemos declarar variáveis e atribuir valores a elas. A declaração é feita de forma bem simples e não precisamos informar o tipo de variável. Alguns exemplos:

  • nome="Isabella"
  • mes_nascimento=9

Variáveis pré-definidas

Essas são variáveis que já possuem funcionalidades atribuídas. As principais são:

  • $? - status de saída do último comando
  • $0 - nome do script que está sendo executado
  • $# - número de parâmetros de linha de comando informados
  • $@ - valor de todos os parâmetros
  • $$ - PID (process ID) do script em execução

Variáveis globais

São as variáveis de ambiente do Bash, que já são definidas e podem ser utilizadas em vários scripts. Alguns exemplos:

  • USER - usuário do Shell
  • PWD - diretório atual do usuário
  • RANDOM - gera um número aleatório
É possível listar todas as suas variáveis de ambiente com o comando printenv.

Arrays

No Bash um array pode ser definido de uma forma bem simples, com a utilização de parênteses e do espaço como separador de cada elemento do array. Por exemplo:

  • listadecompras=("chá" "pó de café" "canela")
  • notas_calculo=(8.5 2 7)

Note que, assim como em qualquer linguagem de programação/script, para acessar os valores do array devemos considerar que seu índice se inicia no zero. Desse modo, no array listadecompras, temos que a posição 0 é igual a “chá”, a posição 1 é igual a “pó de café” e assim por diante.

Chamada e remoção de variáveis

É importante observar que, ao declarar uma variável, utilizamos simplesmente o formato nomedavariavel=“conteudo”, mas caso queira chamar uma variável para acessar seu conteúdo ao longo do código é necessário utilizar o símbolo de cifrão antes: $nomedavariavel. No caso de acessar um array teremos: ${array[posicao]}, e caso queira acessar todos os valores do array, substitua o número de uma posição específica por *.

No caso de querer remover uma variável, utilizamos o comando unset mais o nome da variável (sem o cifrão). Na prática:

  • teste="variável de teste" #cria uma variável
    echo $teste #imprive o valor da variável teste na tela
    unset teste #remove a variável teste
É importante saber que ao criar variáveis ou arrays não podemos utilizar espaço entre o nome da variável e o símbolo de atribuição, assim como entre o símbolo de atribuição e o valor armazenado na variável. Isso é uma restrição da linguagem do Bash pois ele interpreta os espaços.

Estrutura condicional

Uma condicional de if-else no Bash segue a seguinte estrutura:

  • if [ condicao ]; then
    comando
    elif [ condicao2 ]; then
    comando2
    else
    comando3
    fi

A sintaxe é bem parecida com o que conhecemos de outras linguagens de programação, com a leve diferença de que o if só se encerra com um fi ao final.

Operadores

Operadores aritméticos

São utilizados para operações matemáticas e/ou lógicas. São eles:

  • + (adição)
  • - (subtração)
  • * (multiplicação)
  • / (divisão)
  • % (módulo ou resto da divisão)
  • = (igual) OBS.: Sim, é apenas “=” e não “==”.
  • != (diferente/não igual)

Operadores booleanos

Informam como combinar condições. Podem ser de três tipos:

  • ! (diferente/negação)
  • -o (ou)
  • -a (e)
Lembrando que true -a true = true, true -a false = false, false -a false = false, true -o true = true, true -o false = true e false -o false = false.

Laços de repetição

Há dois tipos de laços principais: for e while. No Bash basicamente utilizamos o loop “for” para executar uma série de comandos um determinado número de vezes, e o comando “while” é executado enquanto uma condição for verdadeira. Exemplos:

  • for i in 1 2 3
    do
    comando
    done

O loop for acima irá executar o comando que está dentro da seção do três vezes.

  • while [ condicao ]
    do
    comando
    done

Funções

Para criar funções que deixarão seu código mais organizado, a sintaxe utilizada é:

  • funcao(){
    comandos
    }

Há ainda a possibilidade de especificar com a palavra function antes do nome da função propriamente dito. Ambas as formas são aceitas pelo Bash.


Automatizando backups com um script em Bash

Vamos agora colocar em prática e criar um Shell script para automatizar o backup de algum local de sua máquina. O primeiro passo é definir qual pasta você deseja fazer o backup e criar um arquivo com a extensão .sh para que possamos definir os comandos.

Lembrando que um script nada mais é do que uma sequência de comandos armazenados para serem executados de uma só vez pelo interpretador do Bash. Sendo assim, todos os comandos utilizados no terminal também são válidos dentro de um arquivo .sh

No terminal vá até uma pasta de sua preferência e crie um arquivo chamado backup.sh. Você pode utilizar um editor de texto de sua preferência para editar o arquivo. Aqui irei utilizar o Nano.

nano backup.sh

Dentro do arquivo, já sabemos que a primeira linha precisa ser o Shebang. Logo, vamos escrever “#!/bin/bash”.

O próximo passo é a criação de duas variáveis. Uma irá armazenar o path (caminho) da pasta que desejamos fazer backup e a outra armazena o path para onde o backup vai.

No meu caso, vou fazer um backup das minhas aplicações web que estão salvas na pasta do servidor apache da máquina, mas você pode escolher qualquer outra pasta com arquivos que ache importante!

Assim, minha variável com o caminho da pasta de backup será:

diretorio_origem="/var/www/html"

Abra um outro terminal para que possamos criar um diretório para o qual o nosso backup será direcionado. Vou criar uma pasta para os backups direto na minha home, que fica em /home/isabellabreder. Entre como root (su) e crie o diretório com o seguinte comando:

mkdir /home/{usuário}/Backup

Podemos agora criar a variável que armazena o diretório de saída. Volte para o arquivo backup.sh e insira:

diretorio_saida="/home/{usuário}/Backup"

A próxima variável que vamos criar dentro do arquivo é a que vai armazenar o formato de data para que possamos nomear os backups e saber de qual dia eles são. Repare que se dermos o comando date no terminal, o formato que aparece não é viável para nomeação de arquivos, por isso vamos utilizar o formato aaaa-mm-dd. No arquivo digite:

data=$(date +%Y-%m-%d)
Quando queremos armazenar um comando do Shell em uma variável utilizamos o formato variavel=$(comando) para que o Bash identifique que é um comando que será interpretado pelo Shell e retornará um valor a essa variável.

Para que possamos compactar e armazenar vários arquivos em um só vamos utilizar a extensão .tar.gz nos backups. Assim, nossa próxima variável será o nome dos arquivos de backup:

arquivo="backup-$data.tar.gz"

Agora, para checar se está tudo certo com nossos backups vamos criar um log file, que é um arquivo com informações sobre os eventos executados. No Linux, a pasta ideal para armazenar arquivos log fica no diretório /var/log.

logfile="/var/log/backup_diario.log"

Para que possamos acompanhar o que está acontecendo durante a realização do backup, vamos mostrar na tela que o arquivo iniciou. No arquivo backup.sh:

echo "Realizando backup da pasta $diretorio_origem para $diretorio_saida/$arquivo"
sleep 5
OBS.: A utilização do sleep 5 é puramente para uma melhor visualização do backup. O que ele faz é esperar 5 segundos antes de continuar o próximo comando.

Para compactar os arquivos de backup com o tar, vamos utilizar o seguinte comando no script:

tar -czvf $diretorio_saida/$arquivo $diretorio_origem >> $logfile

Os parâmetros que passamos para o tar vão ser responsáveis por: c: criar um arquivo .tar z: compactar os arquivos com o gzip v: exibir no terminal os processos de criação dos arquivos f: nome do arquivo que será criado Também passamos primeiro o diretório e o arquivo de destino e depois o diretório de origem. No final utilizamos o símbolo de redirecionamento (») para que o resultado dessa saída seja anexada ao nosso log file.

Por fim, podemos ainda avisar que o backup foi concluído, adicionando no arquivo backup.sh o seguinte comando:

echo "Backup concluído com sucesso"

Agora o nosso script de backup está quase pronto. Só precisamos dar permissão ao usuário para executar o arquivo backup.sh, pois ele provavelmente só estará com permissão de escrever (w) e ler (r). Para permitir a execução, vá no terminal, entre na pasta na qual criou o arquivo e digite o comando:

chmod +x backup.sh

Agora pronto! Para realizar seu backup basta rodar o script pela linha de comando:

./backup.sh
Atenção: se o seu diretório de origem do backup é uma pasta da raiz do sistema como a minha é necessário rodar o script como root (usuário superior) ou utilizar o sudo antes do comando ./backup.sh.

Agora pronto! Você já tem uma base para automatizar várias tarefas úteis para o desenvolvimento com Linux. Note que esse foi um exemplo básico, pois não é uma estratégia inteligente realizar o backup de alguma pasta do computador no próprio computador. Você pode incrementar seu script redirecionando esses arquivos de backup para algum serviço de nuvem ou até mesmo para uma mídia removível como um pen drive. Pesquisem e se divirtam!

Isso conclui a parte de Shell script do nosso mini curso de Linux!