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 - andersonriz...@gmail.com; - 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 el...@7seven.com.br; - 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 ${copr...@]} 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 <ala...@pobox.com> 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 > > cristi...@mga0-fwall-dmz:/tmp> tail -f pipe | tr -d "@"& > > [As partes desta mensagem que não continham texto foram removidas] ------------------------------------ --------------------------------------------------------------------- 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: shell-script-unsubscr...@yahoogrupos.com.br --------------------------------------------------------------------- Esta lista é moderada de acordo com o previsto em http://www.listas-discussao.cjb.net --------------------------------------------------------------------- Servidor Newsgroup da lista: news.gmane.org Grupo: gmane.org.user-groups.programming.shell.brazil Links do Yahoo! Grupos <*> Para visitar o site do seu grupo na web, acesse: http://br.groups.yahoo.com/group/shell-script/ <*> Para sair deste grupo, envie um e-mail para: shell-script-unsubscr...@yahoogrupos.com.br <*> O uso que você faz do Yahoo! Grupos está sujeito aos: http://br.yahoo.com/info/utos.html