Programação Shell LinuxAqui temos um livro livre e completo sobre ShellOs sedentos do "saber livre" são muito benvindos. |
Comandos Shell Script |
||
Home | Artigos | Agradecimentos | Links Amigos | Comprar o livroChangelogs |
Papo de Botequim - Parte 1Papo de Botequim - Parte 2Papo de Botequim - Parte 3Papo de Botequim - Parte 4Papo de Botequim - Parte 5Papo de Botequim - Parte 6Papo de Botequim - Parte 7Papo de Botequim - Parte 8Papo de Botequim - Parte 9Papo de Botequim - Parte 10Papo de Botequim - Parte 11Tira Gosto |
Papo de Botequim - Parte XI- E aí rapaz, tudo bom? - Belê, mas você lembra que me pediu para fazer um programa que quando o tamanho de uma tela variasse, no seu centro apareceria dinamicamente, em vídeo reverso, a quantidade de linhas e colunas do jeito que o Linux faz normalmente? Pois é eu fiz mas a aparência não ficou igual. - Não estou nem aí para a aparência, o que eu queria é que você exercitasse o que aprendemos. Deixe-me ver o que você fez. $ cat tamtela.sh
#!/bin/bash
#
# Coloca no centro da tela, em video reverso,
# a quantidade de colunas e linhas
# quando o tamanho da tela eh alterado.
#
trap Muda 28 # 28 = sinal gerado pela mudanca no tamanho
# da tela e Muda eh a funcao que fara isso.
Bold=$(tput bold) # Modo de enfase Rev=$(tput rev) # Modo de video reverso Norm=$(tput sgr0) # Restaura a tela ao padrao default Muda () { clear Cols=$(tput cols) Lins=$(tput lines) tput cup $(($Lins / 2)) $(((Cols - 7) / 2)) # Centro da tela echo $Bold$Rev$Cols X $Lins$Norm } clear read -n1 -p "Mude o tamanho da tela ou tecle algo para terminar " - Perfeito! Que se dane a aparência, depois vou te ensinar uns macetes para melhorá-la o que vale é que o programa está funcionando e está bem enxuto. - Poxa, perdi o maior tempo tentando descobrir como aumentar o fonte ... - Deixe isso para lá e hoje vamos ver umas coisas bastante interessantes e úteis. Named Pipes
Um outro tipo de pipe é o $ ls -l pipe1
prw-r-r-- 1 julio dipao 0 Jan 22 23:11 pipe1|
O
Nos sistemas mais antigos, os
Nos sistemas mais modernos, a mesma tarefa é feita pelo $ mkfifo pipe1
Como sempre, a melhor forma de mostrar como algo funciona é dando exemplos. Suponha que nós tenhamos criado o $ ls -l > pipe1
e em outra faça: $ cat < pipe1
Voilá! A saída do comando executado na primeira console foi exibida na segunda. Note que a ordem em que os comandos ocorreram não importa.
Se você prestou atenção, reparou que o primeiro comando executado, parecia ter "pendurado, congelado". Isto acontece porque a outra ponta do pipe ainda não estava conectada, e então o sistema operacional suspendeu o primeiro processo até que o segundo "abrisse" o pipe. Para que um processo que usa pipe não fique em modo de wait, é necessário que em uma ponta do pipe tenha um processo "tagarela" e na outra um "ouvinte" e no exemplo que demos, o
Uma aplicação muito útil dos Você já viu que o uso desta ferramenta é ótimo para sincronizar processos e para fazer bloqueio em arquivos de forma a evitar perda/corrupção de informações devido a atualizações simultâneas (concorrência). Vejamos exemplos para ilustrar estes casos. Sincronização de processos.Suponha que você dispare paralelamente dois programas (processos) cujos diagramas de blocos de suas rotinas são como a figura a seguir:
Os dois processos são disparados em paralelo e no for Arq in BigFile1 BigFile2 BigFile3 do if sort $Arq then Manda=va else Manda=pare break fi done echo $Manda > pipe1 [ $Manda = pare ] && { echo Erro durante a classificação dos arquivos exit 1 } ...
Assim sendo, o comando
Enquanto o
O fragmento de código do OK=`cat pipe1` if [ $OK = va ] then ... Rotina de impressão ... else # Recebeu "pare" em OK exit 1 fi
Após a execução de seu primeiro bloco, o Bloqueio de arquivosSuponha que você escreveu uma CGI (Common Gateway Interface) em Shell para contar quantos hits recebe uma determinada URL e a rotina de contagem está da seguinte maneira: Hits="$(cat page.hits 2> /dev/null)" || Hits=0 echo $((Hits=Hits++)) > page.hits
Desta forma se a página receber dois ou mais acessos concorrentes, um ou mais poderá(ão) ser perdido(s), basta que o segundo acesso seja feito após a leitura da arquivo
Então o que fazer? Para resolver o problema de concorrência vamos utilizar um $ cat contahits.sh
#!/bin/bash
PIPE="/tmp/pipe_contador" # arquivo named pipe # dir onde serao colocados os arquivos contadores de cada pagina DIR="/var/www/contador" [ -p "$PIPE" ] || mkfifo "$PIPE" while : do for URL in $(cat < $PIPE) do FILE="$DIR/$(echo $URL | sed 's,.*/,,')" # OBS1: no sed acima, como precisava procurar # uma barra,usamos vírgula como separador. # OBS2: quando rodar como daemon comente a proxima linha echo "arquivo = $FILE" n="$(cat $FILE 2> /dev/null)" || n=0 echo $((n=n+1)) > "$FILE" done done Como só este script altera os arquivos, não existe problema de concorrência. Este script será um daemon, isto é, rodará em background. Quando uma página sofrer um acesso, ela escreverá a sua URL no arquivo de pipe. Para testar, execute este comando: echo "teste_pagina.html" > /tmp/pipe_contador Para evitar erros, em cada página que quisermos adicionar o contador acrescentamos a seguinte linha: <!--#exec cmd="echo $REQUEST_URI > /tmp/pipe_contador"-->
Note que a variável Este último exemplo, é fruto de uma idéia que troquei com o amigo e mestre em Shell, Thobias Salazar Trevisan que escreveu o script e colocou-o em sua excelente URL. Aconselho a todos que querem aprender Shell a dar uma olhada nela (Dê uma olhada e inclua-a nos favoritos).
Ahhh! Você pensa que o assunto sobre Substituição de processos
Acabei de mostrar um monte de dicas sobre $ cat <(ls -l)
Resultará no comando Como poderemos constatar isso? Fácil... Veja o comando a seguir: $ ls -l >(cat)
l-wx------ 1 jneves jneves 64 Aug 27 12:26 /dev/fd/63 -> pipe:[7050]
É... Realmente é um
Você deve estar pensando que isto é uma maluquice de nerd, né? Então suponha que você tenha 2 diretórios: $ cmp <(cat dir/*) <(cat dir.bkp/*) || echo backup furado
ou, melhor ainda: $ cmp <(cat dir/*) <(cat dir.bkp/*) >/dev/null || echo backup furado
Da forma acima, a comparação foi efetuada em todas as linhas de todos os arquivos de ambos os diretórios. Para acelerar o processo, poderíamos compara somente a listagem longa de ambos os diretórios, pois qualquer modificação que um arquivo sofra, é mostrada na data/hora de alteração e/ou no tamanho do arquivo. Veja como ficaria: $ cmp <(ls -l dir) <(ls -l dir.bkp) >/dev/null || echo backup furado
Este é um exemplo meramente didático, mas são tantos os comandos que produzem mais de uma linha de saída, que serve como guia para outros. Eu quero gerar uma listagem dos meus arquivos, numerando-os e ao final dar o total de arquivos do diretório corrente: while read arq do ((i++)) # assim nao eh necessario inicializar i echo "$i: $arq" done < <(ls) echo "No diretorio corrente (`pwd`) existem $i arquivos"
Tá legal, eu sei que existem outras formas de executar a mesma tarefa. Usando o comando ls | while read arq do ((i++)) # assim nao eh necessario inicializar i echo "$i: $arq" done echo "No diretorio corrente (`pwd`) existem $i arquivos"
Quando executasse o script, pareceria estar tudo certo, porém no comando Somente para te mostrar que uma variável criada fora do subshell e alterada em seu interior perde as alterações feitas ao seu final, execute o script a seguir: #!/bin/bash LIST="" # Criada no shell principal ls | while read FILE # Inicio do subshell do LIST="$FILE $LIST" # Alterada dentro do subshell done # Fim do subshell echo :$LIST:
Ao final da execução você verá que aperecerão apenas dois dois-pontos ( $ ls | ln
ou então, usando a própria substituição de processos: $ cat -n <(ls)
Um último exemplo: você deseja comparar $ comm <(sort arq1) <(sort arq2)
Esta forma evita que você faça as seguintes operações: $ sort arq1 > /tmp/sort1
$ sort arq2 > /tmp/sort2
$ comm /tmp/sort1 /tmp/sort2
$ rm -f /tmp/sort1 /tmp/sort2
Pessoal, o nosso Papo de Botequim chegou ao fim . Curti muito aqui e recebi diversos elogios pelo trabalho desenvolvido ao longo de doze meses e, o melhor de tudo, fiz muitas amizades e tomei muitos chopes de graça com os leitores que encontrei pelos congressos e palestras que ando fazendo pelo nosso querido Brasil.
O que vou escrever aqui não está combinado nem sei se será publicado, mas como os editores desta revista são dois malucos beleza (ambos Rafael), é bem capaz de deixarem passar. É o seguinte: se quiserem que o Papo de Botequim continue, entulhem a caixa postal da Linux Magazine pedindo por isso e desde já escolham o próximo tema entre De qualquer forma, caso não consigamos sensibilizar a direção da revista, me despeço de todos mandando um grande abraço aos barbudos e beijos às meninas e agradecendo os mais de 100 e-mails que recebi (todos elogiosos) e todos devidamente respondidos. À saúde de todos nós: Tim, Tim. - Chico, fecha a minha conta porque vou mudar de botequim. Vou aproveitar também para mandar o meu jabá: diga para os amigos que quem estiver afim de fazer um curso porreta de programação em Shell que mande um e-mail para a nossa gerencia de treinamento para informar-se. Qualquer dúvida ou falta de companhia para um chope ou até para falar mal dos políticos é só mandar um e-mail para mim. Valeu! |
Licença Creative Commons - Atribuição e Não Comercial (CC) 2009 Pelos Frequentadores do Bar do Júlio Neves. Todo o conteúdo desta página pode ser utilizado segundo os termos da Creative Commons License: Atribuição-UsoNãoComercial-PermanênciaDaLicença. |