|
|
Guia: Programando em Shell ScriptCarlos E. Morimoto 22/03/2005
Um script é um arquivo de texto, com uma seqüência de comandos que são executados linha a linha. Dentro de um script, você pode utilizar qualquer comando de terminal (incluindo programas gráficos e parâmetros para eles) e também funções lógicas suportadas pelo shell, que incluem operações de tomada de decisão, comparação, etc. Você pode até mesmo acessar bancos de dados ou configurar outras máquinas remotamente. Assim como o perl, python e o lua, o shell script é uma linguagem interpretada, onde o próprio script, escrito num editor comum é o executável. Você pode alterá-lo rapidamente e executá-lo logo em seguida para testar a mudança. Nas linguagens tradicionais, o código fonte precisa ser recompilado a cada modificação, o que toma tempo. A princípio, o shell script lembra um pouco os arquivos .bat do DOS, que também eram arquivos de texto com comandos dentro; da mesma forma que um ser humano e uma ameba conservam muitas coisas em comum, como o fato de possuírem DNA, se reproduzirem e sintetizarem proteínas. Mas, assim como um humano é muito mais inteligente e evoluído que uma ameba, um shell script pode ser incomparavelmente mais poderoso e elaborado que um simples .bat do DOS. É possível escrever programas complexos em shell script, substituindo aplicativos que demorariam muito mais tempo para ser escritos em uma linguagem mais sofisticada. Seus scripts podem tanto seguir a velha guarda, com interfaces simples de modo texto (ou mesmo não ter interface alguma e serem controlados através de parâmetros), de forma a desempenhar tarefas simples, quanto possuir uma interface gráfica elaborada, escrita usando o kommander e funções do kdialog. Isso vai de encontro à idéia que muitas pessoas, incluindo até mesmo usuários Linux tarimbados, possuem. O uso de scripts pode ir muito além de simples scripts de configuração. Você pode desenvolver programas bastante complexos se usar as ferramentas certas. Um exemplo de trabalho desenvolvido em shell script é o painel de controle do Kurumin, que utiliza um conjunto de painéis gráficos, criados usando o Kommander, que ativam um emaranhado de scripts para desempenhar as mais diversas tarefas.
O programa de instalação do Kurumin também é escrito em shell script, assim como a maior parte dos programas encarregados de configurar o sistema durante o boot, os painéis para instalar novos programas, configurar servidores e tudo mais. O principal motivo para uso de scripts em shell ao invés de programas escritos em C ou C++, por exemplo, é a rapidez de desenvolvimento, combinada com a facilidade de editar os scripts existentes para corrigir problemas ou adicionar novos recursos. Você vai encontrar uma grande quantidade de scripts em qualquer distribuição Linux, incluindo os próprios scripts de inicialização.
O básico
O primeiro passo para escrever um script é descobrir uma forma de fazer o que precisa via linha de comando. Vamos começar um um exemplo simples: O comando "wget" permite baixar arquivos; podemos usá-lo para baixar o ISO do Kurumin, por exemplo:
$
wget -c http://fisica.ufpr.br/kurumin/kurumin-6.0.iso Depois de baixar o arquivo, é importante verificar o md5sum para ter certeza que o arquivo está correto: $ md5sum kurumin-6.0.iso Estes dois comandos podem ser usados para criar um script rudimentar, que baixa o Kurumin e verifica o md5sum. Abra o kedit ou outro editor de textos que preferir e inclua as três linhas abaixo:
#!/bin/sh O "#!/bin/sh" indica o programa que será usado para interpretar o script, o próprio bash. Por norma, todo script deve começar com esta linha. Na verdade, os scripts funcionam sem ela, pois o bash é o interpretador default de qualquer maneira, mas não custa fazer as coisas certo desde o início. Existe a possibilidade de escrever scripts usando outros interpretadores, ou mesmo comandos, como o sed. Neste caso o script começaria com "#!/bin/sed", por exemplo. Note que a tralha, "#", é usada para indicar um comentário. Toda linha começada com ela é ignorada pelo bash na hora que o script é executado, por isso a usamos para desativar linhas ou incluir comentários no script. A linha "#!/bin/sh" é a única exceção para esta regra. Ao terminar, salve o arquivo com um nome qualquer. Você pode usar uma extensão como ".sh" para que outras pessoas saibam que se trata de um shell script, mas isto não é necessário. Lembre-se de que, no Linux, as extensões são apenas parte do nome do arquivo. Marque a permissão de execução para ele nas propriedades do arquivo, ou use o comando: $ chmod +x baixar-kurumin.sh Execute-o colocando um "./" na frente do nome do arquivo, o que faz o interpretador entender que ele deve executar o "baixar-kurumin.sh" que está na pasta atual. Caso contrário ele tenta procurar nas pastas "/bin/", "/usr/bin" e "/usr/local/bin" que são as pastas onde ficam os executáveis do sistema e não acha o script. $ ./baixar-kurumin.sh O md5sum soma os bits do arquivo e devolve um número de 32 caracteres. No mesmo diretório do servidor onde foi baixado o arquivo, está disponível um arquivo de texto com o md5sum correto do arquivo. O resultado do md5sum do arquivo baixado deve ser igual ao do arquivo, caso contrário significa que o arquivo veio corrompido e você precisa baixar de novo. Você já deve estar cansado de baixar as novas versões do Kurumin, e já sabe de tudo isso. Podemos aproveitar para ensinar isso ao nosso script, fazendo com que, depois de baixar o arquivo, ele verifique o md5sum e baixe o arquivo de novo caso ele esteja corrompido. Isto vai deixar o script um pouco mais complexo: #!/bin/sh
versao="6.0"
wget
-c "$mirror"/kurumin-"$versao".iso
wget
-c "$mirror"/kurumin-"$versao".md5sum.txt
if
[ "$md5sum" != "$md5sumOK" ]; then Você vai perceber que ao executar este segundo script, ele vai tentar baixar o arquivo novamente sempre que o md5sum não bater, se necessário várias vezes. Para isso, começamos a utilizar algumas operações lógicas simples, que lembram um pouco as aulas de pseudo-código que os alunos de Ciências da Computação têm no primeiro ano. Em primeiro lugar, este segundo script usa variáveis. As variáveis podem armazenar qualquer tipo de informação, como um número, um texto ou o resultado de um comando. Veja que no início do script estou definindo duas variáveis "versao" e "mirror", que utilizo em diversas partes do script. Ao armazenar qualquer texto ou número dentro de uma variável, você passa a poder utilizá-la em qualquer situação no lugar no valor original. A vantagem de fazer isso é que, quando precisar alterar o valor original, você só vai precisar alterar uma vez. O mesmo script poderia ser adaptado para baixar uma nova versão do Kurumin, ou para baixá-lo a partir de outro mirror simplesmente alterando as duas linhas iniciais. Usar variáveis desta forma permite que seus scripts sejam reutilizáveis, o que a longo prazo pode representar uma grande economia de tempo. No script anterior, usamos o comando "md5sum kurumin-6.0.iso". Ele simplesmente mostra o md5sum do arquivo na tela, sem fazer mais nada. No segundo script, esta linha ficou um pouco diferente: md5sum=`md5sum kurumin-$versao.iso`. A diferença é que, ao invés de mostrar o mds5um na tela, armazenamos o resultado numa variável, chamada "md5sum". O sinal usado aqui não é o apóstrofo, como é mais comum em outras linguagens, mas sim a crase (o mesmo do "à"). O shell primeiro executa os comandos dentro das crases e armazena o resultado dentro da variável, que podemos utilizar posteriormente. Por padrão, os mirrors com o Kurumin sempre contém um arquivo ".md5sum.txt" que contém o md5sum da versão correspondente. Para automatizar, o script baixa também este segundo arquivo e armazena o conteúdo numa segunda variável, a "md5sumOK". Neste ponto, temos uma variável contendo o md5sum do arquivo baixado, e outra contendo o md5sum correto. As duas podem ser comparadas, de forma que o script possa decidir se deve baixar o arquivo de novo ou não. Para comparar duas variáveis (contendo texto) num shell script, usamos o símbolo "!=" (não igual, ou seja: diferente). Para saber se o arquivo foi baixado corretamente, comparamos as duas variáveis: [ "$md5sum" != "$md5sumOK" ]. Além do "!=", outros operadores lógicos que podem ser usados são:
=
: Igual. Estas funções permitem comparar strings, ou seja, funcionam em casos onde as variáveis contém pedaços de texto ou o resultado de comandos. O bash também é capaz de trabalhar com números e inclusive realizar operações aritméticas. Quando precisar comparar duas variáveis numéricas, use os operadores abaixo:
-lt : (less
than), menor que, equivalente ao <. Mas, apenas comparar não adianta. Precisamos dizer ao script o que fazer depois. Lembre-se de que os computadores são burros, você precisa dizer o que fazer em cada situação. Neste caso temos duas possibilidades: o md5sum pode estar errado ou certo. Se estiver errado, ele deve baixar o arquivo de novo, caso contrário não deve fazer nada. Usamos então um "if" (se) para criar uma operação de tomada de decisão. Verificamos o mds5um, se ele for diferente do correto, então (then) ele vai deletar o arquivo danificado e começar o download de novo. Caso contrário (else) ele vai simplesmente escrever uma mensagem na tela.
if
[ "$md5sum" != "$md5sumOK" ]; then Veja que dentro da função "then" usei o comando para deletar o arquivo e depois executei de novo o "./baixar-kurumin.sh" que vai executar nosso script de novo, dentro dele mesmo. Isso vai fazer com que o script fique em loop, obsessivamente, até conseguir baixar o arquivo corretamente. Uma coisa interessante nos scripts é que eles podem ser executados dentro deles mesmos e alterados durante a execução. O script pode até mesmo deletar a si próprio depois de rodar uma vez, uma espécie de script suicida :-P. É preciso tomar cuidado em situações como esta, pois cada vez que o script executa novamente a si mesmo para tentar baixar o arquivo, é aberta uma nova seção do shell, o que consome um pouco de memória. Um script que entrasse em loop poderia consumir uma quantidade muito grande de memória, deixando o sistema lento. Para evitar isso, incluí um "sleep 120", que faz o script dar uma pausa de 120 segundos entre cada tentativa.
Existem vários programas gráficos que permitem fazer a conversão, entre eles o Grip. Mas, esse é o tipo de coisa que é mais rápido de fazer via linha de comando, usando o lame, como em: $ lame -b 128 musica.mp3 128k-musica.mp3 Aqui é gerado o arquivo "128k-musica.mp3" (na mesma pasta), encodado com 128k de bitrate, sem modificar o arquivo original. Para fazer o mesmo com todos os arquivos no diretório, você poderia usar o comando "for", que permite realizar a mesma operação em vários arquivos de uma vez. Ele é muito usado para renomear ou converter arquivos em massa, baseado em determinados critérios. No nosso caso ele poderia ser usado da seguinte forma:
for
arquivo in *.{mp3,MP3} Aqui, a regra se aplica a todos os arquivos dentro do diretório atual que tiverem extensão ".mp3" ou ".MP3". Para cada um dos arquivos é executado o comando 'lame -b 128 "$arquivo" "128k-$arquivo"', onde o "$arquivo" é substituído por cada um dos arquivos dentro do diretório.
|