Shell
O shell é um interpretador de comandos. Sempre que digitamos algo ele interpreta o nos dá algum retorno. Podemos escrever sequências de comandos que serão executados pelo shell. Essa sequência de comandos fica guardada em um arquivo e é chamada de ‘script’. Como esse script será interpretado por um shell, ele é chamado de Shell Script.
Sabores de Shell
Existem vários interpretadores Shell no mundo Unix, os mais conhecidos são:
- Bourne Shell (sh): Desenvolvido por Stephen Bourne no Bell Labs (da AT&T) foi o shell padrão dos sistemas Unix por muitos anos. Hoje está presente em diversos sabores de Unix e em praticamente todas as distros GNU/Linux.
- Korn Shell (ksh): Desenvolvido por David Korn, também no Bell Labs, é um uma extensão do sh com várias melhorias. Por ter funções que o sh não tem, acaba sendo a opção de alguns programadores.
- Bourne Again Shell (bash): Este é o shell oficial do projeto GNU. Tem suporte total ao sh e acrescenta novos comandos. É o shell que mais cresce em número de usuários e é o padrão das distros GNU/Linux.
Existem diversos sabores de shell, mas coloquei aqui apenas os principais. No restante deste documento usarei apenas o bash, mas a palavra ‘shell’ poderá ser usada para referencia-lo.
Como funciona um comando
Quando se digita um comando em shell, ele é interpretado e executado. Em shell existem os comandos do próprio shell (if, switch) e também os diversos programas/comandos do sistema operacional (ls, cd, mkdir).
Atribuição de Variáveis
Em shell é possível criar variáveis (assim como nas linguagens de programação) para guardar valores. Para isso use a sintaxe:
Um exemplo:
Repare que não há espaços ao redor do símbolo de igual.Para exibir o conteúdo de uma variável e necessário usar um cifrão ($) antes de seu identificador:
Redirecionamento de Saída
Em shell é possível direcionar a saída de um comando para um arquivo usando as instruções ‘>’ e ‘>>’. O comando ‘ls’ lista o conteúdo de um diretório na tela. Para direcionar a saída do comando ls para um arquivo use ‘>’: $ ls > resultado.txt O redirecionador ‘>’ apaga o conteúdo do arquivo e grava a saída do comando. Para adicionar a saída de um comando ao final de um arquivo use ‘>>’, dessa forma o conteúdo do arquivo será mantido:
A primeira linha imprime o texto “Iniciando script” no arquivo log.txt, se o arquivo já existir, ele apaa o conteúdo. A segunda linha lista o conteúdo do diretório /etc, e joga a saída para o arquivo log.txt, dessa vez mantendo o conteúdo do arquivo. A terceira linha imprime o texto “Finalizando script” no arquivo log.txt, mantendo o conteúdo do arquivo.
Redirecionamento entre comandos
Além de redirecionar a saída de um comando para um arquivo, também é possível redirecionar a saída para outro comando usando o pipe ( | ), barra vertical. O comando ls lista o conteúdo de um diretório, o comando wc conta linhas, palavras e caracteres de um arquivo. Unindo esses dois comandos eu posso saber facilmente a quantidade de arquivos e diretórios dentro de um diretórios: |
O ls vai listar cada arquivo em uma linha e o wc, com a opção ‘-l’, vai contar a quantidade de linhas.
Guardando a saída de comandos em variáveis
No exemplo anterior o script contava o número de arquivos e diretórios em um diretório. Para guardar esse número em uma variável é necessário colocar o comando entre acentos graves:
Manipulando Strings
Existem comandos bem interessantes para manipular textos em ambientes Unix. Um deles é o ‘cut’. Este comando ‘corta’ um arquivo em colunas devolvendo apenas a informação requisitada. Veja um exemplo, o arquivo ‘/etc/passwd’ guarda a lista de usuários do sistema e algumas outras informações:
Esta lista tem muita informação, só o que eu quero é o nome dos usuários. Como este arquivo tem campos delimitados por ‘:’, basta usado comando ‘cut’ para cortar o arquivo em colunas:
Pronto, uma lista bem menor, apenas com os nomes dos usuários. No comando ‘cut’ a opção ‘-d’ define o delimitador das colunas do arquivo, no caso ‘:’, e a opção ‘-f’ diz qual é a coluna que queremos, no caso a 1ª.Vamos alterar este comando para que ele retorne apenas os usuários que não possuem um shell no sistema. Esses usuários são identificados por terem um shell ‘/bin/false’ na 7º coluna do arquivo ‘/etc/passwd’. Para pegar esses usuários podemos usar o comando ‘grep’ que filtra um texto e imprime apenas as linhas que contém o texto pesquisado:
Legal, consegui a lista de usuários, mas eu queria apenas os nomes… Então basta redirecionar a saída mais uma vez e usar o ‘cut’:
Para inverter a pesquisa e mostrar apenas o usuários que tem sim algum tipo de shell, diferente de /bin/false, basta usar a opção ‘-v’ do ‘grep’ para que ele inverta a pesquisa e mostre não as linhas que NÃO casam com o texto informado:
E para exibir a quantidade de usuários com algum tipo de shell basta usar o comando ‘wc’:
Criando Scripts
Até agora os comandos foram executados no prompt do bash. Desta vez vou criar um arquivo com uma sequência de comandos que serão executados. veja o conteúdo do arquivo:
Salvei este arquivo com o nome ‘usuarios_shell.sh’. A extensão ‘.sh’ não é obrigatória, mas facilita na hora de procurar seus scripts. Além disso alguns editores de texto (gedit) usam essa extensão para deixar o arquivo com sintaxe colorida, o que facilita bastante a edição.Para executar o arquivo use o comando ‘bash usuarios_shell.sh’, dessa forma o arquivo será interpretado e executado pelo ‘bash’.No arquivo há ums instrução especial na primeira linha. Essa instrução diz que esse arquivo deve ser interpretado pelo bash e graças a ela podemos executar esse script sem usar o comando ‘bash nome_do_arquivo.sh’. Para isso é necessário que o arquivo tenha permissão de execução:
Agora basta executar o arquivo:
O ‘./’ é o caminho atual do arquivo (diretório atual) e é necessário para que o bash saiba onde está o arquivo que se pretende executar caso ele não esteja em um diretório que faz parte da $PATH, que é uma veriável que contém os diretórios onde há programas para serem executados.
Considerações
Graças ao poder dos redirecionadores, como o pipe (|), é possível montar scripts aos poucos, unindo as funcionalidades de diversos comandos. No exemplo acima foram usados os comandos ‘cat’, ‘grep’, ‘cut’ e ‘wc’ para gerar apenas um resultado. Essa é a maneira shell script de se construir scripts, unindo pequenos pedaços, que sozinhos fazem pouco, mas juntos fazem muito.
Shell Script - Parte 2 - Controle de Fluxo
Tomada de Decisões
Em toda linguagem de programação existe alguma estrutura para tomada de decisões. Essa estrutura em geral é feita através do comando “if”. O comando “if” analisa de uma expressão é verdadeira e então executa um bloco de código, caso a expressão seja falsa pode ser executado, ou não, um outro bloco.
Em geral as linguagens de programação oferecem maneiras de verificar se um valor é igual, menor ou maior que outro. As formas mais comuns são:
- ==: Igual à
- != : Diferente de
- < : Menor que
- > : Maior que
- <= : Menor ou igual à
- >= : Maior ou igual à
Em shell script os mesmos testes são obtidos com:
- -eq : (equal) Igual à
- -ne : (not equal) Diferente de
- -lt : (less than) Menor que
- -gt : (greater than) Maior que
- -le : (less or egual) Menor ou igual à
- -ge : (greater or equal) Maior ou igual à
O uso do “if” em shell script é assim:
Repare que é necessário manter espaços entre os colchetes e os números, ou variáveis. O bloco após a palavra “then” será executado se a expressão dentro do “if” for verdadeira. O bloco “if” termina com a palavra “fi” que é “if” ao contrário. Essa é uma maneira simples de identificar o final de um “if” quando o encontramos.
As expressões acima são mais comuns para tratar números. Para fazer comparações com textos use:
- = : Igual à (isso mesmo apenas um sinal de igual)
- != : Diferente de
- -n : String existe e não é vazia (apenas um operador)
- **-z **: String existe e é vazia (apenas um operador)
Veja um exemplo com Strings:
No script acima o “if” verifica se a variável $nome existe e está vazia, isso significa que o usuário não digitou o nome dele. A instrução “read” faz com que o shell leia alguma informação via teclado e retorne essa informação para a variável informada.
Também no script acima foi usada a palavra “else” que significa “senão”. Esse bloco é executado quando o “if” retorna um valor falso.
O Super IF do Shell
Mas o shell oferece mais opções para o “if” do que as linguagens de programação o fazem! Veja outras opções bem interessantes:
- **-s **: Arquivo existe, não vazio (apenas um operador)
- **-f **: Arquivo existe, não é um diretório (apenas um operador)
- **-d **: Diretório existe (apenas um operador)
- **-w **: Arquivo, com permissão de escrita (apenas um operador)
- -r : Arquivo, com permissão de leitura (apenas um operador)
- **-x **: Arquivo, com parmissão de execução -x (apenas um operador)
Veja um exemplo:
O script acima verifica se o arquivo “/tmp/meuLog.txt” existe. Caso exista ele continua o arquivo, colocando mais informações no final dele (redirecionador >>). Caso o arquivo não exista ele o inicia (com o redirecionador >).
IFs Aninhados
Chamamos de “ifs aninhados” as construções onde há um “if” dentro do bloco “then” ou “else” de outro “if”:
IF Multilevel
Você pode fazer comparações em sequência, com o uso do “elif”, desse jeito:
Além do comando “if”, o shell oferece opções como “case” para controle de fluxo.
O Comando Case
O comando “case” é usado para executar um bloco de código de acordo com o valor de uma variável. O comando “case” é interessante pois pode definir diversas opções diferentes sem usar uma estrutura com diversos comandos “if”, “elif” e “else”. Veja um exemplo:
O script acima exibe uma mensagem e então pede uma informação do usuário. O usuário vai digitar alguma letra e então o comando “case” entra em ação. Ele verifica qual valor foi digitado pelo usuário e executa os blocos de código relativos a cada opção. Primeira opção é a padrão, por isso ela é executada mesmo que o usuário não digite um valor.Cada bloco do case é iniciado por um valor que a variável analisada pode ter, ou vários valores, separados por um pipe. Os blocos são finalizados por uma sequência de dois caracteres ‘ponto-e-vírgula’ (;;).
Conclusão
A estrutura de controle “if” do shell é bem interessante pois permite fazer diversas comparações entre valores e ainda oferece opções para lidar com o sistema de arquivos. O comando “case” pode tratar diversos valores de uma vez, o que acuda a manter o código mais limpo e organizado.
Nenhum comentário:
Postar um comentário