domingo, 26 de julho de 2015

Scripts - Pegar informações

No artigo anterior vimos que as linguagens Bash e Python poderiam ser utilizadas de modo similar, porém algumas vezes é melhor escrever um script em Bash do que em Python e vice-versa. A partir deste, vamos começar a ver alguns Casos de Uso para os scripts.


Abandonei Perl? Pessoalmente não consigo ver qualquer diferença entre Python e Perl, como o mercado chama mais para essa primeira prefiro então fixar esses artigos apenas entre Bash e Python. Porém não espere que ficarei repetindo os scripts entre uma e outra linguagem, tal como fiz até o momento, usarei ambas para diferentes scripts como forma de sempre usarmos o modo mais simples que cada linguagem oferece.

Neste artigo vamos ver como pegar informações para atividades úteis do dia a dia.

1º Problema - Para realizar alguns backups, é necessário criar 10 diretórios, abaixo de um diretório pré-determinado (/backup), com um nome que é definido em cada dia, por exemplo, se o nome for lunes, os diretórios devem ser criados como lunes1, lunes2, e assim sucessivamente.

O seguinte script em Bash resolveria facilmente este problema:
#!/bin/bash
echo "Digite o nome das pastas:"
read NOME
cd "backup/"
for NUM in `seq 1 10`; do
    mkdir "$NOME$NUM"
done
2º Problema - Em cada uma das pastas criadas deve ser criado um arquivo, e dentro deste o seguinte conteúdo: "Backup realizado no dia dd/mm/aaaa às hh:mm", com o nome de data.log. Obviamente, devemos passar para o Script o nome do dia.

Para lidar com arquivos fica mais simples se escrevermos o script em Python, do seguinte modo:
#!/usr/bin/env python
import time
arqDia = raw_input('Nome do arquivo do dia: ')
for num in range(1, 11):
    nomeArq = 'backup/' + arqDia + `num` + '/data.log'
    dataFile = open(nomeArq, 'w')
    dataFile.write("Backup realizado no dia " + time.strftime("%d/%m/%Y") + " as " + time.strftime("%H:%M:%S") + '\n')
    dataFile.close()
print "Arquivos criados"
Ou seja, executando ambos arquivos faríamos uma tarefa que provavelmente gastaríamos um bom tempo para realizá-la diariamente (agora imagine com mais pastas, mais arquivos ou várias vezes ao dia).

Perdoe-me ser repetitivo, mas peço que não interprete que ambos os scripts não poderiam ser escritos tanto em Bash como em Python. E se desejar, faça isso como forma de aprendizado.

Obrigado e até a próxima
Fernando Anselmo

domingo, 12 de julho de 2015

Scripts - Diferenças entre Bash e Python

No artigo anterior discutimos sobre a utilidade dos Scripts para o usuário do Sistema Operacional e vimos que em Linux os usuários preferem estes escritos em Bash ou Python. Vamos falar agora sobre a usabilidade na construção de Scripts escritos nessas linguagem.

Começando por sua criação, para o Linux, um dos melhores editores que conheço é chamado Kate que possui um terminal embutido, veja uma imagem dele abaixo. Já a sua localização pode variar de usuário para usuário, pessoalmente gosto de mantê-los organizados embaixo de uma única pasta.


Para criar um Script, criamos um arquivo texto comum, na primeira linha colocamos o comando que indica ao sistema qual linguagem estamos utilizando e fornecemos a permissão para o arquivo ser um executável, com o comando:
$ chmod +x [nomearquivo]
Lembre-se que, por padrão, scripts Python possuem a extensão do arquivo .py enquanto que em Bash usamos .sh, recomendo que utilizemos esta forma de modo a identificar mais facilmente os arquivos.

Não existe a menor diferença entre o que podemos conseguir com Bash ou Python, o que existe é facilidade de escrita. Por exemplo, o script a seguir dispara dois comandos para obtermos algumas informações do sistema sobre dois comandos que são muito mais úteis com seus parâmetros:
  • uname: fornece o nome do seu sistema, porém com o parâmetro -a fica mais completo.
  • df: fornece o espaço livre e ocupado de cada partição, porém com o parâmetro -h essa informação fica, visualmente falando, melhor.
O script criado em Bash para executar esses comandos, com os respectivos parâmetros, teria a seguinte codificação:
#!/bin/bash
printf "Sobre seu sistema:\n"
uname -a
df -h
Já a mesma funcionalidade se fosse escrita em Python, seria assim:
#!/usr/bin/env python
import subprocess
print "Sobre seu sistema:"
subprocess.call(["uname", "-a"])
subprocess.call(["df", "-h"])
Ou seja, notamos que neste caso Bash seria muito mais simples e fácil de entender. Mas então basta apenas usar Bash e pronto? Nem sempre, vamos comparar dois Scripts que buscam uma determinada palavra em um arquivo qualquer, para o nosso exemplo crie um arquivo chamado "arquivo.txt" com o seguinte conteúdo:
Trecho esta em 1
Aqui em dois nao tem
Em tres tem Trecho
Em quatro nao
E tem trecho em cinco, mas minusculo
Está sublinhado a palavra "Trecho" apenas para observarmos melhor onde ocorre, e em negrito a palavra iniciada com a letra em minúscula. Em Bash o script seria escrito assim:
#!/bin/bash
ARQUIVO="arquivo.txt"
TRECHO="Trecho"
TOTAL=(`tr " " "\n" < $ARQUIVO | grep $TRECHO|wc -w`)
echo "A palavra '$TRECHO' ocorre $TOTAL vezes no arquivo $ARQUIVO."
Já em Python ficaria assim:
#!/usr/bin/env python
arquivo = "arquivo.txt"
trecho = "Trecho"
total = 0
try:
    fileObject = open(arquivo)
    for lin in fileObject:
        total += lin.count(trecho)
except:
    print "Arquivo " + arquivo + " inexistente."
    sys.exit(1)
finally:
    fileObject.close()
print "A palavra '" + trecho + "' ocorre " + str(total) + " no arquivo " + arquivo + "."
Algumas observações sobre o Script em Bash, primeiro que as variáveis não obrigatoriamente devem estar em letras maiúsculas, porém o sinal de igual deve estar colado (sem uso de espaço). Segundo é que o comando colocado em TOTAL usa dois "macetes" o primeiro é que o sinal "`" não é aspas simples, mas o caractere que normalmente usamos para conseguir a crase. E finalmente o comando é uma agregação dos comandos "tr", "grep" e "wc" para conseguirmos a totalização das ocorrências.

Já em Python, apesar de muito maior acredito que seja de auto entendimento (obviamente partindo do princípio que conhece a linguagem), ou seja, no caso de uma manutenção seria muito mais simples em Python do que em Bash. Scripts devem ser usados para serem de fácil entendimento, não adianta escrevermos 3 ou 4 linhas e na hora que precisamos modificar algo ficarmos completamente perdido.

Se duvida, tente modificar ambos os scripts para localizar a palavra pouco importando letras maiúsculas ou minúsculas, veja qual dará mais trabalho.

Obrigado e até a próxima
Fernando Anselmo

domingo, 5 de julho de 2015

Scripts - Facilite seu trabalho

Uma das grandes diferenças entre usuário Linux e Windows é o modo como usam a Janela do Terminal (ou de comandos). Os usuários Windows mal sabem sua existência e só dão o comando CMD em caso de extrema necessidade, e sendo muito experientes. Acho isso uma pena pois muita coisa poderia ser facilmente resolvida através dessa janela.

Para os que vivem no mundo Linux, não se passa um único dia sem ao menos acessar essa janela. Porém, muitos a usam de modo muito primitivo, por exemplo, para realizar uma limpeza no sistema preferem abri-la e digitar a série de comandos necessários para realizar a tarefa, mesmo que isso tenha que ser feito semanalmente.

Para ambos os mundos existe a solução adotada do Grande Porte para tarefas rotineiras, a criação de arquivos BATCH - São arquivos que contém os comandos para que o Sistema Operacional realize determinadas operações de forma conjunta. No Windows esses arquivos são nomeados para .bat e contém comandos em linguagem DOS. Já no Linux isso vira a festa de linguagem, mas seu modo de execução é similar em um arquivo formato texto, colocar os códigos, fornecer a permissão de execução para o arquivo e executá-lo com o comando: ./nomearq.

Entre as principais linguagens que podemos utilizar se destacam: Bash (nativa do terminal), Python e Perl. Outro dado curioso é a extensão do arquivo que, diferente do Windows, no Linux é uma mera padronização, assim para Bash usamos a extensão .sh, em Python a extensão .py e para Perl a extensão .pl. Porém poderíamos colocar qualquer coisa que funcionaria do mesmo modo, o que indica ao sistema operacional é a primeira linha do Script (observe as diferenças abaixo).

Comparemos um laço de decisão com o comando IF nas três linguagens para verificarmos essa diferença, primeiro em Bash:
#!/bin/bash
if [ -d "/tmp" ] ; then
  echo "/tmp é um diretório"
else
  echo "/tmp não é um diretório"
fi
O equivalente em Python:
#!/usr/bin/env python
import os
if os.path.isdir("/tmp"):
  print "/tmp é um diretório"
else:
  print "/tmp não é um diretório"
E o equivalente em Perl:
#!/usr/bin/perl
if (-d "/tmp") {
  print "/tmp é um diretório";
} else {
  print "/tmp não é um diretório";
}
Talvez com um laço de repetição possamos perceber melhor essa diferença, novamente iniciando com Bash:
#!/bin/bash
for a in 1 2; do
  for b in a b; do
    echo "$a $b"
  done
done
O equivalente em Python:
#!/usr/bin/env python
for a in [1, 2]:
  for b in ['a', 'b']:
    print a, b
E o equivalente em Perl:
#!/usr/bin/perl
foreach $a ('1', '2') {
  foreach $b ('a', 'b') {
    print "$a $b\n";
  }
}
Como todas derivam do C então as diferenças entre elas são muito sensíveis. Entre essas três, as duas primeiras são preferidas pela maioria dos usuários, conforme demonstrou uma pesquisa que realizei na lista Linux Brasil, da rede social Google+:


E apenas como característica de controle, fiz a mesma pesquisa na lista Ubuntu - Linux - Brasil, na mesma rede, obtive resultados similares:


O próprio mercado já percebeu isso, essa semana contei um aumento de solicitação para programadores nas lista de emprego com conhecimento tanto em Python como Bash para Administradores de Sistema Operacional Linux. Por esse motivo, decidi escrever uma série de artigos mostrando algumas soluções administrativas para auxiliar algumas tarefas rotineiras do Linux.

Obrigado e até a próxima
Fernando Anselmo