Este Blog é Reconhecido pela

quarta-feira, 24 de outubro de 2012

Shell Script: Programação Simplificada - Parte I


Para administração de  Sistemas Operacionais Unix/Linux ou qualquer produto que seja instalado nestas plataformas é fundamental o conhecimento, pelo menos básico, da linguagem Shell. A Necessidade está diretamente ligada ao desenvolvimento de programas (ou scripts) para automatização ou execução de alguma tarefa específica. Este artigo tem como principal objetivo demonstrar algumas das melhores práticas para programação na Linguagem Shell. 

Programar em linguagem Shell é algo muito comum para profissionais que atuam na área de Banco de Dados (DBA), Administradores de Sistemas Operacionais UNIX/LINUX (SysAdmin) e outros que necessitem automatizar ou executar tarefas específicas através de scripts previamente escritos.

A linguagem Shell, assim como qualquer outra linguagem de programação, possui uma série de regras e controles que devem ser definidas pelo programador antes, durante e ao término de cada programa.


O que é o Shell?

Sistemas UNIX/Linux são desenhados para ter o Kernel como centro de todas as atividades.  O Kernel é responsável pela comunicação entre o Sistema Operacional e dispositivos externos, bem como tarefas e processos.
Usuários normais por outro lado, não interagem diretamente com o Kernel. Essa interação é feita através de um Shell. O Shell é um interpretador de comandos que também pode gerenciar outros programas e permitir a criação de scripts para automatizar diversas tarefas do sistema.

Existem vários tipos de Shell disponíveis na maioria das distribuições Unix/Linux, entre eles:


Bourne Shell (sh)

Conhecido como “sh” este Shell substituiu o anterior Thompson Shell (Conhecido também como “sh”) incorporando novas funcionalidades. Foi desenvolvido por Stephen Born e lançado em 1977. O Executável deste Shell fica localizado em “/bin/sh” em distribuições UNIX. Algumas Características:

- Shell com mais portabilidade para programação (Shell Script).
- Linguagem baseada em Algol.
- Possui histórico de comandos, edição e aliases.
- Usa o símbolo $ como prompt default.
- Parte do Unix; Não disponível em Linux.


C Shell (csh)

Este também é um Shell desenvolvido a partir da versão Thompson Shell (antecessora da versão Bourne Shell) . Sua sintaxe é modelada segundo a linguagem de programação C, com estruturas de controle e comandos semelhantes. Possui algumas melhorias em relação ao Bourne Shell tais como aliases e histórico de comandos. Foi desenvolvido por Bill Joy. Algumas Características:

- Não compatível com scripts Bourne Shell.
- Linguagem baseada em C.
- Possui histórico de comandos, auto-completar, programação (scripting), aliases e controle de Jobs.
- Usa o símbolo % como prompt default.


Korn Shell (ksh)

Um dos mais populares.  É uma derivação do Bourne Shell (bsh) e do C Shell (csh). Possui a maioria das suas funcionalidades de ambos incluindo outras novas como interação con outras linguages como awk, icon, perl e tcl. Foi desenvolvido por David G. Korn e vem sido muito utilizado desde 1982. Algumas Características:

- Compatível com scripts Bourne Shell.
- Certificado como Open Source (OSI)
- Possui histórico de comandos, auto-completar, programação (scripting), aliases e controle de Jobs.
- Inclui estilo “emacs” como alternativa para o CSH e POSIX.
- Por muitos anos foi exclusivo de uso em UNIX devido a licenciamento.
- Atualmente encontrado em várias distribuições Linux (Open Source).


Bourne-Again Shell (bash)

Este é o Shell mais conhecido atualmente no mercado. Desenvolvido com apelo de distribuição FREE (GNU Free Software Foundation), se tornou padrão na maioria das distribuições Linux atuais como Red Hat, Suse, Oracle Linux entre outras. O BASH possui a maioria das funcionalidades do C Shell e do Korn Shell. Trabalha em conformidade com POSIX e padrões de ferramentas Shell. O BASH ainda oferece diversas melhorias tanto para programação como para uso interativo, tais como:

- Edição de Linha de Comando.
- Histórico de Comandos ilimitado.
- Controle de Jobs e Tarefas Agendadas.
- Funções Shell e Criação de Alias.
- Matrizes Indexadas ilimitadas.
- Operações Aritméticas.
- Programação e  personalização.
- Compatibilidade com scripts Bourne Shell.
- Executável /bin/bash.


Shell alternativo

A lista anterior fornecida é sem dúvida a mais comum encontrada no mercado. Existem vários outros Shell’s disponíveis e podem ser dividos em 2 (duas) categorias: Open Source (Alternativos ao Shell proprietário) e Shell especializado. Alguns Shell especializados são: tcsh, pdksh e zsh.


Enhanced C Shell (tcsh)

Ao contrário do que se vê normalmente, a abreviação tsch “The Enhanced C Shell” o  “t” na verdade vem de TENEX (sistema operacional que inspirou a utilização do “auto-completar” compatível com o C Shell. Algumas Características:

- Compatível com Scripts C Shell.
- Possui edição de comandos e correção ortográfica.
- Auto-Completar corrigido e melhor em relação ao csh.
- Licenciamento Open Source.


Public Domain Korn Shell (pdksh)

Enquanto o Korn Shell é mantido como proprietário em plataformas UNIX, o Public Domain Korn Shell foi criado como alternativa de compatibilidade para:

- Scripts ksh88.
- Software Open Source (public domain).


Z Shell (zsh)

Inclui a maioria dos recursos do Bourne-Again Shell, Korn Shell e Enhanced C Shell. Inclui novas funcionalidades próprias:

- Pode ser executado no Korn ou Bourne Shell em modo de compatibilidade.
- Um dos Shell com mais compatibilidade e funcionalidades.
- Free. Open Source.


Arquivos de configuração do Shell

Quando um novo Shell é iniciado, o mesmo lê alguns arquivos de configuração que configuram o ambiente para o Shell que será executado. Entender os arquivos de configuração do Bourne Shell é muito importante, uma vez que a maioria dos outros Shells mantém compatibilidade com o Bourne Shell e lê seus arquivos de configuração, se os mesmos estiverem presentes. O Bourne Shell mantém suas configurações em 2 (dois) arquivos. Estes arquivos são utilizados por todos os Shells, uma vez que não exista o arquivo específico de cada Shell no diretório $HOME. A configuração do ambiente (Sistema) é mantida no arquivo /etc/profile. Algumas configurações de ambiente (sistema):

Path default onde estão localizados os programas executáveis.
Configurações default de prompt.
Limites para sessão de Usuários (ulimit)

Para facilitar que outros software alterem de maneira segura o arquivo de configuração do Shell, o Linux também interpreta scripts encontrados no diretório /etc/profile.d.

Abaixo arquivo /etc/profile no Linux:

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "$PS1" ]; then
            . $i
        else
            . $i >/dev/null 2>&1
        fi
    fi
done

Listagem 1. Arquivo /etc/profile


Arquivo ˜/.profile

O arquivo de configuração de usuário também é executado, caso exista. Este arquivo fica localizado no home ($HOME) de cada usuário. Ele permite com que os usuários do Sistema Operacional executem customizações de variáveis conforme sua necessidade.

export PERL_HOME=/usr/local/perl
export PERL5LIB=$PERL_HOME/lib
export PATH/usr/bin:/sbin:/usr/sbin
stty erase ˆH

Listagem 2. Arquivo ˜/.profile

No caso do Bourne-Again Shell, o arquivo configuração do Shell para usuários pode ser localizado em $HOME/.bash_profile de cada usuário do S.O.


Canais de Comunicação

Todos os programas escritos em ambiente UNIX / Linux utilizam os canais STDIN, STDOUT e STERR como comunicação com os dispositivos externos. STDIN (ou ‘Standard In’) é utilizado como canal de entrada, onde a informação é enviada a um programa. Os caracteres digitados no teclado de um computador são recebidos por um programa via STDIN.

A informação de saída de um programa utiliza normalmente o STDOUT ou STDERR (ou ambos). Por default, estes dois canais são gerados em tela. A vantagem de utilizar estes dois canais é que pode-se separar a saída normal de programa de seus erros. Nem sempre é interessante ver ambos em uma saída apenas.

O fluxo correto utilizado pelos canais de comunicação consiste em entrada, processamento e saída, conforme figura 1.


Figura 1. Fluxograma de Canais de Comunicação


Redirecionamento para Arquivos

O Redirecionamento de canais de comunicação para arquivos facilita a interpretação dos resultados gerados por um programa e ainda podem garantir um histórico de execução para posterior análise. Os seguintes caracteres são utilizados para redirecionamento:

< Redireciona o STDIN de um arquivo
> Redireciona o STDOUTpara um arquivo (sobrescreve)
>> Redireciona o STDOUT para um arquivo (inserção/append)
2> Redireciona o STDERR para um arquivo (sobrescreve)
2>> Redireciona o STDERR para um arquivo (inserção/append)
&> Redireciona ambos STDOUT e STDERR

Redirecionar o arquivo “/etc/passwd” para STDIN so programa “sort”:
$ sort < /etc/passwd

Listagem 3. Redirecionando STDIN do comando sort


A saída do comando “echo” é redirecionada para o arquivo “salario”. O conteúdo será 342 e todo o conteúdo existente será excluído. Se o arquivo não existir, o mesmo será criado:

$ echo 342 > salario

Listagem 4. Redirecionando STDOUT do comando echo


A saída do comando “ls” será exibida em tela, porém qualquer erro que venha a ocorrer será redirecionado para o arquivo “erros”. Se o arquivo já existir, o mesmo será sobrescrito.

$ ls –alR /proc 2> erros

Listagem 5. Criando arquivo erros com conteudo do comando ls


Praticamente o mesmo caso acima, com a diferença que os possíveis erros gerados pelo comando “find” serão adicionados ao arquivo “erros” e nenhuma informação neste arquivo será perdida. Se o arquivo “erros” não existir, o mesmo será criado. 

$ find / –name “teste” 2>> erros

Listagem 6. Incluindo saída no arquivo erros


Utilizando pipe

Como fundamento principal em um sistema Unix / Linux, o pipe  envia  a saída de um comando qualquer (STDOUT) para a entrada de outro comando (STDIN), incluindo toda a cadeia de comandos. O Símbolo para o pipe é identificado por  |. Pode ser muito útil para controlar saídas em telas, com o comando abaixo pode-se listar um diretório qualquer com pausa de tela:

ls –la /etc | more

Listagem 7. Listando conteúdo do diretório /etc com pausa de tela


Uso de STDOUT e STDIN em comandos:

ls –la /proc |sort | wc -l

Listagem 8. Contando e ordenando conteúdo do diretório /proc


1 – O Comando “ls –la /proc” lista o conteúdo do diretório /proc.
2 – O comando “sort” orderna o output.
3 – O Comando “wc –l” conta o número de linhas retornadas.


Expressões Regulares

Utilizar Expressões Regulares é um método muito poderoso para comparar partes específicas de um texto ou variável. Elas devem ser avaliadas via STDIN, via Dispositivo de entrada.

Caracteres especiais de expressões Regulares podem ser simplesmente um comparativo. Ex: a=a, b=b,c=c, etc. Existem alguns outros caracteres especiais como:

\t tab
\n Nova Linha
\r Carriage Return (ENTER)
\f Form Feed (FORM)
\c Caracter de controle
\x Caracter em Hexa
. Caracter Único


Variáveis do Shell

As variáveis de um Shell são utilizadas para determinar todas as variáveis configuradas em uma determinada sessão dentro de um Shell. Através do comando “set” pode-se identificar todas as variáveis determinadas em uma sessão. Um uma sessão comum/interativa de um Shell, essas variáveis podem vir de 3 (três) locais:

1 – Das configurações gerais do Ambiente, quando o Shell é executado.
2 – Definidas pelos arquivos de inicialização do Shell tais como: “/etc/profile”, “~/.bash_profile”, “~/.bashrc”, entre outros.
3 – Definidas manualmente pelo usuário através de uma sessão interativa.

As variáveis do Shell não são necessariamente visíveis aos programas iniciados em um Shell. Abaixo é demonstrado que o valor da variável $IDADE não é visível para um novo Shell. Também mostra o uso to comando “unset” para “destruir” uma variável.

1      $ echo $Shell
2      ksh
3      $ IDADE=42
4      $ echo $IDADE
5      42
6      $ bash
7      bash# echo $IDADE
8      .
9      bash# exit
10    $ echo $IDADE
11    42
12    $ unset IDADE; echo $IDADE
13     .

Listagem 9. Utilizando comando unset

Na linha 6 um novo Shell é iniciado. Na linha 8, nenhum resultado é apresentado. Na linha 9 o mesmo Shell é encerrado. Na linha 13 nenhum resultado é apresentado. 


Variáveis do Ambiente

Como comando “export” permite com que uma variável do Shell seja definida como uma variável de ambiente, que pode ser identificada por cada processo iniciado no sistema. A lista de todas as variáveis de ambiente pode ser obtida através do comando “env”.

1      $ echo $Shell
2      ksh
3      $ IDADE=42
4      $ env | grep IDADE
5      $. . . NENHUM RESULTADO . . .
6      $ export IDADE
7      $ env | grep IDADE
8      IDADE=42
9      $ bash
10    bash# echo $IDADE
11    42

Listagem 10. Utilizando comando env

Na linha 9 um novo Shell é iniciado.


As variáveis também podem ser adicionadas ao ambiente através de linha de comando antes da chamada de um programa qualquer. Pode-se definir o idioma como Português/Brasil, o Editor como “vi” e somente então o programa “crontab” (agendador de tarefas do Unix/Linux) é executado:

$ LANG=pt_BR EDITOR=vi crontab –e

Listagem 11. Utilizando várias váriaveis no Shell


Para ignorar uma determinada variável de ambiente na chamada de um programa, pode-se utilizar a opção “-u” do comando “env”. Pode-se iniciar um processo de um cliente SSH que não terá acesso ao processo agente do SSH em execução:

$ env -u SSH_AGENT_PID ssh usuario@servidor1

Listagem 12. Restringindo acessos a processos


Executar o comando “env” com a opção “-i” irá iniciar um comando qualquer sem nenhuma variável de ambiente declarada.

$ env –i telnet servidor2

Listagem 13. Restringindo acessos a processos


Executar o comando “env” com a opção “-i” irá iniciar um comando qualquer sem nenhuma variável de ambiente declarada.

$ env –i telnet servidor2



Referências

Visão Geral sobre 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




Abraço
Victor Armbrust 

0 Comentários:

Postar um comentário

Postagens mais lidas

_______________________________________________________________________________

Copyright:


Este site e todo o conteúdo aqui publicado permite ao Blog VictorDBA.net e possui seus respectivos direitos autorais.

O Conteúdo desde Blog não deve ser publicado, distribuído ou transmitido sem autorização prévia de seu autor.

Oracle e seus produtos são marcas registradas da Oracle Corporation® (http://www.oracle.com)

Todo o material aqui encontrado é mantido sem ajuda financeira e mantém como propriedade de seu fundador/escritor.



Disclaimer:


The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.

As opiniões publicadas neste blog (http://victordba.net) são pessoais e não necessariamente representam a visão da Oracle.


Toda informação aqui encontrado é oferecida através do uso do bom senso e boa fé do seus leitores e não deve ser considerada como material

oficial da Oracle Corporation (http://www.oracle.com)


O Autor (e contribuidores) não considera as informações aqui como oficiais e/ou permitidas para redistribuição. Ao utilizar o site http://victordba.net o

leitor deve entender e aceitar que as informações aqui encontradas são de direitos autorais do Autor e contribuidores.


O blog http://victordba.net não faz revisão de conteúdo publicado por outros como comentários bem como posts em grupo de usuários ou portais.

Seus autores não necessariamente concordam ou apoiam opiniões de seus leitores.


ESTE É UM SITE INDEPENDENTE E NÃO REPRESENTA A ORACLE CORPORATION® (http://www.oracle.com) EM NENHUM SENTIDO. AS OPINIÕES E

CONTEÚDOS AQUI ENCONTRADOS NÃO POSSUEM RELAÇÃO COM A VISÃO DA ORACLE CORPORATION®. ESTE SITE NÃO POSSUI NENHUM APOIO

OU PATROCINIO DA ORACLE CORPORATION®

_______________________________________________________________________________