shell-script-pt
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RES: [shell-script] Scripts em paralelo...


From: Julio Cezar Neves - DATAPREVRJ
Subject: RES: [shell-script] Scripts em paralelo...
Date: Thu, 9 Oct 2003 13:13:07 -0300

Fernando,
use named-pipes (ou fifo). Abaixo vou poiar um pedaço do livro que fala
sobre o assunto:

Uma vantagem muito útil que o Linux/Unix lhe oferece são os named pipes, que
permitem a comunicação entre processos diferentes.
Uma característica fundamental que é extremamente útil aos usuários
Linux/Unix é o pipe. Os pipes permitem que processos separados se comuniquem
sem terem sido desenvolvidos para trabalharem juntos. Isto permite que
ferramentas bastante específicas em suas funções sejam combinadas de formas
complexas.
Um exemplo simples do uso de pipes é o comando:
$ ls | fgrep que

Quando o Shell examina a linha de comandos ele acha a barra vertical (|) que
separa os dois comandos. O Shell  executa ambos os comandos, conectando a
saída do primeiro à entrada do segundo.
O programa ls produz a lista dos arquivos no diretório corrente, enquanto o
grep lê a saída do ls e imprime somente aqueles que contêm a cadeia que em
seus nomes.
O exemplo mostado acima, que já é familiar a vocês, é um exemplo de um
unamed pipe. O pipe existe somente no interior do kernel e não pode ser
acessado pelo processo que o criou, neste caso, o Shell . 
Um outro tipo de pipe é o named pipe que também é chamado de FIFO. FIFO é um
acrônimo de "First In First Out" que se refere à propriedade em que a ordem
dos bytes entrando no pipe é a mesma que a da saída. O name  em named pipe
é, na verdade, o nome de um arquivo. Os arquivos tipo named pipes são
exibidos pelo comando ls como qualquer outro, com poucas diferenças:
$ ls -l fifo1
prw-r-r--   1 julio  dipao    0 Jan 22 23:11 fifo1|

o p na coluna mais à esquerda indica que fifo1 é um named pipe. O resto dos
bits de controle de permissões, quem pode ler ou gravar o pipe, funcionam
como um arquivo normal. Nos sistemas mais modernos um caracter | colocado ao
fim do nome do arquivo, é outra dica, e nos sistemas Linux, onde a opção de
cor está habilitada, o nome do arquivo é escrito em vermelho por default.
Nos sistemas mais antigos, os named pipes são criados pelo programa mknod,
normalmente situado no diretório /etc. Nos sistemas mais modernos, a mesma
tarefa é feita pelo mkfifo. O programa mkfifo recebe um ou mais nomes como
argumento e cria pipes com estes nomes. Por exemplo para criar um named pipe
com o nome pipe1, faça:
$ mkfifo pipe1

Exemplos:
Como sempre, a melhor forma de mostrar como algo funciona é dando exemplos.
Suponha que nós tenhamos criado o named pipe mostrado anteriormente. Em
outra sessão ou uma console virtual, faça:
$ ls -l > pipe1

e em outra, faça:
$ cat < pipe1

Voilá! A saída do comando executado na primeira console foi exibido 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". Isto acontece porque a outra ponta do pipe ainda não estava
conectada, e então o kernel suspendeu o primeiro processo até que o segundo
"abrisse" o pipe, isto é 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".
Uma aplicação muito útil dos named pipes é permitir que programas sem
nenhuma relação, possam se comunicar entre si. 
Por exemplo, um programa que serve algum tipo de requisição (imprimir
arquivos, acessar banco de dados)  poderia abri o arquivo de pipe para
leitura (seria o processo "ouvinte"). Então, outro processo poderia fazer
esta requisição abrindo o pipe passando o comando (este seria o "tagarela").
Isto é, o "servidor" poderia executar uma tarefa em benefício do "cliente".
Exemplos:
Suponha que, para não gerar inconsistências em um arquivo que seja alterado
por muitos usuários, todas inclusões, exclusões e alterações de registros
sejam feitos por um só programa servidor que sempre estará em backgound.
Veja só como ficaria simples:
$ mkfifo pipe1  Criando um arquivo tipo pipe
$ ls -l pipe1
prw-r--r--   1 jneves   ssup              0 Jan 14 17:48 pipe1
$ cat cliente   Passador de dados para atualização do arquivo (tagarela)
#!/bin/sh
clear
echo "
                           O que voce deseja fazer?


                                1 - Incluir

                                2 - Excluir

                                3 - Alterar

                          Informe a sua opcao: "
tput cup 10 47
read Opc
Txt=
tput cup 12 26
case $Opc in
        1)  echo "Informe o conteudo do novo registro:"
                tput cup 14 26
                read Reg
                Cmd=a
                ;;
        2)      echo "Exclusao de qual registro?"
                tput cup 14 26
                read Reg
                Cmd=d
                ;;
        3)      echo "Informe o texto antigo:"
                tput cup 14 26
                read Reg
                tput cup 16 26
                echo "Informe o novo texto:"
                tput cup 18 26
                read Txt
                Cmd=c
                ;;
        *)      echo ""
                exit
                ;;
esac
echo "$Cmd:$Reg:$Txt" > pipe1

Veja agora o programa que atualiza o arquivo.
$ cat servidor  Prog em background que atualiza o arquivo (ouvinte)
trap "rm /tmp/$$ 2> /dev/null; exit" 0 1 2 15

while true
do
    Cmd=`cat pipe1`
    case `echo $Cmd | cut -f1 -d:` in
        a)  echo `echo $Cmd | cut -f2 -d:` >> arquivo
            ;;
        d)  grep -v `echo $Cmd | cut -f2 -d:` arquivo > /tmp/$$
            mv -f /tmp/$$ arquivo
            ;;
c)      EraAssim=`echo $Cmd | cut -f2 -d:`
            SeraAssim=`echo $Cmd | cut -f3 -d:`
            sed "s/$EraAssim/$SeraAssim/" arquivo > /tmp/$$
            mv -f /tmp/$$ arquivo
            ;;
    esac
done

Uma outra forma (menos nobre) de utilizarmos o FIFO é para 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 BLOCO1 do Programa1 as
três classificações são disparadas da seguinte maneira:
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 if testa cada classificação que esta sendo efetuada.
Caso ocorra qualquer problema, as classificações seguintes são abortadas,
uma mensagem contendo a cadeia pare é enviada pelo pipe1 e programa1 é
descontinuado com um fim anormal.
Enquanto o Programa1 executava o seu primeiro bloco (as classificações) o
Programa2 executava o seu BLOCO1, processando as suas rotinas de abertura e
menu paralelamente ao Programa1, ganhando desta forma um bom intervalo de
tempo.
O fragmento de código do Programa2 a seguir, mostra a transição do seu
BLOCO1 para o BLOCO2:
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 Programa2 passará a "ouvir" o
pipe1, ficando parado até que as classificações do Programa1 terminem,
testando a seguir a mensagem passada pelo pipe1 para decidir se os arquivos
estão íntegros para serem impressos, ou se o programa deverá ser
descontinuado.

[ ]s,
Julio Cezar Neves
-Programa de Software Livre da DATAPREV-
-I Support Free Software-
* +55 21 2528-7070  /  +55 21 8112-9988
*address@hidden


> -----Mensagem original-----
> De: Fernando Lemes da Silva [mailto:address@hidden]
> Enviada em: quinta-feira, 9 de outubro de 2003 11:53
> Para: address@hidden
> Assunto: [shell-script] Scripts em paralelo...
> 
> 
> 
>    Pessoal, estou querendo fazer dois scripts rodar em 
> paralelo, mas o loop
> de um depende da saida do outro. A ideia que tive é do 
> primeiro gerar a
> saida em um arquivo e o segundo leria o arquivo e faria o resto. Se o
> segundo terminar o serviço e o primeiro não tiver acabado ele deveria
> esperar um pouco e tentar ler novamente os dados.
> 
>    O que eu ainda não descobri como fazer é : Como ler a 
> primeira linha do
> arquivo jogando ela pra saida padrão e ao mesmo tempo 
> removendo esta linha
> do arquivo ? Tem algo pronto que resolva esse problema ou eu 
> teria que fazer
> na mão ?
> 
>    Outra duvida é quando a trava de uso dos arquivos... o que 
> aconteceria se
> eu tentasse adicionar uma linha ao final do arquivo enquanto 
> outro programa
> le este arquivo ?
> 
>    Agradeço qualquer ajuda...
> 
>    []'s
>    Fernando Lemes
> 
> 
> 
> ---------------------------------------------------------------------
> Esta lista não admite a abordagem de outras liguagens de 
> programação, como perl, C etc. Quem insistir em não seguir 
> esta regra será moderado sem prévio aviso.
> ---------------------------------------------------------------------
> Sair da lista: address@hidden
> ---------------------------------------------------------------------
> Esta lista é moderada de acordo com o previsto em 
http://www.listasdiscussao.cjb.net
---------------------------------------------------------------------
 

Seu uso do Yahoo! Grupos é sujeito às regras descritas em:
http://br.yahoo.com/info/utos.html 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]