Curso de extensão em Administração de sistemas GNU/Linux: redes e serviços
Italo Valcy - italo@dcc.ufba.br
Gestores da Rede Acadêmica de Computação Departamento de Ciência da Computação
Universidade Federal da Bahia
Todo o material aqui disponível pode, posteriormente, ser utilizado sobre os termos da:
Creative Commons License:
Atribuição - Uso não comercial - Permanência da Licença
Assuntos abordados
Programação em Shell Script
Expressões Regulares
Programação Shell Script
Quando usar o Shell?
Quais problemas podem ser resolvidos utilizando a programação em Shell?
Quais problemas não podem ser resolvidos utilizando a programação em Shell?
Qual a diferença entre um shell script e uma linha de programação como C, C++, Java?
Programação Shell Script
Escrevendo scripts
Um script é basicamente uma sequência de comandos. Os comandos podem ser separados por um ponto e
vírgula (;) ou por quebra de linha.
Um arquivo contendo um script traz, na primeira linha a seguinte string:
Programação Shell Script
Escrevendo scripts
Tanto espaços em branco quanto tabulações antes dos comandos são ignorados.
Comentários são iniciados com o caractere # e se estendem até o fim da linha, conforme exemplo:
#!/bin/bash
# isso eh um comentario
Programação Shell Script
Variáveis em Shell
Nome dado ao espaço de memória que armazena um valor.
O nome da variável é escolhido pelo programador. Não é necessário declaração prévia.
Tipos suportados: Inteiro
Decimal String Vetor
Programação Shell Script
Variáveis em Shell
Para criar uma variável, basta atribuir-lhe um valor:
#!/bin/bash
minha_variavel=”hello world” echo $minha_variavel
Programação Shell Script
Variáveis em Shell
X=14 # funciona
X=teste # funciona
X=varias palavras # não funciona :(
X=”varias palavras” # agora sim! :)
Y=”$X unidades” # $X será substituído pelo valor de X Y='$X unidades' # $X não será substituído
Como atribuir a saída de um comando a uma variável?
Programação Shell Script
Escopo das variáveis
O que é escopo? Onde é utilizada uma variável criada em um script?
Variáveis locais: somente no script
Variáveis de ambiente: em todo o ambiente Shell
X=1 # X é local
export X # X agora é variável de ambiente
exporte Y=”/srv/books” # variável de ambiente
Programação Shell Script
Parâmetros
O que é um parâmetro ou argumento?
cp -R origem destino invoke-rc.d ssh restart
Variável especial contém o argumento: $<n>
./meu_script.sh cpu 1 verde $0 → ./meu_script.sh
$1 → cpu $2 → 1
Programação Shell Script
Parâmetros
Outras variáveis de parâmetros:
$@: Contém todos os parâmetros passados a partir de
$1. Trata-os como uma lista.
$#: Contém o número de parâmetros passados
$$: Número PID do processo atual (do próprio script) $_: Último argumento do último comando executado $?: Código de retorno do último comando executado
Programação em Shell Script
Já sabemos como escrever scripts (cabeçalhos, estrutura básica de um script)
Utilização de variáveis Parâmetros
O Mundo GNU/Linux
Como executar operações matemáticas (1+1, por exemplo) em bash?
Basta utilizar o bloco do tipo “$((...))” que retorna o resultado de uma operação aritmética.
Soma: $((1+1)) ou X=$((1+1)) Resto: $((7 % 4))
Exponenciação: $((4**2))
Comando IF:
if <condicao>
then <comandos> else <comandos> fi
Condição: resultado de uma comparação aritmética ou o resultado de um comando (baseado no código de
retorno).
Comandos: grupo de ações a serem executadas caso a condição seja verdadeira.
Execução condicional
Exemplos:
if ls >/dev/null 2>&1; then echo “ok”; fi if ls /naoexiste 2>/dev/null
then echo “ok”
else echo “problema”; fi if ((5 > 3))
then
echo “5 eh maior que 3” fi
Execução condicional
Quando usar:
((expressao)) [ expressao ] [[ expressao ]]
Execução condicional
Expressão Símbolo Exemplo O arquivo existe -e
Diretório existe -d Arquivo executável -x
-n [ -n $VARIAVEL ] -z [ -z $VARIAVEL ] Igualdade de strings == [ $VAR1 == $VAR2 ]
[ -e /etc/passwd ] [ -d /root ] [ -x /bin/echo ] String não nula
String nula É maior que (GreaterThan) -gt [ 5 -gt 4 ] É menor igual (LessEqual) -le [ 4 -lt 5 ] É maior igual
(GreaterEqual) -ge [ 1 -ge 1] É igual (EQual) -eq [ 3 -eq 4 ] É diferente
(NotEqual) -ne [ 1 -ne 1 ]
Escreva um comando que dê boa tarde, bom dia ou boa noite de acordo à saída do comando date.
Dica: date +FORMAT exibe a data usando
FORMAT como padrão de saída. Mais informações
man date.
Tempo estimado para realização da atividade 5min.
Execução condicional – Exercício 1
Comando for:
for ((expr1; expr2; expr3)) do
<comandos> done
Expr1: Executa no início do comando
Expr2: Avaliada a cada iteração do comando Expr3: Executa no final de cada iteração
for ((x=0; x <= 10; x++)); do echo $x
done
Controle de fluxo
Existem outras formas para o comando for: Usando listas:
for <variavel> in <lista> do
<comandos> done
variavel: iterador para cada elemento da lista
lista: saída de comando ou variável com lista de
elementos
comando: comandos que serão executados. Controle de fluxo
Comando while: executa os comandos enquanto a expressão for verdadeira:
while <expressao>; do <comandos>
done
Comando until: executa os comandos até a expressão se tornar verdadeira:
until <expressao>; do <comandos>
done
Controle de fluxo
Comando while: x=1 while ((x < 10)); do echo $x x=$((x+1)) done
Qual a função do comando acima?
Qual a função dos duplos parenteses? Como reescrever o comando com until?
Controle de fluxo
Escreva um script que conte o número de
palavras de um arquivo-texto. Utilize o comando
for para isso.
* Esta atividade permite que o aluno treine o controle de fluxo e operações com listas.
Controle de fluxo – Exercício 2
Como saber se um script executou corretamente? Zero: terminou com sucesso.
Não-zero: terminou sem sucesso.
Em geral o código de retorno para “sem sucesso” é 1.
$ cd /
$ echo $?
0
$ cd /inexistente
bash: cd: /inexistente: arquivo ou diretório não encontrado
$ echo $? 1
Status de execução
O comando read <variavel> é utilizado para ler um valor da entrada padrão e armazená-lo em variavel. Escreva um script que solicite que o usuário digite uma string qualquer. O script deve continuar solicitando a entrada até que o usuário digite PARE.
Dica: while true
Programação shell script – Exercício 3
Crie um script para efetuar backup de arquivos e diretórios. O script deve receber como parâmetros um ou mais arquivos e diretórios que serão copiados para /tmp/<datadehoje>, onde <datadehoje> deverá ser no formato AnoMesDia-HoraMinuto. O script deverá emitir uma mensagem de erro caso a cópia não seja efetuada com sucesso.
Programação shell script – Exercício 4
Home work: Faça scripts para resolver os problemas
propostos no SVN do curso [1]. A solução deve estar disponível no SVN até 31/03/2009. Dúvidas podem ser tiradas pela lista de dicussão.
Postem o trabalho no SVN do curso [1], dentro de um diretório no seguinte padrão:
seu-nome/exercicios-shell
1 - https://intranet.dcc.ufba.br/svn/curso-graco/2009.1/exercicios-shell.txt
Programação shell script – Exercício 5
Dúvidas?
Expressões regulares
Poupam tempo na busca por informações ou em tarefas complexas.
Uma expressão regular (Regex), é uma construção que utiliza pequenas ferramentas, feita para obter uma determinada sequência de caracteres de um texto.
Vários programas e linguagens de programação tem suporte à Regex, dentre eles o grep, egrep, find, sed,
awk, lex, perl, e também alguns editores como o vim e emacs.
Expressões regulares
Curingas são utilizados para expressar conjuntos de arquivos na linha de comando:
*.txt: todos os arquivos que terminam com “.txt”
arquivo-??.txt: dois caracteres quaisquer após o hífen.
arquivo.{txt,html}: terminação com txt ou html.
Expressões regulares
grep, egrep, fgrep – imprimem linhas que casão com
um padrão.
Grep [opcoes] PADRAO [arquivo]
grep 'root' /etc/passwd
Imprime as linhas do arquivo /etc/passwd que contêm a palavra root.
grep -v 'root' /etc/passwd
Imprime as linhas de /etc/passwd que não contêm a palavra “root”.
grep -lr 'wireless' /usr/src/linux/doc/*
Imprime os arquivos do diretório /usr/src/linux/doc e subdiretórios, que contém a palavra wireless.
Expressões regulares
Metacaracteres são caracteres com funções específicas, que informam padrões e posições impossíveis de serem especificadas com caracteres normais.
Exemplos:
todas as linhas iniciadas pelos caracteres “a”,”b”,”c” e “d”, e que terminam com “1”
todas as linhas que possuam três números em seqüência
todos as linhas que possuem um padrão de data (dd/mm/aaaa)
Expressões regulares
O circunflexo ^: Simboliza o início de uma linha.
grep '^root' /etc/passwd
O cifrão $: representa o fim de uma linha:
grep 'bash$' /etc/passwd
Uma combinação útil seria:
grep '^$' arquivo # busca por linhas em branco O metacaractere ^ e $
Expressões regulares
Os [ ] permitem limitar um conjunto de caracteres a ocupar uma dada posição no texto.
Exemplos:
$ grep '^[aeiou]' /etc/group
filtra todos os grupos com nome iniciado pelas vogais
$ grep '^[bcdfghjklmnpqrstvxywz]' /etc/passwd
filtra todas os usuários cujo o nome inicia por uma consoante
$ grep '[0123456789][0123456789][0123456789]' /etc/group
filtra todas as linhas que possuam três números em seqüência
Expressões regulares
Para lista seqüênciais como 0123456789, abcd...z é possível utilizar o meta caracter -, para simbolizar a seqüência.
Exemplos:
$ grep '^[a-z]' /etc/passwd
filtra todas os usuários cujo o nome inicia por uma letra
$ grep '[0-9][0-9][0-9]' /etc/group
filtra todas as linhas que possuam três números em seqüência
Expressões regulares
As { } serve para indicar a quantidade de repetições de um caracter ou metacaracter
Exemplos:
$ grep '^.\{41\}$' /etc/passwd
filtra todas as linhas que possuem 41 caracteres. Observe que as barras reversas, “\”, são necessários para escapar as chaves no grep. É sugerido utilizar o egrep no lugar do grep.
$ egrep '^.{41}$' /etc/passwd
Mesmo comando acima, porém mais simples
$ egrep '^.{20,40}$' /etc/passwd
Expressões regulares
Mais exemplos:
$ egrep '^.{20,}' /etc/passwd
filtra as linhas com 20 ou mais caracteres.
$ egrep '^.{,27}$' /etc/passwd
filtra as linhas com menos de 27 caracteres
$ egrep '^.{20,40}$' /etc/passwd
filtra as linhas com 20 a 40 caracteres Algumas abreviações de repetição:
? == {0,1} - pode aparecer uma vez ou não
* == {0,} - pode aparecer qualquer quantidade, inclusive nenhuma
+ == {1,} - aparecer uma vez ou mais
Expressões regulares
Metacaracter ou (|): As listas, [ ], trabalham apenas com caracteres, mas em outras ocasiões é necessário procurar por palavras alternativas. Para isto de usa o ou lógico |.
Filtra apenas as linhas iniciadas com root, adm ou lp
$ egrep '^(root|adm|lp):' /etc/passwd
Metacaracter de negação de lista [^]: Para se negar uma lista, basta colocar o circunflexo a frente dos caracteres negados.
filtra as linhas iniciadas com consoantes
$ egrep '^[^aeiou]' /etc/passwd
Dúvidas?
Manipulação de stream
Utilizado para exibir na saída padrão colunas colunas ou campos de um ou mais arquivos. O arquivo original não é modificado.
Sintaxe: cut opcoes [arquivo] Algumas opções utilizadas:
-b lista-bytes: Mostra apenas os bytes nas posições listadas em lista-bytes.
-f lista-campos: Mostra os campos presentes em lista-campos.
-d delimitador: Define o delimitador de campos. Deve ser usada junto à -f.
Manipulação de stream
Queremos saber quais terminais virtuais estão em uso no sistema: $ who | cut -c10-15 tty7 pts/0 pts/1 pts/2 pts/3
Queremos quais usuários tem shell == /bin/bash no sistema:
$ grep bash /etc/passwd | cut -f1 -d:
root
Manipulação de stream
A operação básica do awk é pesquisar em um conjunto de linhas de entrada aquelas que satisfazem a um padrão e executar determinada ação para aquela(s) linha(s).
A sintaxe básica:
awk [opcoes] 'padrao-acao' [arquivo ...]
O awk também trabalha com campos. Geralmente utilizamos esses campos nas cláusulas do padrão. Exemplo:
awk '$1 == “Paula” {print $2, $3}'
Tanto a ação quanto o padrão podem ser omitidos, sendo que:
'$1 == “nome”', imprime as linhas que casam com padrão '{print $2, $3}', imprime o segundo e terceiro campo de todas as linhas.
Manipulação de stream
Opções úteis:
-F value: configura o separador dos campos
-v var=value: seta variável var para ser usada com valor
value.
Operadores relacionais usados em padrão
==, >, >=, <, <=
Operadores lógicos
&&, ||, !
Manipulação de stream
Utilizado para fazer edição de arquivos. Sua sintaxe geral:
sed regex [arquivo]
Onde, regex segue em partes as regras já vistas, mas obedecem o seguinte formato geral:
[<addr1>[,<addr2>]] <funcao> <argumentos>
Nesse caso, addr1 e addr2 definem a abrangência do
comando no arquivo. Se ambos forem omitidos, todas as linhas serão processadas. Se somente um for especificado, sobre a linha referida.
Manipulação de stream
Referenciando a linha pelo seu número:
$ sed '4 ...' arquivo $ sed '4,9 ...' arquivo
Procurando por uma cadeia no texto. Deve-se colocar tal cadeia entre barras.
$ sed '/cadeia/ ...' arquivo
$ sed '/cadeia1/,/cadeia2/ ...' arquivo
Manipulação de stream
Função para substituição de cadeias (s). $ sed 's/{valor velho}/{novo valor}/' Exemplo:
$ echo 'Frase qualquer' | sed 's/qualquer/especial/'
Frase especial
Podemos fazer múltiplas modificações usando a opção -e ou com “;”:
$ echo 'Frase qualquer' | sed -e 's/qualquer/especial/' -e \ 's/Frase/Palavra/'
Palavra qualquer
$ echo 'Frase qualquer' | sed -e 's/qualquer/especial; \ s/qualquer/especial/'
Palavra qualquer
Manipulação de stream
Para realizar múltiplas substituições devemos adicionar um “g” ao fim do comando. Exemplo:
$ cat arquivo
abcUNIXdefgUNIX
hijlmUNIXnoUNIXpqrUNIX
$ sed 's/UNIX/LINUX/' arquivo abcLINUXdefgUNIX
hijlmLINUXnoUNIXpqrUNIX
$ sed 's/UNIX/LINUX/g' arquivo abcLINUXdefgLINUX
hijlmLINUXnoLINUXpqrLINUX
Manipulação de stream
Outra função bastante usada é a remoção de linhas. Vejam que remoção de palavras pode ser feito pelo comando se substituição. A sintaxe do comando é:
'{string de busca} d'
Para remover as linhas que contenham two sed '/two/ d' numbers
Para remover as três primeiras linhas: sed '1,3 d' numbers
O comando sed – Deletando linhas
$ cat numers one two one three two one
Manipulação de stream
Adicionar texto a uma posição específica;Inserir texto em um trecho específico; Ler e escrever ao mesmo tempo;
Alterar linhas;
Inverter lógica dos comandos; etc.
Dúvidas?
Referências
http://aurelio.net/shell/canivete.html http://aurelio.net/curso/material/apostila-expressoes-intro.pdf http://rra.etc.br/linux/apresentacoes/Incrementando_o_Shell_com_E R.pdf http://www.oracle.com/technology/pub/articles/dulaney_sed.htmlProgramação Shell Script
Exercício 6
Crie um script que recebe como parâmetro um diretório e lista a quantidade de arquivos dentro daquele diretório (incluindo subdiretórios, se for o caso). Exemplo:
./conta_arquivos.sh /etc
O diretório /etc contém 3214 arquivos.
./conta_arquivos.sh /boot
O diretório /boot contém 106 arquivos.
./conta_arquivos.sh documentos
Programação Shell Script
Exercício 7
Crie um script que recebe como parâmetro uma string, digamos expr, um diretório, digamos source, e outro diretório, target. O script deverá procurar por arquivos
que contenham o padrão expr no seu nome e estejam no diretório source. Todos os arquivos encontrados devem ser copiados para a pasta target, a qual deve ser criada se não existir.