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

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

Re: [shell-script] Re: Limpando lixo de executável


From: Julio C. Neves
Subject: Re: [shell-script] Re: Limpando lixo de executável
Date: Tue, 4 May 2010 14:45:43 -0300

Fala Alain,
o Bash 4.0 incorporou a filosofia de thread que permite paralelizar
processos. como a 8a. edição do meu livro aborda as principais alterações do
Bash 4.0, apesar de ainda não tê-lo publicado em papel, em
www.julioneves.com já tem o pdf que mandei para a editora. assim sendo, quem
quiser atualizar o seu livro, vá neste site, escolha no menu "Changelogs do
livro Programação Shell Linux" e luma vez lá, escolha "Faça o download do
PDF com as mudanças da *7ª* para a *8ª* edição". Neste pdf procure a seção
"coprocessos".

O conteúdo desta seção tb pode ser lido abaixo da minha assinatura, porém
desformatado.

Abraços,
Julio
Cursos de Shell e Zenity em 2 fins de semana?
- Aracaju turma de Shell em 12/05 - address@hidden;
- DF turma de Shell em 12/06 - ligue (61)3223-3000;
- RJ turma de Shell em 14/06 - ligue (21)2210-6061;
- Floripa turma de Shell e Zenity 12/07 – address@hidden;
- Turmas fechadas em outras cidades ligue (21)8112-9988.


Coprocessos
A partir da versão 4.0, o Bash incorporou o comando coproc. Este novo
intrínseco
(builtin) permite dois processos assíncronos se comunicarem e interagirem.
Como cita
Chet Ramey no Bash FAQ, ver. 4.01:
        "Há uma nova palavra reservada, coproc, que especifica um
coprocesso: um
        comando assíncrono que é executado com 2 pipes conectados ao Shell
criador.
        coproc pode receber nome. Os descritores dos arquivos de entrada e
saída e o PID
        do coprocesso estão disponíveis para o Shell criador em variáveis
com nomes
        específicos do coproc."
George Dimitriu explica:
        "coproc é uma facilidade usada na substituição de processos que
agora está
        publicamente disponível."
A comprovação do que disse Dimitriu não é complicada, quer ver? Veja a
substituição de
processos a seguir:
$ cat <(echo xxx; sleep 3; echo yyy; sleep 3)
Viu?! O cat não esperou pela conclusão dos comandos entre parênteses, mas
foi
executado no fim de cada um deles. Isso aconteceu porque estabeleceu-se um
pipe
temporário/dinâmico e os comandos que estavam sendo executados, mandavam
para ele
as suas saídas, que por sua vez as mandava para a entrada do cat.
Isso significa que os comandos desta substituição de processos rodaram
paralelos,
sincronizando somente nas saídas dos echo com a entrada do cat.
A sintaxe de um coprocesso é:
        coproc [nome] cmd redirecionamentos
Isso criará um coprocesso chamado nome. Se nome for informado, cmd deverá
ser um
comando composto. Caso contrário (no caso de nome não ser informado), cmd
poderá
ser um comando simples ou composto.
Quando um coproc é executado, ele cria um vetor com o mesmo nome nome no
Shell
criador. Sua saída padrão é ligada via um pipe a um descritor de arquivo
associado à
variável ${nome[0]} à entrada padrão do Shell pai (lembra que a entrada
padrão de um
processo é sempre associada por default ao descritor zero?). Da mesma forma,
a entrada
do coproc é ligada à saída padrão do script, via pipe, a um descritor de
arquivos
chamado ${nome[1]}.
Assim, simplificando, vemos que o script mandará dados para o coproc pela
variável $
{nome[0]}, e receberá sua saída em ${nome[1]}.
Note que estes pipes serão criados antes dos redirecionamentos especificados
pelo
comando, já que eles serão as entradas e saídas do coprocesso.
A partir daqui, vou detalhar rapidamente uns estudos que fiz. Isso contém um
pouco de
divagações e muita teoria. Se você pular para depois desses ls's, não
perderá nada,
mas se acompanhar, pode ser bom para a compreensão do mecanismo do coproc.
Após colocar um coproc rodando, se ele está associado a um descritor de
arquivo,
vamos ver o que tem ativo no diretório correspondente:
$ ls -l /dev/fd
lrwxrwxrwx 1 root root 13 2010-01-06 09:31 /dev/fd -> /proc/self/fd
Hummm, é um link para o /proc/self/fd... O que será que tem lá?
$ ls -l /proc/self/fd
total 0
lrwx------ 1 julio julio 64 2010-01-06 16:03 0 -> /dev/pts/0
lrwx------ 1 julio julio 64 2010-01-06 16:03 1 -> /dev/pts/0
lrwx------ 1 julio julio 64 2010-01-06 16:03 2 -> /dev/pts/0
lr-x------ 1 julio julio 64 2010-01-06 16:03 3 -> /proc/3127/fd
Epa, que o 0, 1 e 2 apontavam para /dev/pts/0 eu já sabia, pois são a
entrada
padrão, saída padrão e saída de erros padrão apontando para o pseudo
terminal corrente,
mas quem será esse maldito device 3? Vejamos:
                                           $$ É o PID do Shell corrente
$ ls -l /proc/$$/fd
total 0
lr-x------ 1 julio julio       64  2010-01-06      09:31    0 -> /dev/pts/0
lrwx------ 1 julio julio       64  2010-01-06      09:31     1 -> /dev/pts/0
lrwx------ 1 julio julio       64  2010-01-06      09:31     2 -> /dev/pts/0
lrwx------ 1 julio julio       64  2010-01-06      16:07    255 ->
/dev/pts/0
l-wx------ 1 julio julio       64  2010-01-06      16:07    54 ->
pipe:[168521]
l-wx------ 1 julio julio       64  2010-01-06      16:07    56 ->
pipe:[124461]
l-wx------ 1 julio julio       64  2010-01-06      16:07    58 ->
pipe:[122927]
lr-x------ 1 julio julio       64  2010-01-06      16:07    59 ->
pipe:[168520]
l-wx------ 1 julio julio       64  2010-01-06      16:07    60 ->
pipe:[121302]
lr-x------ 1 julio julio       64  2010-01-06      16:07    61 ->
pipe:[124460]
lr-x------ 1 julio julio       64  2010-01-06      16:07    62 ->
pipe:[122926]
lr-x------ 1 julio julio       64  2010-01-06      16:07    63 ->
pipe:[121301]
Epa, aí estão os links apontando para os pipes. Esse monte de arquivo de
pipe que foi
listado, deve ser porque estava testando exaustivamente essa nova facilidade
do Bash.
Para terminar esta teoria chata, falta dizer que o PID do Shell gerado para
interpretar o
coproc pode ser obtido na variável $nome_PID e o comando wait pode ser usado
para
esperar pelo fim do coprocesso. O código de retorno do coprocesso ($?) é o
mesmo de
cmd.
Exemplos:
Vamos começar com o mais simples: um exemplo sem nome e direto no prompt:
                                           coproc ativo
$ coproc while read Entra
> do
>       echo -=-=- $Entra -=-=-
> done
[2] 3030
                                           Manda Olá para a pipe da saída
$ echo Olá >&${COPROC[1]}
                                           Lê do pipe da entrada
$ read -u ${COPROC[0]} Sai
$ echo $Sai
-=-=- Olá -=-=-
                                           Isso não pode ser esquecido...
$ kill $COPROC_PID
Como você viu, o vetor COPROC, está associado a dois pipes; o ${COPROC[1]}
que
contém o endereço do pipe de saída, e por isso a saída do echo esta
redirecionada para
ele e o ${COPROC[0]} que contém o endereço do pipe de entrada, e por isso
usamos a
opção -u do read que lê dados a partir de um descritor de arquivo definido,
ao invés da
entrada padrão.
Como o coprocesso utilizava a sintaxe sem nome, o padrão do nome do vetor é
COPROC.
Só mais uma teoriazinha chata:
                                           Lista todos os elementos do vetor
$ echo ${COPROC[@]}
59 54
Como você viu ${COPROC[0]} estava usando o pipe apontado por /proc/$$/fd /59
e
${COPROC[1]} usava /proc/$$/fd /54.
Agora chega de teoria mesmo! Vamos agora usar nome neste mesmo exemplo, para
ver
que pouca coisa muda:
$ coproc teste {
> while read Entra
> do
>        echo -=-=- $Entra -=-=-
> done
> }
[6] 3192
$ echo Olá >&${teste[1]}
$ read -u ${teste[0]} Sai
$ echo $Sai
-=-=- Olá -=-=-
$ kill $teste_PID
Nesse momento, é bom mostrar uma coisa interessante: Quais são os processos
em
execução?
                                         Somente um Bash em execução
$ ps
   PID TTY             TIME CMD
  1900 pts/0       00:00:01 bash
  2882 pts/0       00:00:00 ps
Vamos executar 2 coprocessos simultâneos:
                                         Coprocesso nome1
$ coproc nome1 {
> while read x
> do
>       echo $x
> done; }
[1] 2883
                                         Coprocesso nome2
$ coproc nome2 {
> while read y
> do
>       echo $y
> done; }
bash: aviso: execute_coproc: coproc [2883:nome1] still exists
[2] 2884
Xiiii! Acho que deu zebra! Mas será que deu mesmo? Repare que além do PID
2883 de
nome1, ele também me devolveu o PID 2884, que deve ser de nome2. Vamos ver o
que está acontecendo:
$ ps
   PID   TTY           TIME   CMD
                                         Esse já existia
  1900   pts/0     00:00:01  bash
                                         Esse está executando nome1
  2883   pts/0     00:00:00   bash
                                         Esse está executando nome2
  2884   pts/0     00:00:00   bash
  2885   pts/0     00:00:00   ps
Parece que foi só um aviso, pois os dois PIDs informados quando iniciamos os
dois
coprocessos, estão ativos. Então vamos testar esses 2 caras:
                                         Mandando cadeia para nome1
$ echo xxxxxxxxx >&${nome1[1]}
                                         Mandando cadeia para nome2
$ echo yyyyyyyyy >&${nome2[1]}
$ read -u ${nome1[0]} Recebe
$ echo $Recebe
xxxxxxxxx
$ read -u ${nome2[0]} Recebe
$ echo $Recebe
yyyyyyyyy
$ kill $nome1_PID
$ kill $nome2_PID



Em 4 de maio de 2010 13:14, Alain Mouette <address@hidden> escreveu:

>
>
> Vou recomeçar toda minha explicação de novo, tá difícil...
>
> Vamos simular meu aplicativo com este script:
>
> #!/bin/bash
> echo mensagem1
> sleep 2
> echo @mensagem2
>
> Eu testei todas as sujestões dadas, e todas funcionam e não resolvem. Eu
> preciso ver o mensagem1 **NA HORA** e a segunda (sem o @) na hora dela.
> Todas as sugestões mostram as duas juntas depois...
>
> Espero ter ficado mais claro, desculpem minhas explicações
> incompreensíveis aso que dedicaram tempo ao meu problema...
> Alain
>
> PS: o motivo disso é que o aplicativo pode parar no meio, por motivos de
> hw externo, mostrando um aviso que preciso ver.
>
> Em 03-05-2010 22:29, box_ferrari escreveu:
> > mkfifo pipe
> > cristiano@mga0-fwall-dmz:/tmp> tail -f pipe | tr -d "@"&
>  
>


[As partes desta mensagem que não continham texto foram removidas]



reply via email to

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