Difference: TWikiBarTalk011 (1 vs. 8)

Revision 825 Dec 2017 - Main.PauloSantana

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part XI


Line: 304 to 304
  - Waiter, close my account because I'm changing pub.
Changed:
<
<
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me.
>
>
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me.
  Thanks! \ No newline at end of file
Added:
>
>
start

-- PauloSantana - 25 Dec 2017

 \ No newline at end of file

Revision 724 Apr 2014 - JulioNeves

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part XI


Line: 294 to 294
 $ rm -f /tmp/sort1 /tmp/sort2
Changed:
<
<
Guys, our Pub Talk came to an end frown . I enjoyed myself here and I received many accolades for the work done over twelve months and, best of all, I made ​​many friends and drank many chopes of free with the readers who I found by congresses and lectures I've been doing for our beloved Brazil.
>
>
Guys, our Pub Talk came to an end frown . I enjoyed myself here and I received many accolades for the work done over twelve months and, best of all, I made ​​many friends and drank many beers of free with the readers who I found by congresses and lectures I've been doing for our beloved Brazil.
  What I will write here is not combined do not even know if it will be published, but as the editors of this journal are two crazy beauty (both Rafael), is well able to let go. It is this: if you want to keep the Pub Talk, fill the mailbox of Linux Magazine asking for it and already choose the next theme among sed + regular expressions or awk language.

Revision 622 Apr 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part XI


Line: 253 to 253
  echo "In the current directory (`pwd`) there is $i files"
Changed:
<
<
Quando executasse o script, pareceria estar tudo certo, porém no comando echo após o done, você verá que o valor de $i foi perdido. Isso deve-se ao fato desta variável estar sendo incrementada em um subshell criado pelo pipe (|) e que terminou no comando done, levando com ele todas as variáveis criadas no seu interior e as alterações feitas em todas as variáveis, inclusive as criadas externamente.
>
>
When you executed the script, would seem to be all right, but the command echo after the done you will see that the value of $i was lost. This is due to the fact that variable being incremented in a subshell created by the pipe (|) and ending in command done, taking with him all the variables created inside it and changes in all variables, including those created externally.
 
Changed:
<
<
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:
>
>
Just to show you that a variable created outside of subshell and changed in inside loses changes made to its end, run the following script:
 
    #!/bin/bash
Changed:
<
<
LIST="" # Criada no shell principal ls | while read FILE # Inicio do subshell
>
>
LIST="" # Created in the main shell ls | while read FILE # Start of subshell
  do
Changed:
<
<
LIST="$FILE $LIST" # Alterada dentro do subshell done # Fim do subshell
>
>
LIST="$FILE $LIST" # Changed within the subshell done # End the subshell
  echo :$LIST:
Changed:
<
<
Ao final da execução você verá que aperecerão apenas dois dois-pontos (::). Mas no início deste exemplo eu disse que era meramente didático porque existem formas melhores de fazer a mesma tarefa. Veja só estas duas:
>
>
At the end of the run you will see that only appear two colons (::). But earlier this example I said it was merely didactic because there are better ways of doing the same task. Look at these two:
 
$ ls | cat -n -
Changed:
<
<
ou então, usando a própria substituição de processos:
>
>
or, using the proper substitution processes:
 
$ cat -n <(ls)
Changed:
<
<
Um último exemplo: você deseja comparar arq1 e arq2 usando o comando comm, mas este comando necessita que os arquivos estejam classificados. Então a melhor forma de proceder é:
>
>
One last example: you want to compare arq1 and arq2 using the comm command, but this command requires that the files are sorted. So the best way to proceed is:
 
$ comm <(sort arq1) <(sort arq2)
Changed:
<
<
Esta forma evita que você faça as seguintes operações:
>
>
This form saves you perform the following operations:
 
$ sort arq1 > /tmp/sort1
Line: 294 to 294
 $ rm -f /tmp/sort1 /tmp/sort2
Changed:
<
<
Pessoal, o nosso Papo de Botequim chegou ao fim frown . 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.
>
>
Guys, our Pub Talk came to an end frown . I enjoyed myself here and I received many accolades for the work done over twelve months and, best of all, I made ​​many friends and drank many chopes of free with the readers who I found by congresses and lectures I've been doing for our beloved Brazil.
 
Changed:
<
<
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 sed + expressões regulares ou linguagem awk.
>
>
What I will write here is not combined do not even know if it will be published, but as the editors of this journal are two crazy beauty (both Rafael), is well able to let go. It is this: if you want to keep the Pub Talk, fill the mailbox of Linux Magazine asking for it and already choose the next theme among sed + regular expressions or awk language.
 
Changed:
<
<
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.
>
>
Anyway, if we can not sensitize the direction of the magazine, I say farewell to everyone sending a big hug to the bearded and kisses the girls and thanking the more than 100 e-mails I received (all complimentary) and all duly answered.
 
Changed:
<
<
À saúde de todos nós: Tim, Tim.
>
>
A toast to the health of us all!
 
Changed:
<
<
- Chico, fecha a minha conta porque vou mudar de botequim.
>
>
- Waiter, close my account because I'm changing pub.
 
Changed:
<
<
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.
>
>
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me.
 
Changed:
<
<
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!

-- AngelaFerreira - 16 Apr 2014

>
>
Thanks!

Revision 522 Apr 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part XI


Line: 194 to 194
  Ahhh! You think about it named pipes is exhausted? Was mistaken. I'll show a different use from now on.
Changed:
<
<

Substituição de processos

>
>

Process substitution

 
Changed:
<
<
Acabei de mostrar um monte de dicas sobre named pipes, agora vou mostrar que o Shell também usa os named pipes de uma maneira bastante singular, que é a substituição de processos (process substitution). Uma substituição de processos ocorre quando você põe um comando ou um pipeline de comandos entre parênteses e um < ou um > grudado na frente do parêntese da esquerda. Por exemplo, teclando-se o comando:
>
>
I just showed a lot of tips named pipes, now I will show that Shell also uses named pipes a rather unique way, which is the substitution process. A substitution process occurs when you put a command or pipeline of commands between parentheses and a < or a > stuck in front of the left parenthesis. For example, typing the command:
 
$ cat <(ls -l)
Changed:
<
<
Resultará no comando ls -l executado em um subshell como é normal (por estar entre parênteses), porém redirecionará a saída para um named pipe temporário, que o Shell cria, nomeia e depois remove. Então o cat terá um nome de arquivo válido para ler (que será este named pipe e cujo dispositivo lógico associado é /dev/fd/63), e teremos a mesma saída que a gerada pela listagem do ls -l, porém dando um ou mais passos que o usual, isto é, mais onerosa para o computador.
>
>
Will result in the command ls -l run in a subshell as is normal (by being in parentheses), but will redirect the output to a named pipe temporary, that the Shell creates, nominates and removes later. So the cat will have a valid file name to read (which will be this named pipe and whose associated logical device is /dev/fd/63), and we will have the same output as that generated by the listing of ls -l, but giving one or more steps than usual, that is more burdensome to the computer.
 
Changed:
<
<
Como poderemos constatar isso? Fácil... Veja o comando a seguir:
>
>
How can we note it? Easy ... See the following command:
 
$ ls -l >(cat) l-wx------ 1 jneves jneves 64 Aug 27 12:26 /dev/fd/63 -> pipe:[7050]
Changed:
<
<
É... Realmente é um named pipe.
>
>
It is... It really is a named pipe.
 
Changed:
<
<
Você deve estar pensando que isto é uma maluquice de nerd, né? Então suponha que você tenha 2 diretórios: dir e dir.bkp e deseja saber se os dois estão iguais (aquela velha dúvida: será que meu backup está atualizado?). Basta comparar os dados dos arquivos dos diretórios com o comando cmp, fazendo:
>
>
You must be thinking that this is a madness of nerd, right? So suppose you have two directories: dir and dir.bkp and want to know if the two are equal (that old doubt: will my backup is up to date?). Just compare the data with files from directories with cmp command, doing:
 
Changed:
<
<
$ cmp <(cat dir/*) <(cat dir.bkp/*) || echo backup furado
>
>
$ cmp <(cat dir/*) <(cat dir.bkp/*) || echo bored backup
 
Changed:
<
<
ou, melhor ainda:
>
>
or better yet:
 
Changed:
<
<
$ cmp <(cat dir/*) <(cat dir.bkp/*) >/dev/null || echo backup furado
>
>
$ cmp <(cat dir/*) <(cat dir.bkp/*) >/dev/null || echo bored backup
 
Changed:
<
<
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:
>
>
In the above form, the comparison was performed on all lines of all files in both directories. To accelerate the process, we could only compare the long listing of both directories, because any modification that suffers a file is shown in the date/time of change and/or file size. See how it would look:
 
Changed:
<
<
$ cmp <(ls -l dir) <(ls -l dir.bkp) >/dev/null || echo backup furado
>
>
$ cmp <(ls -l dir) <(ls -l dir.bkp) >/dev/null || echo bored backup
 
Changed:
<
<
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:
>
>
This is merely a didactical example, but there are so many commands that produce more than one output row, which serves as a guide for others. I want to generate a listing of my files, numbering them and in the end give the total number of files of the current directory:
 
    while read arq
    do
Changed:
<
<
((i++)) # assim nao eh necessario inicializar i
>
>
((i++)) # so it is not necessary to initialize i
  echo "$i: $arq" done < <(ls)
Changed:
<
<
echo "No diretorio corrente (`pwd`) existem $i arquivos"
>
>
echo "In the current directory (`pwd`) there is $i files"
 
Changed:
<
<
Tá legal, eu sei que existem outras formas de executar a mesma tarefa. Usando o comando while, a forma mais comum de resolver esse problema seria:
>
>
Alright, I know there are other ways to perform the same task. Using the command while, the most common way to solve this problem would be:
 
    ls | while read arq
    do
Changed:
<
<
((i++)) # assim nao eh necessario inicializar i
>
>
((i++)) # so it is not necessary to initialize i
  echo "$i: $arq" done
Changed:
<
<
echo "No diretorio corrente (`pwd`) existem $i arquivos"
>
>
echo "In the current directory (`pwd`) there is $i files"
 

Quando executasse o script, pareceria estar tudo certo, porém no comando echo após o done, você verá que o valor de $i foi perdido. Isso deve-se ao fato desta variável estar sendo incrementada em um subshell criado pelo pipe (|) e que terminou no comando done, levando com ele todas as variáveis criadas no seu interior e as alterações feitas em todas as variáveis, inclusive as criadas externamente.

Revision 422 Apr 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part XI


Line: 85 to 85
  You have seen that the use of this tool is great for synchronize processes and to lock files in order to avoid loss/corruption of information due to concurrent updates (competition). A few examples to illustrate these cases.
Changed:
<
<

Sincronização de processos.

>
>

Synchronization processes

 
Changed:
<
<
Suponha que você dispare paralelamente dois programas (processos) cujos diagramas de blocos de suas rotinas são como a figura a seguir:
>
>
Suppose you shoot parallel two (processes) programs whose block diagrams of their routines are like the following figure:
 
Changed:
<
<
Gráfico do Named Pipe
>
>
Graph of Named Pipe
 
Changed:
<
<
Os dois processos são disparados em paralelo e no BLOCO1 do Programa1 as três classificações são disparadas da seguinte maneira:
>
>
The two processes are triggered in parallel and in BLOCK1 of Program1 the three classifications are triggered as follows:
 
    for Arq in BigFile1 BigFile2 BigFile3
    do
        if  sort $Arq 
        then
Changed:
<
<
Manda=va
>
>
Send=go
  else
Changed:
<
<
Manda=pare
>
>
Send=stop
  break fi done
Changed:
<
<
echo $Manda > pipe1 [ $Manda = pare ] &&
>
>
echo $Send > pipe1 [ $Send = stop ] &&
  {
Changed:
<
<
echo Erro durante a classificação dos arquivos
>
>
echo Error while sorting files
  exit 1 } ...
Changed:
<
<
Assim sendo, o comando if testa cada classificação que está sendo efetuada. Caso ocorra qualquer problema, as classificações seguintes serão abortadas, uma mensagem contendo a cadeia pare é enviada pelo pipe1 e programa1 é descontinuado com um fim anormal.
>
>
Thus, the if command tests each classification being performed. Case a problem occurs, the following classifications will be aborted, a message containing the chain stop is sent by pipe1 and program1 is dropped with an abnormal end.
 
Changed:
<
<
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.
>
>
While the Program1 ran their first block (the classifications) the Program2 executed his BLOCK1, processing routine of opening and parallel menu to Program1, thereby gaining a good time interval.
 
Changed:
<
<
O fragmento de código do Programa2 a seguir, mostra a transição do seu BLOCO1 para o BLOCO2:
>
>
The fragment of code Program2 below, shows the transition of its BLOCK1 to BLOCK2:
 
    OK=`cat pipe1`
    if  [ $OK = va ]
    then
        ...
Changed:
<
<
Rotina de impressão
>
>
Print routine
  ...
Changed:
<
<
else # Recebeu "pare" em OK
>
>
else # Received "stop" in OK
  exit 1 fi
Changed:
<
<
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. Desta forma é possível disparar programas de forma assíncrona e sincronizá-los quando necessário, ganhando bastante tempo de processamento.
>
>
After running his first block, the Program2 will "listen" the pipe1, still standing until the classifications of Program1 finish testing the following message passed by pipe1 to decide if the files are righteous to be printed, or if the program should be discontinued. Thus it is possible to trigger asynchronously programs and sync them when needed, gaining enough processing time.
 
Changed:
<
<

Bloqueio de arquivos

>
>

Lock of files

 
Changed:
<
<
Suponha 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:
>
>
Suppose you wrote a CGI (Common Gateway Interface) in Shell to count how many hits receives a certain URL and counting routine is as follows:
 
    Hits="$(cat page.hits 2> /dev/null)" || Hits=0
    echo $((Hits++)) > page.hits
Changed:
<
<
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 page.hits e antes da sua gravação, isto é, basta que o segundo acesso seja feito após o primeiro ter executado a primeira linha do script e antes de executar a segunda.
>
>
This way if the page receives two or more concurrent accesses, one or more may (will) be lost, just that the second access is done after reading the file page.hits and before recording, ie it is sufficient that the second access be done after first having performed the first line of script and before the second run.
 
Changed:
<
<
Então o que fazer? Para resolver o problema de concorrência vamos utilizar um named pipe. Criamos o seguinte script que será o daemon que receberá todos os pedidos para incrementar o contador. Note que ele vai ser usado por qualquer página no nosso site que precise de um contador.
>
>
So what to do? To solve the competition problem we will use a named pipe. We created the following script will be the daemon will receive all requests to increment the counter. Note that it will be used by any page on our site that you need an accountant.
 
Changed:
<
<
$ cat contahits.sh
>
>
$ cat counthits.sh
 #!/bin/bash

Changed:
<
<
PIPE="/tmp/pipe_contador" # arquivo named pipe # dir onde serao colocados os arquivos contadores de cada pagina DIR="/var/www/contador"
>
>
PIPE="/tmp/pipe_counter" # file named pipe # dir where counters files of each page will be placed DIR="/var/www/counter"
  [ -p "$PIPE" ] || mkfifo "$PIPE"
Line: 163 to 163
  for URL in $(cat < $PIPE) do FILE="$DIR/$(echo $URL | sed 's,.*/,,')"
Changed:
<
<
# 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"
>
>
# NOTE1: in the sed above, as needed to look # A bar, use comma as separator. # NOTE2: when running as a daemon comment the next line echo "file = $FILE"
  n="$(cat $FILE 2> /dev/null)" || n=0 echo $((n=n+1)) > "$FILE"
Line: 174 to 174
 done
Changed:
<
<
Como só este script altera os arquivos, não existe problema de concorrência.
>
>
As only this script change the files, there is no competition problem.
 
Changed:
<
<
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:
>
>
This script is a daemon, that is, will run in the background. When a page access experience, she will write your URL in the pipe file. To test, run this command:
 
Changed:
<
<
echo "teste_pagina.html" > /tmp/pipe_contador
>
>
echo "test_page.html" > /tmp/pipe_counter
 
Changed:
<
<
Para evitar erros, em cada página que quisermos adicionar o contador acrescentamos a seguinte linha:
>
>
To avoid errors in each page that we want to add the counter, add the following line:
 
Changed:
<
<
<--#exec cmd="echo $REQUEST_URI > /tmp/pipe_contador"-->
>
>
<--#exec cmd="echo $REQUEST_URI > /tmp/pipe_counter"-->
 
Changed:
<
<
Note que a variável $REQUEST_URI contém o nome do arquivo que o navegador (browser) requisitou.
>
>
Note that the variable $REQUEST_URI contains the filename that the browser requested.
 
Changed:
<
<
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).
>
>
This last example is the result of an idea that I traded with friend and master Shell, Thobias Salazar Trevisan who wrote the script and put it in his excellent URL. I advise all who want to learn Shell to give a look at it (Take a look and add it to your favorites).
 
Changed:
<
<
Ahhh! Você pensa que o assunto sobre named pipes está esgotado? Enganou-se. Vou mostrar um uso diferente a partir de agora.
>
>
Ahhh! You think about it named pipes is exhausted? Was mistaken. I'll show a different use from now on.
 

Substituição de processos

Revision 322 Apr 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"

Pub Talk Part XI


Line: 48 to 48
 

Named Pipes

Changed:
<
<
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, veja:
>
>
Another type of pipe is named pipe, which is also called FIFO. FIFO is an acronym First In First Out it refers to the property in which the order of the bytes entering the pipe is the same as that of the output. The name in named pipe is, actually the name of a file. The type file named pipes are displayed by the command ls like any other, with a few differences, see:
 
$ ls -l pipe1 prw-r-r-- 1 julio dipao 0 Jan 22 23:11 pipe1|
Changed:
<
<
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 uma barra vertical (|) 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.
>
>
The p the leftmost column indicates that fifo1 is named pipe. The rest of the bits of permissions control who can read or write to the pipe, work as a normal file. In most modern systems a vertical bar (|) in LINUX systems placed at the end of the file name, is another tip, and where the color option is enabled, the file name is written in red by default.
 
Changed:
<
<
Nos sistemas mais antigos, os named pipes são criados pelo programa mknod, normalmente situado no diretório /etc.
>
>
In older systems, the named pipes are created by the program mknod normally located in the directory /etc.
 
Changed:
<
<
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:
>
>
In modern systems, the same task is done by mkfifo. The mkfifo program receives one or more names as an argument and creates pipes with these names. For example, to create a named pipe to the name pipe1 do:
 
$ mkfifo pipe1
Changed:
<
<
Como sempre, a melhor forma de mostrar como algo funciona é dando exemplos. Suponha que nós tenhamos criado o named pipe mostrado anteriormente. Vamos agora trabalhar com duas sessões ou duas consoles virtuais ou uma de cada. Em uma delas faça:
>
>
As always, the best way to show how something works is by giving examples. Suppose we have created the named pipe shown above. We will now work with two sessions or two virtual consoles or one of each. In one of them do:
 
$ ls -l > pipe1
Changed:
<
<
e em outra faça:
>
>
and other make:
 
$ cat < pipe1
Changed:
<
<
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.
>
>
Voila! The output of the command executed on the first console was displayed on the second. Note that the order in which the commands were not matter.
 
Changed:
<
<
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 ls era o "falador" e o cat era o "orelhão".
>
>
If you paid attention, noticed that the first command executed, seemed to have "hung, frozen." This happens because the other end of the pipe was still not connected, then the operating system suspended the first process until the second "open" the pipe. For a process that uses pipe not stay in wait mode, it is necessary that at one end of the pipe have a "talkative" process and in the other a "listener" and the example we gave, the ls was "talkative" and the cat was the "phone booth".
 
Changed:
<
<
Uma aplicação muito útil dos named pipes é permitir que programas sem nenhuma relação possam se comunicar entre si, os named pipes também são usados para sincronizar processos, já que em um determinado ponto você pode colocar um processo para "ouvir" ou para "falar" em um determinado named pipe e ele daí só sairá, se outro processo "falar" ou "ouvir" aquele pipe.
>
>
A very useful application of named pipes is allow programs unrelated to communicate with each other, the named pipes are also used to synchronize processes, since at a certain point you can put a process to "listen" or to "speak" in a given named pipe and then it will only come out if another process "talk" or "listen" that pipe.
 
Changed:
<
<
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.
>
>
You have seen that the use of this tool is great for synchronize processes and to lock files in order to avoid loss/corruption of information due to concurrent updates (competition). A few examples to illustrate these cases.
 

Sincronização de processos.

Revision 221 Apr 2014 - Main.AngelaFerreira

Line: 1 to 1
 
META TOPICPARENT name="WebHome"
Changed:
<
<

Papo de botequim parte XI

>
>

Pub Talk Part XI

 


Deleted:
<
<
     - E aí rapaz, tudo bom?
 
Changed:
<
<
     - 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.
>
>
This is a very new translation from Portuguese to English. Please contribute to the development of this site indicating errors and and/or suggesting corrections and materials for this person.
 
Changed:
<
<
     - 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.
>
>
     - Hey man, how are you?
 
Added:
>
>
     - All right, but remember that you asked me to make a program that when the size of a screen varied in its center dynamically appear in reverse video, the amount of rows and columns the way that Linux normally do? Yeah I did but the appearance wasn't equal.

     - I do not care for the look, what I wanted is that you exercise what we have learned. Let me see what you did.

 
$ cat tamtela.sh #!/bin/bash #
Changed:
<
<
# Coloca no centro da tela, em video reverso, # a quantidade de colunas e linhas # quando o tamanho da tela eh alterado.
>
>
# Puts the center of the screen in reverse video, # the amount of columns and rows # when the screen size changes.
 #
Changed:
<
<
trap Muda 28 # 28 = sinal gerado pela mudanca no tamanho # da tela e Muda eh a funcao que fara isso.
>
>
trap Change 28 # 28 = signal generated by the change in size # of the screen and Change is the function that will make it.
 
Changed:
<
<
Bold=$(tput bold) # Modo de enfase Rev=$(tput rev) # Modo de video reverso Norm=$(tput sgr0) # Restaura a tela ao padrao default
>
>
Bold=$(tput bold) # Mode of emphasis Rev=$(tput rev) # Mode of reverse video Norm=$(tput sgr0) # Restores the default screen
 
Changed:
<
<
Muda ()
>
>
Change ()
 { clear Cols=$(tput cols) Lins=$(tput lines)
Changed:
<
<
tput cup $(($Lins / 2)) $(((Cols - 7) / 2)) # Centro da tela
>
>
tput cup $(($Lins / 2)) $(((Cols - 7) / 2)) # Center of the screen
  echo $Bold$Rev$Cols X $Lins$Norm }

clear

Changed:
<
<
read -n1 -p "Mude o tamanho da tela ou tecle algo para terminar "
>
>
read -n1 -p "Change the size of the screen or press something to finish "
 
Changed:
<
<
     - 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.
>
>
     - Perfect! To hell the look, then I'll teach you a few tricks to improve it what matters is that the program is working well and is streamlined.
 
Changed:
<
<
     - Poxa, perdi o maior tempo tentando descobrir como aumentar o fonte ...
>
>
     - Gosh, I lost the most time trying to find how to increase font ...
 
Changed:
<
<
     - Deixe isso para lá e hoje vamos ver umas coisas bastante interessantes e úteis.
>
>
     - Leave it there and today we will see some very interesting and useful things.
 

Named Pipes

Revision 116 Apr 2014 - Main.AngelaFerreira

Line: 1 to 1
Added:
>
>
META TOPICPARENT name="WebHome"

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 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, veja:

$ ls -l pipe1 prw-r-r-- 1 julio dipao 0 Jan 22 23:11 pipe1|

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 uma barra vertical (|) 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

Como sempre, a melhor forma de mostrar como algo funciona é dando exemplos. Suponha que nós tenhamos criado o named pipe mostrado anteriormente. Vamos agora trabalhar com duas sessões ou duas consoles virtuais ou uma de cada. Em uma delas faça:

$ 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 ls era o "falador" e o cat era o "orelhão".

Uma aplicação muito útil dos named pipes é permitir que programas sem nenhuma relação possam se comunicar entre si, os named pipes também são usados para sincronizar processos, já que em um determinado ponto você pode colocar um processo para "ouvir" ou para "falar" em um determinado named pipe e ele daí só sairá, se outro processo "falar" ou "ouvir" aquele pipe.

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:

Gráfico do Named Pipe

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 está sendo efetuada. Caso ocorra qualquer problema, as classificações seguintes serã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. Desta forma é possível disparar programas de forma assíncrona e sincronizá-los quando necessário, ganhando bastante tempo de processamento.

Bloqueio de arquivos

Suponha 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++)) > 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 page.hits e antes da sua gravação, isto é, basta que o segundo acesso seja feito após o primeiro ter executado a primeira linha do script e antes de executar a segunda.

Então o que fazer? Para resolver o problema de concorrência vamos utilizar um named pipe. Criamos o seguinte script que será o daemon que receberá todos os pedidos para incrementar o contador. Note que ele vai ser usado por qualquer página no nosso site que precise de um contador.

$ 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 $REQUEST_URI contém o nome do arquivo que o navegador (browser) requisitou.

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 named pipes está esgotado? Enganou-se. Vou mostrar um uso diferente a partir de agora.

Substituição de processos

Acabei de mostrar um monte de dicas sobre named pipes, agora vou mostrar que o Shell também usa os named pipes de uma maneira bastante singular, que é a substituição de processos (process substitution). Uma substituição de processos ocorre quando você põe um comando ou um pipeline de comandos entre parênteses e um < ou um > grudado na frente do parêntese da esquerda. Por exemplo, teclando-se o comando:

$ cat <(ls -l)

Resultará no comando ls -l executado em um subshell como é normal (por estar entre parênteses), porém redirecionará a saída para um named pipe temporário, que o Shell cria, nomeia e depois remove. Então o cat terá um nome de arquivo válido para ler (que será este named pipe e cujo dispositivo lógico associado é /dev/fd/63), e teremos a mesma saída que a gerada pela listagem do ls -l, porém dando um ou mais passos que o usual, isto é, mais onerosa para o computador.

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 named pipe.

Você deve estar pensando que isto é uma maluquice de nerd, né? Então suponha que você tenha 2 diretórios: dir e dir.bkp e deseja saber se os dois estão iguais (aquela velha dúvida: será que meu backup está atualizado?). Basta comparar os dados dos arquivos dos diretórios com o comando cmp, fazendo:

$ 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 while, a forma mais comum de resolver esse problema seria:

    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 echo após o done, você verá que o valor de $i foi perdido. Isso deve-se ao fato desta variável estar sendo incrementada em um subshell criado pelo pipe (|) e que terminou no comando done, levando com ele todas as variáveis criadas no seu interior e as alterações feitas em todas as variáveis, inclusive as criadas externamente.

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 (::). Mas no início deste exemplo eu disse que era meramente didático porque existem formas melhores de fazer a mesma tarefa. Veja só estas duas:

$ ls | cat -n -

ou então, usando a própria substituição de processos:

$ cat -n <(ls)

Um último exemplo: você deseja comparar arq1 e arq2 usando o comando comm, mas este comando necessita que os arquivos estejam classificados. Então a melhor forma de proceder é:

$ 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 frown . 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 sed + expressões regulares ou linguagem awk.

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!

-- AngelaFerreira - 16 Apr 2014

 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki-SL? Send feedback