Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Curso de Shell Script - 006, Notas de estudo de Informática

Você não agüenta mais aquele seu amigo usuário de Linux enchendo o seu saco com aquela história de que o sistema é fantástico e o Shell é uma ferramenta maravilhosa? A partir desta edição vai ficar mais fácil entender o porquê deste entusiasmo... POR JULIO CEZAR NEVES

Tipologia: Notas de estudo

2011

Compartilhado em 10/03/2011

william-felipe-dutra-abreu-da-silva
william-felipe-dutra-abreu-da-silva 🇧🇷

21 documentos

1 / 5

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
���������������������������������������������������������������������������������
�������������������������������������������
�������������������������������������������������������������������������������������������������������������������������������������������������������
86 edição 06
www.linuxmagazine.com.br
Papo de Botequim
LI NU X U SE R
Fala, cara! E aí, já tá sabendo tudo
do comando for? Eu te deixei um
exercício para t reinar, se não me
engano era para contar a quantidade de
palavras de um arquivo... Você fez?
Claro! empolgadão com essa lin-
guagem! Eu z da forma que você
pediu, olha só...
Êpa! Peraí que eu sequinho pra
tomar um chope. Aê Chico, traz dois
por favor. Um sem colari nho!
Como eu ia dizendo, olha como eu fi z.
É muito fácil...
$ cat contpal.sh
#!/bin/bash
# Script meramente pedagógico
# cuja função é contar a
# quantidade de palavras de
# um arquivo. Supõe-se que as
# palavras estão separadas
# entre si por espaços, <TAB>
# ou <ENTER>.
if [ $# -ne 1 ]
then
echo uso: $0 /caminho/do/
U
arquivo
exit 2
Cont=0
for Palavra in $(cat $1)
do
Cont=$((Cont+1))
done
echo O arquivo $1 tem $Cont
U
palavras.
Ou seja, o prog rama começa, como
sempre, verifi cando se a passagem de
parâ metros foi correta; em seguida o
comando for se incumbe de pegar cada
uma das palavras (lembre-se que o $IFS
padrão é branco, TAB e ENTER, que é
exatamente o que desejamos para sepa-
rar as pa lavras), incrementando a var i-
ável $ Cont. Vamos relembrar como é o
arquivo ArqDoDOS.txt.
$ cat ArqDoDOS.txt
Este arquivo
foi gerado pelo
DOS/Rwin e foi
baixado por um
ftp mal feito.
Agora vamos testar o programa pas-
sando esse arquivo como parâmetro:
$ contpal.sh ArqDoDOS.txt
O arquivo ArqDoDOS.txt tem 14
palavras.
Funcionou legal!
Se você se lembra,
em n ossa últi ma
aula mostra mos o
loop for a seguir:
for ((; i<=9;))
do
let i++
echo -n "$i "
done
Uma vez que chegamos neste ponto,
creio ser interessa nte citar que o Shell
trabalha com o conceito de “Expansão
Ar it tic a” (Ar ith metic E xpans ion),
que é acionada por uma construção da
forma $((expressão)) ou let expressão.
No últ imo loop for usei a expansão
aritmét ica das duas form as, mas não
podemos seguir adiante sem saber que
a expressão pode ser uma das listadas
na tabela 1.
Mas você pensa que o papo de loop
(ou laço) se encerra no comando for?
Ledo engano, amigo, vamos a partir de
agora ver mais dois comandos.
O comando while
Todos os programadores conhecem este
comando, porque é comum a todas as
linguagens. Nelas, o que normalmente
ocorre é que um bloco de coma ndos é
executado, enquanto (enquanto, em
ing lês, é “while”) uma determinada
condição for verdadeira.
Dave Hamilton - www. sxc.hu
Expressão Resultado
id++ id-- pós-incremento e pós- decremento de variáveis
++id --id pré-incremento e pré- decremento de variáveis
** exponenciação
* / % multiplicação, divisão, resto da divisão (módulo)
+ - adição, subtração
<= >= < > comparação
== != igualdade, desigualdade
&& E lógico
|| OU lógico
Tabela 1: Expressões no Shell
Blocos de código e laços (ou loops, como preferem alguns)
são o tema do mês em mais uma lição de nosso curso de Shell
Script. Garçom, salta uma boa redondinha, que tô a fi m de
refrescar o pensamento!
POR JULIO CEZAR NEVES
Curso de Shell Script
Papo de
Botequim VI
pf3
pf4
pf5

Pré-visualização parcial do texto

Baixe Curso de Shell Script - 006 e outras Notas de estudo em PDF para Informática, somente na Docsity!

86 edição 06 www.linuxmagazine.com.br LINUX USER^ Papo de Botequim

F

ala, cara! E aí, já tá sabendo tudo do comando for? Eu te deixei um exercício para treinar, se não me engano era para contar a quantidade de palavras de um arquivo... Você fez?

  • Claro! Tô empolgadão com essa lin-

guagem! Eu fi z da forma que você pediu, olha só...

  • Êpa! Peraí que eu tô sequinho pra

tomar um chope. Aê Chico, traz dois por favor. Um sem colarinho!

  • Como eu ia dizendo, olha como eu fi z.

É muito fácil... $ cat contpal.sh #!/bin/bash

Script meramente pedagógico

cuja função é contar a

quantidade de palavras de

um arquivo. Supõe-se que as

palavras estão separadas

entre si por espaços,

ou .

if [ $# -ne 1 ] then echo uso: $0 /caminho/do/U arquivo exit 2 fi Cont= for Palavra in $(cat $1) do Cont=$((Cont+1)) done echo O arquivo $1 tem $Cont U palavras. Ou seja, o programa começa, como sempre, verificando se a passagem de parâmetros foi correta; em seguida o comando for se incumbe de pegar cada uma das palavras (lembre-se que o $IFS padrão é branco, TAB e ENTER , que é exatamente o que desejamos para sepa- rar as palavras), incrementando a vari- ável $Cont. Vamos relembrar como é o arquivo ArqDoDOS.txt. $ cat ArqDoDOS.txt Este arquivo foi gerado pelo DOS/Rwin e foi baixado por um ftp mal feito. Agora vamos testar o programa pas- sando esse arquivo como parâmetro: $ contpal.sh ArqDoDOS.txt O arquivo ArqDoDOS.txt tem 14 palavras. Funcionou legal! Se você se lembra, em nossa última aula mostramos o loop for a seguir: for ((; i<=9;)) do let i++ echo -n "$i " done Uma vez que chegamos neste ponto, creio ser interessante citar que o Shell trabalha com o conceito de “Expansão Aritmética” ( Arithmetic Expansion ), que é acionada por uma construção da forma $((expressão) ) ou let expressão. No último loop for usei a expansão aritmética das duas formas, mas não podemos seguir adiante sem saber que a expressão pode ser uma das listadas na tabela 1. Mas você pensa que o papo de loop (ou laço) se encerra no comando for? Ledo engano, amigo, vamos a partir de agora ver mais dois comandos. O comando while Todos os programadores conhecem este comando, porque é comum a todas as linguagens. Nelas, o que normalmente ocorre é que um bloco de comandos é executado, enquanto (enquanto, em inglês, é “while”) uma determinada condição for verdadeira. Dave Hamilton - www.sxc.hu Expressão Resultado id++ id-- pós-incremento e pós-decremento de variáveis ++id --id pré-incremento e pré-decremento de variáveis ** exponenciação * / % multiplicação, divisão, resto da divisão (módulo) + - adição, subtração <= >= < > comparação == != igualdade, desigualdade && E lógico || OU lógico Tabela 1: Expressões no Shell Blocos de código e laços (ou loops , como preferem alguns) são o tema do mês em mais uma lição de nosso curso de Shell Script. Garçom, salta uma boa redondinha, que tô a fim de refrescar o pensamento! POR JULIO CEZAR NEVES Curso de Shell Script

Papo de

Botequim VI

��������������������������������������������������

���������������������������������������������������

��������������������������������������������������

���������������������������������������������������

Papo de Botequim LINUX USER ���������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ www.linuxmagazine.com.br edição 06 87 Pois bem, isso é o que acontece nas linguagens caretas! Em programação Shell, o bloco de comandos é executado enquanto um comando for verdadeiro. E é claro, se quiser testar uma condi- ção, use o comando while junto com o comando test , exatamente como você aprendeu a fazer no if , lembra? Então a sintaxe do comando fica assim: while comando do cmd cmd ... cmdn done e dessa forma, o bloco formado pelas instruções cmd1, cmd2 ,... e cmdn é exe- cutado enquanto a execução da instru- ção comando for bem sucedida. Suponha a seguinte cena: tinha uma tremenda gata me esperando e eu estava preso no trabalho sem poder sair porque o meu chefe, que é um pé no saco (aliás chefe-chato é uma redun- dância, né?), ainda estava na sala dele, que fica bem na minha passagem para a rua. Ele começou a ficar cabreiro depois da quinta vez que passei pela sua porta e olhei para ver se já havia ido embora. Então voltei para a minha mesa e fi z, no servidor, um script assim: $ cat logaute.sh #!/bin/bash

Espero que a Xuxa não tenha

copyright de xefe e xato :)

while who | grep xefe do sleep 30 done echo O xato se mandou, não U hesite, dê exit e vá à luta Neste scriptzinho, o comando while testa o pipeline composto pelos coman- dos who e grep , que será verdadeiro enquanto o grep localizar a palavra xefe na saída do comando who. Desta forma, o script dormirá por 30 segundos enquanto o chefe estiver logado (Argh!). Assim que ele se desconectar do servi- dor, o fluxo do script sairá do loop e te mostrará a tão ansiada mensagem de liberdade. Mas quando executei o script, adivinha o que aconteceu? $ logaute.sh xefe pts/0 Jan 4 08:46 U (10.2.4.144) xefe pts/0 Jan 4 08:46 U (10.2.4.144) ... xefe pts/0 Jan 4 08:46 U (10.2.4.144) Isto é, a cada 30 segundos a saída do comando grep seria enviada para a tela, o que não é legal, já que poluiria a tela do meu micro e a mensagem tão espe- rada poderia passar despercebida. Para evitar isso, já sabemos que a saída do pipeline tem que ser redirecionada para o dispositivo /dev/null. $ cat logaute.sh #!/bin/bash

Espero que a Xuxa não tenha

copyright de xefe e xato :)

while who | grep xefe > /dev/null do sleep 30 done echo O xato se mandou, não U hesite, dê exit e vá a luta Agora quero montar um script que receba o nome (e eventuais parâme- tros) de um programa que será execu- tado em background e que me informe do seu término. Mas, para você enten- der este exemplo, primeiro tenho de mostrar uma nova variável do sistema. Veja estes comandos executados direta- mente no prompt: $ sleep 10& [1] 16317 $ echo $! 16317 [1]+ Done sleep 10 $ echo $! 16317 Isto é, criei um processo em back- ground que dorme por 10 segundos, somente para mostrar que a variável $! guarda o PID ( Process ID ) do último pro- cesso em background. Mas observe a listagem e repare, após a linha do Done , que a variável reteve o valor mesmo após o término desse processo. Bem, sabendo isso, já fica mais fácil monitorar qualquer processo em back- ground. Veja só como: $cat monbg.sh #!/bin/bash

Executa e monitora um

processo em background

$1 & # Coloca em backgroud while ps | grep -q $! do sleep 5 done echo Fim do Processo $ Esse script é bastante similar ao ante- rior, mas tem uns macetes a mais, veja só: ele tem que ser executado em back- ground para não prender o prompt mas o $! será o do programa passado como parâmetro, já que ele foi colocado em background após o monbg.sh propria- mente dito. Repare também na opção -q (quiet) do grep, que serve para fazê-lo “trabalhar em silêncio”. O mesmo resul- tado poderia ser obtido com a linha: while ps | grep $! > /dev/null , como nos exemplos que vimos até agora. Vamos melhorar o nosso velho musinc , nosso programa para incluir registros no arquivo musicas , mas antes preciso te ensinar a pegar um dado da tela, e já vou avisando: só vou dar uma pequena dica do comando read (que é quem pega o dado da tela), que seja o suficiente para resolver este nosso problema. Em uma outra rodada de chope vou te ensinar tudo sobre o assunto, inclusive como formatar tela, mas hoje estamos falando sobre loops. A sintaxe do comando read que nos interessa por hoje é a seguinte: $ read -p "prompt de leitura" var Onde “prompt de leitura” é o texto que você quer que apareça escrito na tela. Quando o operador teclar tal dado, ele será armazenado na variável var. Por exemplo: $ read -p "Título do Álbum: " Tit Bem, uma vez entendido isso, vamos à especificação do nosso problema: faremos um programa que inicialmente lerá o nome do álbum e em seguida fará um loop de leitura, pegando o nome da música e o artista. Esse loop termina quando for informada uma música com nome vazio, isto é, quando o operador

��������������������������������������������������

���������������������������������������������������

��������������������������������������������������

���������������������������������������������������

Papo de Botequim LINUX USER ���������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ www.linuxmagazine.com.br edição 06 89 Em 20/01 às 11:23h Voltando à nossa CDteca, quando vamos cadastrar músicas seria ideal que pudéssemos cadastrar diversos CDs de uma vez só. Na última versão do programa isso não ocorre: a cada CD cadastrado o programa termina. Veja na listagem 2 como melhorá-lo. Nesta versão, um loop maior foi adi- cionado antes da leitura do título, que só terminará quando a variável $Para deixar de ser vazia. Caso o título do álbum não seja informado, a variá- vel $Para receberá um valor (coloquei 1, mas poderia ter colocado qualquer coisa) para sair desse loop, terminando o programa. No resto, o script é idêntico à versão anterior. Atalhos no loop Nem sempre um ciclo de programa, c o m p r e e n d i d o entre um do e um done , sai pela porta da frente. Em algu- mas oportunidades, temos que colocar um comando que aborte de forma c ont rolada esse loop. De maneira inversa, algumas vezes desejamos que o f lu xo de execução do programa volte antes de chegar ao done. Para isso, temos res- pectivamente os comandos break (que já vimos rapidamente nos exemplos do comando while ) e continue , que funcio- nam da forma mostrada na figura 1. O que eu não havia dito anterior- mente é que nas suas sintaxes genéricas eles aparecem da seguinte forma: break [qtd loop] e também: continue [qtd loop] Onde qtd loop representa a quanti- dade dos loops mais internos sobre os quais os comandos irão atuar. Seu valor por default é 1. Duvido que você nunca tenha apa- gado um arquivo e logo após deu um tabefe na testa se xingando porque não devia tê-lo removido. Pois é, na décima vez que fi z esta besteira, criei um script para simular uma lixeira, isto é, quando mando remover um (ou vários) arquivo(s), o programa “fi nge” que deletou, mas no duro o que ele fez foi mandá-lo(s) para o diretório /tmp/ LoginName_do_usuario. Chamei esse programa de erreeme e no arquivo /etc/ profile coloquei a seguinte linha, que cria um “apelido” para ele: alias rm=erreeme Veja o programa na listagem 3. Como você pode ver, a maior parte do script é formada por pequenas críticas aos parâmetros informados, mas como o script pode ter recebido diversos arqui- vos a remover, a cada arquivo que não se encaixa dentro do especificado há $ cat musinc.sh #!/bin/bash

Cadastra CDs (versao 5)

Para= until [ "$Para" ] do clear read -p "Título do Álbum: " Tit if [! "$Tit" ] # Se titulo vazio... then Para=1 # Liguei fl ag de saída else if grep "^$Tit^" musicas > /dev/null then echo "Este álbum já está cadastrado" exit 1 fi Reg="$Tit^" Cont= oArt= while [ "$Tit" ] do echo Dados da trilha $Cont: read -p "Música: " Mus [ "$Mus" ] || break # Sai se vazio read -p "Artista: $oArt // " Art [ "$Art" ] && oArt="$Art" # Se vazio Art anterior Reg="$Reg$oArt~$Mus:" # Montando registro Cont=$((Cont + 1))

A linha anterior tb poderia ser ((Cont++))

done echo "$Reg" >> musicas sort musicas -o musicas fi done Listagem 2 Figura 1: A estrutura dos comandos break e continue , usados para contro- lar o fluxo de execução em loops. �� �������� �������� ���� ��������������� ����� ��������������� �������� ����� ����� �� �������� �������� ���� ����� ��������

������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

��������������������������������������������������

��������������������������������������������������

90 edição 06 www.linuxmagazine.com.br LINUX USER^ Papo de Botequim um continue , para que a seqüência volte para o loop do for de forma a receber outros arquivos. Quando você está no Windows (com perdão da má palavra) e tenta remover aquele monte de lixo com nomes esqui- sitos como HD04TG.TMP, se der erro em um dos arquivos os outros não são removidos, não é? Então, o continue foi usado para evitar que uma improprie- dade dessas ocorra, isto é, mesmo que dê erro na remoção de um arquivo, o programa continuará removendo os outros que foram passados.

  • Eu acho que a esta altura você deve

estar curioso para ver o programa que restaura o arquivo removido, não é? Pois então aí vai vai um desafio: faça-o em casa e me traga para dis- cutirmos no nosso próximo encontro aqui no boteco.

  • Poxa, mas nesse eu acho que vou dan-

çar, pois não sei nem como começar...

  • Cara, este programa é como tudo

o que se faz em Shell: extrema- mente fácil. É para ser feito em, no máximo, 10 linhas. Não se esqueça de que o arquivo está salvo em /tmp/ $LOGNAME e que sua última linha é o diretório em que ele residia antes de ser “removido”. Também não se esqueça de criticar se foi passado o nome do arquivo a ser removido.

  • É eu vou tentar, mas sei não...
  • Tenha fé, irmão, eu tô te falando que

é mole! Qualquer dúvida é só passar um email para julio.neves@gmail. com. Agora chega de papo que eu já estou de goela seca de tanto falar. Me acompanha no próximo chope ou já vai sair correndo para fazer o script que passei?

  • Deixa eu pensar um pouco...
  • Chico, traz mais um chope enquanto

ele pensa! $ cat erreeme.sh #!/bin/bash

Salvando cópia de um arquivo antes de removê-lo

Tem de ter um ou mais arquivos a remover

if [ $# -eq 0 ] then echo "Erro -> Uso: erreeme arq [arq] ... [arq]" echo "O uso de metacaracteres e’ permitido. Ex.U erreeme arq*" exit 1 fi

Variável do sistema que contém o nome do usuário.

MeuDir="/tmp/$LOGNAME"

Se não existir o meu diretório sob o /tmp...

if [! -d $MeuDir ] then mkdir $MeuDir # Vou criá-lo fi

Se não posso gravar no diretório...

if [! -w $MeuDir ] then echo "Impossivel salvar arquivos em $MeuDir. U Mude as permissões..." exit 2 fi

Variável que indica o cod. de retorno do programa

Erro=

Um for sem o in recebe os parametros passados

for Arq do

Se este arquivo não existir...

if [! -f $Arq ] then echo "$Arq nao existe." Erro= continue # Volta para o comando for fi

Cmd. dirname informa nome do dir de $Arq

DirOrig=dirname $Arq

Verifi ca permissão de gravacao no diretório

if [! -w $DirOrig ] then echo "Sem permissão no diretorio de $Arq" Erro= continue # Volta para o comando for fi

Se estou "esvaziando a lixeira"...

if [ "$DirOrig" = "$MeuDir" ] then echo "$Arq fi cara sem copia de seguranca" rm -i $Arq # Pergunta antes de remover

Será que o usuário removeu?

[ -f $Arq ] || echo "$Arquivo removido" continue fi

Guardo no fi m do arquivo o seu diretório originalU

para usá-lo em um script de undelete cd $DirOrig pwd >> $Arq mv $Arq $MeuDir # Salvo e removo echo "$Arq removido" done

Passo eventual número do erro para o código

de retorno

exit $Erro Listagem 3: erreeme.sh Julio Cezar Neves é Analista de Suporte de Sistemas desde 1969 e tra- balha com Unix desde 1980, quando participou do desenvolvimento do SOX, um sistema operacional similar ao Unix produzido pela Cobra Com- putadores. Pode ser contatado no SOBRE O AUTOR e-mail [email protected]