Shell Script: Programação Simplificada – Parte II
Como prometido, continuemos com a segunda parte do artigo.
Variáveis Padrão do Ambiente
Existem inúmeras variáveis que são utilizadas por programas executados em um Shell. Um programa pode necessitar da variável $USER para identificar qual o nome do usuário que está executando um determinado programa. Usuários podem possuir permissões diferentes em diferentes programas. Outro exemplo comum é a utilização da variável $HOME, que define o diretório padrão de cada usuário no Sistema Operacional.
Algumas Variáveis Padrão do Ambiente
Variável $PATH
Esta variável contém a lista de diretórios que o Shell irá verificar toda vez que um programa for executado. Se o valor da variável $PATH for /bin:/usr/bin:/sbin e um usuário executar o comando “ls”, o Shell irá buscar por /bin/ls, /usr/bin/ls e finalmente /sbin/ls.
Uma diferença importante entre o DOS/WINDOWS é que a variável $PATH do Unix/Linux não inclui o diretório atual no PATH, sendo assim se um programa for executado e o mesmo não estiver em um diretório definido na variável $PATH, o Unix/Linux não conseguirá encontrá-lo. Neste caso pode-se utilizar a chamada local do programa, utilizando o “./”.
$ bash
bash# ls
Applications Library
Desktop Movies
Documents Music
Downloads Parallels
Favorites Pictures
Games Public
bash# cat busca
ls -lart /home/
bash# busca
-bash: busca: command not found
bash# ./busca
92 15 Mar 09:37 ..
1 31 Mai 14:20 .
bash#
Listagem 14. Verificando caminhos Default ($PATH)
Variável $PWD
A variável $PWD é alterada cada vez que a sessão de um Shell troca de diretório, ou seja, esta variável sempre armazena o diretório atual de uma sessão.
Variável $TERM
Esta variável contém informações sobre o terminal que está sendo utilizado em uma sessão aberta. Se for utilizado um programa que emula um terminal “xterm”, então a variável $TERM mostrará o conteúdo xterm.
Variável $Shell
Esta variável armazena o Shell em utilização: bash, sh, csh, etc.
Prós da utilização de Shell Script
A maioria das tarefas que se repetem são boas candidatas para criação de scripts Shell. Scripts não se esquecem de passo algum. Scripts Shell funcionam mais rapidamente, cometem menos erros e podem focar em tarefas específicas de um script.
Mesmo que uma determinada tarefa necessite de parâmetros diferentes em situações diferentes, pode-se adaptar um script Shell para receber, tratar e alterar estes parâmetros.
Scripts Shell podem ainda atender demandas para pequenas ou grandes necessidades. Uma rotina composta de muitas tarefas pode ser dividida em vários scripts que se relacionam e resolvem uma tarefa complexa, isso não só automatiza a execução da tarefa, mas também diminui a chance de pontos de falha.
Portabilidade é outra vantagem de utilizar scripts Shell. Pode-se utilizar o mesmo script em diferentes plataformas UNIX ou LINUX, uma vez que pode-se escolher o Shell conforme necessidade de cada plataforma.
Contras da utilização de Shell Script
Uma recomendação válida para a programação Shell script é manter os scripts curtos. Para um programa ou tarefa muito complexo (ex: 1000 linhas) é mais interessante utilizar linguagens mais estruturadas como Perl, Python, etc.
Scripts Shell são bons para processar comparativos entre strings, processar arquivos textos, tratar variáveis entre outras. De qualquer forma é um recurso limitado para calcular operações aritméticas, onde deve-se tomar um cuidado especial com números decimais, neste caso recomenda-se uma linguagem mais estruturadas.
Executando Scripts Shell
Uma vez criado o script, o mesmo pode ser executado de várias maneiras. Primeiro, pode-se passar como um argumento do Shell:
$ bash nome_do_script.sh
Listagem 15. Executando scripts especificando o nome do Shell
Pode-se também executar o script de maneira direta:
$ ./nome_do_script.sh
Listagem 16. Executando scripts de maneira direta
Quando um script é executado diretamente, o Shell procura pelo “número mágico” (#!) na primeira linha do script. Se este caractere existir, então o script irá utilizar o Shell especificado. Caso este caracter não existir, então o script será executado no Shell da sessão atual / padrão. É extremamente recomendável especificar o Shell desejado em todos os scripts desenvolvidos.
#!/bin/bash
ls –lrt /home/oracle
sqlplus / @teste.sql
exit
Listagem 17. Especificando o Shell dentro de Scripts
É importante lembrar que para executar um script qualquer, o mesmo deve possuir permissões para execução. Essas permissões devem ser concedidas através do comando “chmod”:
$ chmod a+c nome_do_script.sh
$ chmod 755 nome_do_script.sh
Listagem 18. Garantindo permissões de execução para scripts Shell
Jobs e Alias
Todos os Shells ainda suportam a utilização de Jobs agendados ou não, considerados como processos dentro do Sistema Operacional. Um Job tem por definição executar uma ou mais tarefas distintas ou ainda dentro de vários scripts Shell previamente criados. A função de um Job é facilitar a execução de tarefas repetitivas: Backups, Coletas, Relatórios, etc. Como um Job é um processo, cada Job possui seu PID específico no sistema operacional.
Existem três tipos de Jobs: Primeiro Plano (Foreground), Segundo Plano (Background) e Parado (Stopped).
Foreground: Este ocorre quando um Job é executado dentro de uma janela de terminal e utiliza esse terminal até o encerramento do Job, não permitindo assim a execução de outras tarefas neste terminal.
Background: Este ocorre quando um determinado Job é executado via agendador de tarefas (CRONTAB) ou manualmente porém a utilização do símbolo “&” ao final do comando. Neste caso o Job será colocado em processamento sem utilizar ou “bloquear” a utilização do terminal corrente, permitindo assim o usuário executar outras tarefas paralelas.
Stopped: Se durante a execução de um Job, no mesmo terminal, foi pressionado a combinação de teclas “CONTROL +Z” então este Job será parado com status “stopped”, mas o processo no sitema operacional continuará aguardando a retomada ou encerramento do Job.
A utilização de Alias é muito comum para facilitar a chamada de comandos com grande quantidade de parâmetros. Pode-se criar inúmeras aliases em um Shell Unix ou Linux. Todas as aliases criadas são armazenadas pelo Shell e relacionadas aos comandos desejados. Existem algumas regras tais quais: Não podem existir espaços em branco ao lado do sinal de igualdade (=). O comando de criação deve conter aspas caso o mesmo contenha parâmetros os metacaracteres. Cada comando de um único Alias deve ser separado por ponto e vírgula (;).
$ alias info=’uname –a; id; date’
Listagem 19. Exemplo de criação de Alias
Para remover um alias, deve-se utilizar o caracter () antes do nome do arquivo durante o comando “rm”.
A utilização de Alias não se restringe apenas em linha de comando dentro de um Terminal qualquer, um Alias pode ser utilizado dentro de scripts que compõem ou não um determinado Job.
Scripts dentro de Scripts
Todo e qualquer Script Shell por ser tratar de um programa computacional pode ser tratado com os mesmos conceitos de um programa comum.
Os scripts podem ser executados através de chamadas dentro de outros scripts de maneira direta, indireta ou com especificação do Shell. Pode-se também utilizar o conceito de recursividade dentro de programas escritos em Shell Script, onde um script para atuar conforme saída ou retorno do script anterior.
Este conceito de chamada recursiva é de comum uso com estruturas de controle como “for”, “while” e outras, onde o resultado de um script serve como entrada para outro script.
10 Dicas para Programar em Shell Script
É muito comum que em alguns casos, estes profissionais tenham dúvidas para desenvolver programas na linguagem Shell devido a dúvidas no conceito e funcionalidades do Shell (bash, csh, ksh, sh) no sistema operacional.
Para facilitar o entendimento e simplificar sua programação, existem algumas regras Básicas:
1 – Especificar qual Shell será utilizado
É pré-requisito em qualquer programa escrito em Shell SCRIPT definir qual será o Shell que será utilizado. Isso garante que o Sistema Operacional irá interpretar e executar todas as instruções do script com o interpretador correto.
#!/bin/bash
# Procedimento - Backup Database FULL.
# Data: 30-05-2012
# Por: Victor Armbrust
# VictorDBA.net
Listagem 20. Especificar qual Shell será utilizado
Na linha 1 o Shell é especificado.
2 – Comentários e descrição do Script
Esta sessão tem como objetivo descrever o objetivo do script e suas funcionalidades. Isso ajudará o desenvolvedor a lembrar porque o script foi escrito, e para qual função.
#!/bin/bash
# Procedimento - Backup Database FULL.
# Data: 30-05-2012
# Por: Victor Armbrust
# VictorDBA.net
Listagem 21. Manter comentários e descrição do Script
Após a linha 1 é definida a descrição do script.
3 – Declara Variáveis
É muito importante garantir que todas as variáveis necessárias para execução de seu programa sejam declaradas. É recomendável fazer esta declaração no início do script.
Lembre-se: Quando o script é executado será aberto um novo Shell, com isso, nenhuma variávei declarada na sessão atual será utilizada. Declarar variáveis é PRIMORDIAL, assim como em qualquer outra linguagem de programação.
#!/bin/bash
# Procedimento - Backup Database FULL.
# Data: 30-05-2012
# Por: Victor Armbrust
# VictorDBA.net
export TEMP=/tmp
export TMPDIR=/tmp
export ORACLE_SID=$1
export ORACLE_BASE=/u/oracle
export ORACLE_HOME=$ORACLE_BASE/product/10.2.0/db_1
export PATH=$ORACLE_HOME/bin:$PATH:/usr/bin/usr/local/bin
export ORACLE_OWNER=oracle
case "$ORACLE_SID" in
pback1*)
export BKPDIR=/u5/backup/rman/pback
;;
pback2*)
export BKPDIR=/u5/backup/rman/pback
;;
*)
export BKPDIR=/backup/rman/${ORACLE_SID}
;;
esac
data=`date +%d%m%y%H`
LOG=/logs/backup_diario_${ORACLE_SID}_$data.log
DH=`date +%Y%m%d-%H%M`
DTIME=`date "+%m%d%y_%H%M"`
TAG=hot_disk_${ORACLE_SID}_${DTIME}
Listagem 22. Declarar todas as variáveis no início do script
Após a linha 5 é feita a declaração e tratamento de variáveis.
4 – Edentação
Muitas pessoas acreditam que edentar scripts não é necessário. Para garantir o funcionamento do script realmente não é, porém para entendimento próprio ou de outro analista que venha futuramente utilizer o script, é extremamente necessário. Edentação é sinônimo de organização e facilita o entendimento posterior.
case "$ORACLE_SID" in
pback1*)
export BKPDIR=/u5/backup/rman/pback
;;
pback2*)
export BKPDIR=/u5/backup/rman/pback
;;
*)
export BKPDIR=/backup/rman/${ORACLE_SID}
;;
esac
Listagem 23. Manter Edentação
5 – Comentários fase-a-fase
Procure descrever em comentários o que cada parte do script irá executar. Isso ajuda a realizer melhorias e “debugar” possíveis problemas futuros.
Os comentários também ajudam a dividir o script em etapas e facilitam o entendimento de estruturas de controle, procedimentos, etc.
################################################
## Fase 1 - Apagar Backup Database $ORACLE_SID FULL ##
################################################
Listagem 24. Manter comentários fase a fase
6 – Logs
Mantenha logs de todos os seus scripts. Preferencialmente especificando o arquivo de LOG dentro do script, como variável. Para análise posterior em execuções será muito mais fácil encontrar possíveis erros.
Utilizar arquivos de LOGs com controle de datas é uma maneira de organizer o histórico de execuções, prevenindo que logs de execuções anteriores sejam sobrescritos.
data=date +%d%m%y%H
LOG=/logs/backup_diario_${ORACLE_SID}_$data.log
DH=date +%Y%m%d-%H%M
Listagem 25. Geração de Logs
7 – Corpo do Script (Body)
Utilize suas variáveis declaradas no início do script. Isso ajuda a não fixar valores e facilita a alteração do script.
$ORACLE_HOME/bin/rman target / nocatalog <<EOF >> $LOG
RUN {
sql 'alter system archive log current';
sql 'alter system switch logfile';
BACKUP FORMAT '$BKPDIR/bkp_db.bkp' DATABASE TAG=${TAG};
BACKUP FORMAT '$BKPDIR/bkp_arc.bkp' ARCHIVELOG ALL TAG=${TAG};
BACKUP FORMAT '$BKPDIR/bkp_ctrl.bkp' CURRENT CONTROLFILE TAG=${TAG};
BACKUP FORMAT '$BKPDIR/spfile_%s_%p_%t' SPFILE TAG=${TAG};
}
Listagem 26. Utilização de Variáveis no corpo do script
8 – Validação da execução de cada comando
De nada adianta um script que executa 100 tarefas e nenhuma possui validação. Este é um dos “erros” mais comuns em programação Shell. Um commando executado sem análise de retorno (“Return Code”) não possui integridade alguma. Procure sempre analisar passo-a-passo sua execução.
RETVAL=$?
if test "$RETVAL" != "0"
then
echo " " >> $LOG
echo "****Erro Fase 2: Gerar Backup. returcode $RETVAL" >> $LOG
echo " " >> $LOG
exit 0
fi
Listagem 27. Validar código de retorno
9 – Nomes Coerentes
Procure manter o nome de seus scripts de forma coerente. É sempre mais fácil para encontrar scripts que possuam relação entre seu nome e a atividade que o mesmo executa.
Ex:
Backup Hot Online Completo do Oracle Database
“bkp_rman_full.sh”
Backup de Todas as Tabelas do Oracle Database
“bkp_expdp_full.sh”
Listagem 28.Manter nomes de arquivos coerentes
10 – Validação das execuções de Scripts
Este provavelmente é o passo mais importante. Valide as execuções de seus scripts, acompanhe os logs (diários, mensais, etc), neles você poderá encontrar erros ou melhorias. Sempre que possível, implemente algum recurso de monitoração.
CRONTAB
As dicas acima são válidas também para execução de scripts via agendador de tarefas do Linux/Unix, o CRONTAB. O daemon “crond” é executado em Shell separado, e também exige que todos os comandos e variáveis sejam corretamente definidos.
Existem diversas regras e dicas que podem ser seguidas para otimizar as funcionalidades de seus scripts, essas são apenas algumas.
Procure sempre manter a organização e o fácil entendimento para que não ocorram futuros “desconfortos”.
Conclusões
A Programação Shell script pode ajudar de diversas maneiras na automatização de tarefas e administração de sistemas e aplicativos em plataformas UNIX e LINUX. Como demonstrado é extremamente importante dominar e ponderar a utilização deste recurso de programação, sempre visando melhorias em segurança e minimização de falhas. Existem inúmeros recursos disponíveis ao desenvolvedor em várias distribuições de cada Shell, é importante entendê-los para atingir resultados proveitosos.
Atualmente o Linux é um Sistema Operacional maduro e com grande utilização no mercado. Nas atuais distribuições o Shell mais utilizado é o Bourne-Again Shell, que é extremamente confiável e estável. É uma ótima opção para escrever scripts em Shell e definir estratégias para rotinas comuns do dia-a-dia.
Referências
- Visão Geral sobre Shell Script http://pt.wikipedia.org/wiki/Shell_script
- Learning the Korn Shell (2002 – 2nd Edition – 434pgs) O’Reilly Media, ISBN-10: 0596001959,Bill Rosenblatt, Arnold Robbins
- Linux Command Line and Shell Scripting Bible, (2011 – 2nd Edition – 840pgs) Wiley, ISBN-10: 1118004426, Richard Blum, Christine Bresnahan
- GNU Operating System http://www.gnu.org/software/bash/