CI066 - Oficina de Programação
Notas de Aula # 09

Prof. Armando Luiz N. Delgado

1 Programação Shell - Scripts Shell

1.1 Conceitos Básicos

Freqüentemente um usuário deseja executar repetidas vêzes uma seqüência específica de comandos sem que precise redigitar todos os comandos da seqüência.

Em UNIX, um usuário pode criar um arquivo cujo conteúdo se constitui desta seqüência de comandos, passando em seguida a utilizar este arquivo como se fosse um simples comando. A este arquivo denominamos script shell e ele é equivalente aos arquivos em lote (extensão .bat) encontrados nos sistemas MS-Windows.

Assim, supondo-se que exista um arquivo com nome ~/bin/arq_estranhos cujo conteúdo seja:

       #!/bin/bash

       # Encontra arquivos de outros usuários
       find ~ \( ! -user $USER -o -perm -033 \) -exec ls -l {} \; >| ~/LOG

       if [ -s ~/LOG ]; then
          echo "Arquivos estranhos foram encontrados em sua área."
          echo "Verifique o arquivo ~/LOG."
       fi

será possível ao usuário executar o comando arq_estranhos na linha de comando shell. O que acontece é que todos os comandos dentro do arquivo serão executados em seqüência.

A estrutura básica de um script é a seguinte:

       #!/bin/bash

       <definição de variáveis de ambiente>
          .
          .
          .
       <comandos e/ou estruturas de controle> # <comentário>
          .
          .
          .
       # <comentarios>

A primeira linha indica qual shell será usado para interpretar e executar o conteúdo do script.

Se esta linha está ausente, o shell usado será o mesmo da sessão corrente (indicado pela variável de ambiente SHELL).

Em particular, esta linha é mais importante quando se pretende executar o script em sessões com outros tipos de shell (por exemplo csh(1) ou zsh(1)).

Qualquer texto escrito após o caracter # é considerado um comentário e não é interpretado pelo shell (a primeira linha mencionada acima é um comentário especial que indica o tipo de shell a ser usado para interpretar o restante do script).

Execução de scripts shell

Existem 2 formas de executar um script shell:

  1. Fornecer o nome do script como argumento para bash(1)
             bash ~/bin/arq_estranhos
    
  2. Definir permissão de execução para o script:
            chmod +x ~/bin/arq_estranhos
            ~/bin/arq_estranhos
    

    No segundo caso, é natural que o usuário queira executar seu script digitando apenas o nome deste, sem especificar o diretório onde o script está (e sem mudar de diretório com cd ou pushd/popd). Para isto, é importante que o diretório onde o script está faça parte do valor da variável de ambiente PATH.

    Recomenda-se que o usuário crie o diretório ~/bin e coloque lá todos seus scripts. Em seguida, acrescente ao final do arquivo  /.bashrc a linha abaixo:

             export PATH="${HOME}/bin:${PATH}"
    

Argumentos de scripts shell

Como em qualquer comando, um script shell pode receber argumentos. Em script estes argumentos são acessados via parâmetros posicionais:

$1, $2, ... $n
expande para o valor do n-ésimo argumento (positional parameter no manual on-line), isto é, $1 acessa o 1o argumento, $2 acessa o 2o argumento, e assim por diante.

ATENÇÃO: se n $>$ 9, deve estar limitado por {}: ${10}, ${11}, ...

$0
expande para o valor do nome do script (incluindo o caminho completo até o arquivo)
$*
expande para o valor de TODOS os argumentos digitados na linha de comando, começando do 1o argumento. Se limitado por aspas, $*" é equivalente a $1 $2 $3 ...".
$@
expande para o valor de TODOS os argumentos digitados na linha de comando, começando do 1o argumento. Se limitado por aspas, $@" é equivalente a $1" $2" $3" ....
$#
expande para o número de argumentos na linha de comando.
$$
expande para o PID do shell em que executa o script

O exemplo abaixo mostra um script shell que imprime o valor de seus parâmetros posicionais:

#!/bin/bash

echo "\$0 = $0"
echo "NOME SCRIPT = $(basename $0)"
echo "Numero de argumentos = $#"
echo "ARGUMENTOS = $*"
echo "ARGUMENTOS = $@"
echo "PID = $$"
echo
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$4 = $4"
echo "\$10 = $10"
echo "\$10 = ${10}"

O resultado da execução do script acima é:

ci066@dupond:~bash ./teste.sh a b c d e f g h i j k l
$0 = ./teste.sh
NOME SCRIPT = teste.sh
Numero de argumentos = 12
ARGUMENTOS = a b c d e f g h i j k l
ARGUMENTOS = a b c d e f g h i j k l
PID = 1249

$1 = a
$2 = b
$3 = c
$4 = d
$10 = a0
$10 = j
ci066@dupond:~echo $PATH
.:/home/especial/ci066/bin:/usr/X11/bin:/usr/local/bin:/usr/bin:/bin
ci066@dupond:~mv teste.sh ~/bin
ci066@dupond:~teste.sh a b c d e f g h i j k l
$0 = /home/delgado/bin/teste.sh
NOME SCRIPT = teste.sh
$1 = a
$2 = b
$3 = c
$4 = d
$10 = a0
$10 = j

Observe a diferença no valor do parâmetro $0 em ambas as execuções acima. Observe também a necessidade das chaves ao se exibir o valor do 10º argumento.

1.2 Comandos úteis em scripts shell

1.3 Variáveis de Ambiente em scripts shell

Variáveis de ambiente tem o mesmo objetivo de variáveis de programação: guardar informação ou valores que podem ser usados posteriormente durante a execução de um script.

Adicionalmente, algumas variáveis de ambiente são usadas pelo shell e outros programas como forma de configuração e parametrização. São exemplos disto as variáveis PATH, MANPATH, EDITOR, dentre outras.

Criação de variáveis

Define-se um nome para a variável e assinala-se um valor ao nome usando-se =:

         estado=12
         NOME="Arnaldo Arnoldo"
         vazio=""
         cont=0

ATENÇÃO: Não há espaços em branco antes e depois de =

Exibição do valor de variáveis

Para referenciar ou exibir o valor de uma variável de ambiente, deve-se preceder o nome da variável por cifrão ($):

          vazio=$estado
          echo "O nome do suspeito eh $NOME"

O último comando acima exibe na tela O nome do suspeito eh Arnaldo Arnoldo

Para isolar a referência ao valor de algum string imediatamente adjacente, coloca-se o nome da variável entre chaves ({}):

      echo "$cont1"           # Não exibe nada, pois não existe variável cont1
      echo "${cont}1"         # Exibe 01

1.4 Exemplos de scripts shell

  1. Comando ache_arquivos para mostrar todos os arquivos em um diretório (e sub-árvore) que tenham um determinado string:

            #!/bin/bash
            find $1 -type f -print | xargs grep -l "$2"
    

    O comando passa a ser executado da seguinte forma (após o devido uso de chmod(1)):

              ache_arquivo ~ '^[7-9].*'
    

  2. Comando insere_cliente para adicionar pessoas no arquivo de telefones visto em aulas anteriores:

            #!/bin/bash
            echo "$1        $2'' >> LabNum7/fones.txt
            sort -o LabNum7/fones.txt LabNum7/fones.txt
    

    O comando passa a ser executado da seguinte forma (após o uso apropriado de chmod(1)):

              insere_cliente "Arnaldo Arnoldo" 324-2345
    

  3. Comando showpid que mostre os PID de todos os processos de um determinado usuário:

            #!/bin/bash
            ps axu | grep "$1" | cut -c10-14
    

    O comando passa a ser executado da seguinte forma: (após o uso adequado de chmod(1)):

              showpid fbn02
    

  4. Comando killmy que mata todos os meus processos:

            #!/bin/bash
            pids=`ps axu | grep "$USER" | grep -v grep | cut -c10-16`
            kill $pids
    

    O comando passa a ser executado da seguinte forma (após o uso providencial de chmod(1)):

              killmy
    



Armando Luiz Nicolini Delgado
2008-07-11