Difference: TWikiBarTalk010 (1 vs. 9)

Revision 925 Dec 2017 - Main.PauloSantana

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

Pub Talk Part X

Line: 523 to 523
       - Waiter, quickly bring the bill! I'll count to one and if you do not bring I'm leaving!
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.

next

-- PauloSantana - 25 Dec 2017

Revision 817 Apr 2014 - JulioNeves

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

Pub Talk Part X

Line: 521 to 521
  But before I'll let you think of a problem for you: when you vary the size of a screen, at its center not dynamically appear in reverse video the amount of rows and columns? So! I want you to play it using the Shell language.
Changed:
<
<
     - Waiter, quickly brings my account! I'll count to one and if you do not bring I'm leaving!
>
>
     - Waiter, quickly bring the bill! I'll count to one and if you do not bring I'm leaving!
  Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me.

Revision 716 Apr 2014 - Main.AngelaFerreira

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

Pub Talk Part X

Line: 307 to 307
  Suppose two cases: you have two scripts that we'll call script1, the first line will be a trap and script2, the latter being placed in the first run, and because they are two processes, will have two distinct PID.
Changed:
<
<
  • 1º Caso: O ftp encontra-se em script1
    Neste caso, o argumento do comando trap deveria vir entre aspas (") porque caso ocorresse uma interrupção (<CTRL+C> ou <CTRL+\>) no script2, a linha só seria interpretada neste momento e o PID do script2 seria diferente do encontrado em /tmp/$$ (não esqueça que $$ é a variável que contém o PID do processo ativo);
>
>
  • 1st case: The ftp It's found in script1
    In this case, the command argument trap should be quoted (") because if it occurred an interruption (<CTRL+C> or <CTRL+\>) in the script2, the line would only be interpreted at this moment and the PID of script2 be different from those found in /tmp/$$ (don't forget that $$ is the variable that contains the PID of the active process);
 
Changed:
<
<
  • 2º Caso: O ftp acima encontra-se em script2
    Neste caso, o argumento do comando trap deveria estar entre apóstrofos ('), pois caso a interrupção se desse durante a execução de script1, o arquivo não teria sido criado, caso ocorresse durante a execução de script2, o valor de $$ seria o PID deste processo, que coincidiria com o de /tmp/$$.
>
>
  • 2st case: The ftp above It's found in script2
    In this case, the command argument trap should be quoted ('), because if the interruption occurred while running script1, the file wouldn't have been created, if it occurred during the execution of script2, the value of $$ would PID of this process, which would coincide with that of /tmp/$$.
 
Changed:
<
<
O comando trap, quando executado sem argumentos, lista os sinais que estão sendo monitorados no ambiente, bem como a linha de comando que será executada quando tais sinais forem recebidos.
>
>
The command trap when run without arguments, lists the signals being monitored in the environment, as well as the command line that will be executed when such signals are received.
 
Changed:
<
<
Se a linha de comandos do trap for nula (vazia), isto significa que os sinais especificados devem ser ignorados quando recebidos. Por exemplo, o comando:
>
>
If the command line trap is null (empty), this means that the specified signal should be ignored when received. For example, the command:
 
    trap "" 2
Changed:
<
<
Especifica que o sinal de interrupção (<CTRL+C>) deve ser ignorado. No caso citado, quando não se deseja que sua execução seja interrompida. No último exemplo note que o primeiro argumento deve ser especificado para que o sinal seja ignorado, e não é equivalente a escrever o seguinte, cuja finalidade é retornar o sinal 2 ao seu estado padrão (default):
>
>
Specifies that the interrupt signal (<CTRL+C>) should be ignored. Thus in this case when you don't want your run is stopped. In the last example note that the first argument must be specified for the signal is ignored, and is not equivalent to write the following, whose purpose is to return the sign 2 to its default state (default):
 
    trap 2
Changed:
<
<
Se você ignora um sinal, todos os Subshells irão ignorar este sinal. Portanto, se você especifica qual ação deve ser tomada quando receber um sinal, então todos os Subshells irão também tomar a ação quando receberem este sinal, ou seja, os sinais são automaticamente exportados. Para o sinal que temos mostrado (sinal 2), isto significa que os Subshells serão encerrados.
>
>
If you ignore a signal, all Subshells will ignore this signal. So if you specify what action should be taken when receiving a signal, then all Subshells will also take action when they receive this signal, that is, the signals are automatically exported. For the signal we have shown (sign 2), this means that the Subshells are closed.
 
Changed:
<
<
Suponha que você execute o comando:
>
>
Suppose you run the command:
 
    trap "" 2
Changed:
<
<
e então execute um Subshell, que tornará a executar outro script como um Subshell. Se for gerado um sinal de interrupção, este não terá efeito nem sobre o Shell principal nem sobre os Subshell por ele chamados, já que todos eles ignorarão o sinal.
>
>
and then execute one Subshell, which will make another run script as a Subshell. If an interrupt signal is generated, this has no effect either on the main Shell nor on the "Subshell" called by him, since they all will ignore the signal.
 
Changed:
<
<
Outra forma de restaurar um sinal ao seu default é fazendo:
>
>
Another way to restore a signal to its default is doing:
 
Changed:
<
<
trap - sinal
>
>
trap - signal
 
Changed:
<
<
Em korn shell (ksh) não existe a opção -s do comando read para ler uma senha. O que costumamos fazer é usar o comando stty com a opção -echo que inibe a escrita na tela até que se encontre um stty echo para restaurar esta escrita. Então, se estivéssemos usando o interpretador ksh, a leitura da senha teria que ser feita da seguinte forma:
>
>
In korn shell (ksh) there isn't -s option of the command read to read a password. What we usually do is to use the stty command with the echo option that inhibits the writing on the screen until you find one stty echo to restore this writing. So, if we were using the interpreter ksh, the reading the password would have to be made ​​as follows:
 
Changed:
<
<
echo -n "Senha: "
>
>
echo -n "Password: "
  stty -echo
Changed:
<
<
read Senha
>
>
read Password
  stty echo
Changed:
<
<
O problema neste tipo de construção é que caso o operador não soubesse a senha, ele provavelmente daria um <CTRL+C> ou um <CTRL+\> durante a instrução read para descontinuar o programa e, caso ele agisse desta forma, o que quer que ele escrevesse, não apareceria na tela do seu terminal. Para evitar que isso aconteça, o melhor a fazer é:
>
>
The problem with this type of construction is that if the operator did not know the password, he probably would make a <CTRL+C> or a <CTRL+\> during the instruction read to discontinue the program, if he acted this way, whatever he wrote, did not appear on your terminal screen. To prevent this from happening, the best thing to do is:
 
Changed:
<
<
echo -n "Senha: "
>
>
echo -n "Password: "
  trap "stty echo exit" 2 3 stty -echo
Changed:
<
<
read Senha
>
>
read Password
  stty echo trap 2 3
Changed:
<
<
Para terminar este assunto, abra uma console gráfica e escreva no prompt de comando o seguinte:
>
>
To end this subject, open a graphical console and write the following at the command prompt:
 
Changed:
<
<
$ trap "echo Mudou o tamanho da janela" 28
>
>
$ trap "echo Changed the window size" 28
 
Changed:
<
<
Em seguida, pegue o mouse (arghh!!) e arraste-o de forma a variar o tamanho da janela corrente. Surpreso? É o Shell orientado a eventos... smile
>
>
Then take the mouse (arghh!!) And drag it in order to vary the size of the current window. Surprised? Is the Shell event oriented ... smile
 
Changed:
<
<
Mais unzinho porque não pude resistir. Agora escreva assim:
>
>
More one simple because I couldn't resist. Now type this:
 
Changed:
<
<
$ trap "echo já era" 17
>
>
$ trap "echo it was" 17
 
Changed:
<
<
Em seguida faça:
>
>
Then do:
 
$ sleep 3 &
Changed:
<
<
Você acabou de criar um subshell que irá dormir durante três segundos em background. Ao fim deste tempo, você receberá a mensagem já era, porque o sinal 17 é emitido a cada vez que um subshell termina a sua execução.
>
>
You just create a subshell which will sleep for three seconds in background. After this time, you will get the message it was, because the 17 is issued each time a subshell ends its execution.
 
Changed:
<
<
Para devolver estes sinais aos seus defaults, faça:
>
>
To return these signals to their defaults, do:
 
$ trap 17 28
Changed:
<
<
Ou
>
>
Or
 
$ trap - 17 28
Changed:
<
<
Acabamos de ver mais dois sinais que não são tão importante como os que vimos anteriormente, mas vou registrá-los na tabela a seguir:
>
>
We just saw two signs that are not as important as we saw earlier, but I'll record them in the following table:
 
Changed:
<
<
Sinais Não Muito Importantes
  28     SIGWINCH     Mudança no tamanho da janela gráfica  
Sinal  Gerado por:
  17     SIGCHLD     Fim de um processo filho  
>
>
Not Very Important Signs
  28     SIGWINCH     Change in the size of the graphics window  
Signal  Generatedr:
  17     SIGCHLD     End of a son process  
 
Changed:
<
<
Muito legal este comando, né? Se você descobrir algum caso bacana de uso de sinais, por favor me informe por e-mail porque é muito rara a literatura sobre o assunto.
>
>
Very cool this command, right? If you find some cool use case of signs, please let me know by e-mail because it is very rare literature about the subject.
 
Changed:
<
<

Comando getopts

>
>

Getopts command

 
Changed:
<
<
O comando getopts recupera as opções e seus argumentos de uma lista de parâmetros de acordo com a sintaxe POSIX.2, isto é, letras (ou números) após um sinal de menos (-) seguidas ou não de um argumento; no caso de somente letras (ou números) elas podem ser agrupadas. Você deve usar este comando para "fatiar" opções e argumento passados para o seu script.
>
>
The getopts command retrieves the options and their arguments from a list of parameters according to POSIX.2 syntax, that is, letters (or numbers) after a minus sign (-) followed or not an argument; in the case of only letters (or numbers) they can be grouped. You must use this command to "to slice" options and arguments passed to your script.
 
Changed:
<
<
Sintaxe:
>
>
Syntax:
 
Changed:
<
<
getopts cadeiadeopcoes nome
>
>
getopts optionschain name
 
Changed:
<
<
A cadeiadeopcoes deve explicitar uma cadeia de caracteres com todas as opções reconhecidas pelo script, assim se ele reconhece as opções -a -b e -c, cadeiadeopcoes deve ser abc. Se você deseja que uma opção seja seguida por um argumento, ponha dois-pontos (:) depois da letra, como em a:bc. Isto diz ao getopts que a opção -a tem a forma:
>
>
The optionschain must specify a character string with all the options recognized by script, so if it recognizes the options -a b and -c, optionschain must abc. If you want an option is followed by an argument, put a colon (:) after the letter, as in a:bc. This tells to the getopts the option -a has the form:
 
Changed:
<
<
-a argumento
>
>
-a argument
 
Changed:
<
<
Normalmente um ou mais espaços em branco separam o parâmetro da opção; no entanto, getopts também manipula parâmetros que vêm colados à opção como em:
>
>
Normally one or more white spaces separate the option parameter; however getopts also manipulates parameters that come attached to the option as in:
 
Changed:
<
<
-aargumento
>
>
-aargument
 
Changed:
<
<
cadeiadeopcoes não pode conter interrogação (?).
>
>
optionschain can not contain interrogation (?).
 
Changed:
<
<
O nome constante da linha de sintaxe acima, define uma variável que cada vez que o comando getopts for executado, receberá a próxima opção dos parâmetros posicionais e a colocará na variável nome.
>
>
The name constant syntax line above, defines a variable each time the command getopts runs, will receive the next option of the positional parameters and place it in the variable name.
 
Changed:
<
<
getopts coloca uma interrogação (?) na variável definida em nome se achar uma opção não definida em cadeiadeopcoes ou se não achar o argumento esperado para uma determinada opção.
>
>
getopts puts a question mark (?) in variable defined in name if find an option undefined in optionschain or if didn't find the expected argument for a given option.
 
Changed:
<
<
Como já sabemos, cada opção passada por uma linha de comandos tem um índice numérico, assim, a primeira opção estará contida em $1, a segunda em $2, e assim por diante. Quando o getopts obtém uma opção, ele armazena o índice do próximo parâmetro a ser processado na variável OPTIND.
>
>
As we already know, every last option for a command line has a numeric index, so the first option is contained in $1, the second in $2, and so on. When getopts gets an option, it stores the index of the next parameter to be processed in the variable OPTIND.
 
Changed:
<
<
Quando uma opção tem um argumento associado (indicado pelo : na cadeiadeopcoes), getopts armazena o argumento na variável OPTARG. Se uma opção não possui argumento ou o argumento esperado não foi encontrado, a variável OPTARG será "matada" (unset).
>
>
When an option has an associated argument (indicated by : in the optionschain) getopts stores the argument in the variable OPTARG. If an option has no argument or the expected argument is not found, the variable = OPTARG= be "killed" (unset).
 
Changed:
<
<
O comando encerra sua execução quando:
  • Encontra um parâmetro que não começa por menos (-);
  • O parâmetro especial -- marca o fim das opções;
  • Quando encontra um erro (por exemplo, uma opção não reconhecida).
>
>
The command terminates its execution when:
  • Find a parameter that does not start for minus (-);
  • The special parameter - marks the end of the options;
  • When it finds an error (for example, an unrecognized option).
 
Changed:
<
<
O exemplo abaixo é meramente didático, servindo para mostrar, em um pequeno fragmento de código o uso pleno do comando.
>
>
The example below is merely didactic, serving to show, in a small fragment code full use of the command.
 
$ cat getoptst.sh #!/bin/sh
Changed:
<
<
# Execute assim:
>
>
# Run so:
 #
Changed:
<
<
# getoptst.sh -h -Pimpressora arq1 arq2
>
>
# getoptst.sh -h -Pprinter arq1 arq2
 #
Changed:
<
<
# e note que as informacoes de todas as opcoes sao exibidas
>
>
# and note that the information of all options are displayed
 #
Changed:
<
<
# A cadeia 'P:h' diz que a opcao -P eh uma opcao complexa # e requer um argumento, e que h eh uma opcao simples que nao requer # argumentos.
>
>
# The chain 'P:h' says the option -P is a complex option # and requires an argument, and that h is a simple option that does not require # arguments.
 
Changed:
<
<
while getopts 'P:h' OPT_LETRA
>
>
while getopts 'P:h' OPT_LETTER
 do
Changed:
<
<
echo "getopts fez a variavel OPT_LETRA igual a '$OPT_LETRA'" echo " OPTARG eh '$OPTARG'"
>
>
echo "getopts made the variable OPT_LETTER equal the '$OPT_LETTER'" echo " OPTARG is '$OPTARG'"
 done used_up=`expr $OPTIND - 1`
Changed:
<
<
echo "Dispensando os primeiros \$OPTIND-1 = $used_up argumentos"
>
>
echo "Dispensing the first \$OPTIND-1 = $used_up arguments"
 shift $used_up
Changed:
<
<
echo "O que sobrou da linha de comandos foi '$*'"
>
>
echo "What remained the command line was '$*'"
 
Changed:
<
<
Para entendê-lo melhor, vamos executá-lo como está sugerido em seu cabeçalho:
>
>
To understand it better, we'll run it as is suggested in your header:
 
Changed:
<
<
$ getoptst.sh -h -Pimpressora arq1 arq2 getopts fez a variavel OPT_LETRA igual a 'h' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 2 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'
>
>
$ getoptst.sh -h -Pprinter arq1 arq2 getopts made the variable OPT_LETTER equal the 'h' OPTARG is '' getopts made the variable OPT_LETTER equal the 'P' OPTARG is 'printer' Dispensing the first $OPTIND-1 = 2 arguments What remained the command line was 'arq1 arq2'
 
Changed:
<
<
Desta forma, sem ter muito trabalho, separei todas as opções com seus respectivos argumentos, deixando somente os parâmetros que foram passados pelo operador para posterior tratamento.
>
>
This way, without too much hassle, I separated all the options with their respective arguments, leaving only the parameters that were passed by the operator for subsequent treatment.
 
Changed:
<
<
Repare que se tivéssemos escrito a linha de comando com o argumento (impressora) separado da opção (-P), o resultado seria exatamente o mesmo, exceto pelo $OPTIND, já que neste caso ele identifica um conjunto de três opções/argumentos e no anterior somente dois. Veja só:
>
>
Notice that if we had written the command line with the argument (printer) separated from (-P) option, the result would be exactly the same, except $OPTIND, since in this case it identifies a set of three options/arguments and only the previous two. Check it:
 
Changed:
<
<
$ getoptst.sh -h -P impressora arq1 arq2 getopts fez a variavel OPT_LETRA igual a 'h' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 3 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'
>
>
$ getoptst.sh -h -P printer arq1 arq2 getopts made the variable OPT_LETRA equal the 'h' OPTARG is '' getopts made the variable OPT_LETTER equal the 'P' OPTARG is 'printer' Dispensing the first $OPTIND-1 = 3 arguments What remained the command line was 'arq1 arq2'
 
Changed:
<
<
Repare, no exemplo a seguir, que se passarmos uma opção inválida, a variável $OPT_LETRA receberá um ponto-de-interrogação (?) e a $OPTARG será "apagada" (unset).
>
>
Notice at the following example, that if we pass an invalid option, the $OPT_LETTER variable will get a question mark (?) and the $OPTARG will be "erased" (unset).
 
Changed:
<
<
$ getoptst.sh -f -Pimpressora arq1 arq2 # A opção -f não é valida
>
>
$ getoptst.sh -f -Pprinter arq1 arq2 # The -f option is not valid
 ./getoptst.sh: illegal option -- f
Changed:
<
<
getopts fez a variavel OPT_LETRA igual a '?' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 2 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'
>
>
getopts made the variable OPT_LETTER equal the '?' OPTARG is '' getopts made the variable OPT_LETTER equal the 'P' OPTARG is 'printer' Dispensing the first $OPTIND-1 = 2 arguments What remained the command line was 'arq1 arq2'
 
Changed:
<
<
     - Me diz uma coisa: você não poderia ter usado um case para evitar o getopts?
>
>
     - Tell me something: you couldn't have used a case to avoid getopts?
 
Changed:
<
<
     - Poderia sim, mas para que? Os comandos estão aí para serem usados... O exemplo dado foi didático, mas imagine um programa que aceitasse muitas opções e seus parâmetros poderiam ou não estar colados às opções, suas opções também poderiam ou não estar coladas, ia ser um case infernal e com getopts é só seguir os passos acima.
>
>
     - Could do, but for what? The commands are there to be used ... The example given was didactic, but imagine a program that accepts many options and their parameters could or could not be attached to options, your options could also be united or not, would be a case infernal and with getopts just follow the steps above
 
Changed:
<
<
     - É... Vendo desta forma acho que você tem razão. É porque eu já estou meio cansado com tanta informação nova na minha cabeça. Vamos tomar a saideira ou você ainda quer explicar alguma particularidade do Shell?
>
>
     - It is... Seeing this way I think you're right. It's because I'm getting tired with so much new information in my head. Let's have a nightcap or you still want to explain some peculiarity of the Shell?
 
Changed:
<
<
     - Nem um nem outro, eu também já cansei mas hoje não vou tomar a saideira porque estou indo dar aula na UniRIO, que é a primeira universidade federal que está preparando no uso de Software Livre, seus alunos do curso de graduação em informática.
>
>
     - Neither of them, I have also tired but today I will not have a nightcap because I'm going to teach in UNIRIO, which was the first federal university that is preparing the use of Free Software, your students of the degree course in computer.
 
Changed:
<
<
Mas antes vou te deixar um problema para te encucar: quando você varia o tamanho de uma tela, no seu centro não aparece dinamicamente em vídeo reverso a quantidade de linhas e colunas? Então! Eu quero que você reproduza isso usando a linguagem Shell.
>
>
But before I'll let you think of a problem for you: when you vary the size of a screen, at its center not dynamically appear in reverse video the amount of rows and columns? So! I want you to play it using the Shell language.
 
Changed:
<
<
     - Chico, traz rapidinho a minha conta! Vou contar até um e se você não trouxer eu me mando!
>
>
     - Waiter, quickly brings my account! I'll count to one and if you do not bring I'm leaving!
 
Deleted:
<
<
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.

-- JulioNeves - 18 Mar 2014

 \ No newline at end of file
Added:
>
>
Any doubt or lack of companionship for a beer or even to speak ill of politicians just send an email to of me.

Revision 616 Apr 2014 - Main.AngelaFerreira

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

Pub Talk Part X

Line: 284 to 284
  trap "rm -f /tmp/$$ ; exit" 0 1 2 3 15
Changed:
<
<
Desta forma, caso houvesse uma interrupção brusca (sinais 1, 2, 3 ou 15) antes do programa encerrar (no exit dentro do comando trap), ou um fim normal (sinal 0), o arquivo /tmp/$$ seria removido.
>
>
This way, if there was a sudden interruption (signs 1, 2, 3 or 15) before the program terminate (in exit within the command trap), or a normal end (signal 0), the file /tmp/$$ would be removed.
 
Changed:
<
<
Caso na linha de comandos do trap não houvesse a instrução exit, ao final da execução desta linha o fluxo do programa retornaria ao ponto em que estava quando recebeu o sinal que originou a execução deste trap.
>
>
If the command line trap there was no instruction exit, the end of execution of this line the program flow would return to the point where you were when you received the signal that caused the execution of this trap.
 
Changed:
<
<
Este trap poderia ser subdividido, ficando da seguinte forma:
>
>
This trap could be subdivided, being as follows:
 
    trap "rm -f /tmp/$$" 0
    trap "exit" 1 2 3 15
Changed:
<
<
Assim ao receber um dos sinais o programa terminaria, e ao terminar, geraria um sinal 0, que removeria o arquivo. Caso seu fim seja normal, o sinal também será gerado e o rm será executado.
>
>
Thus when get one of the signs the program would end, and when finished, would generate a signal 0, which would remove the file. If your end is normal, the signal will also be generated and rm runs.
 
Changed:
<
<
Note também que o Shell pesquisa a linha de comandos uma vez quanto o trap é interpretado (e é por isso que é usual colocá-lo no início do programa) e novamente quando um dos sinais listados é recebido. Então, no último exemplo, o valor de $$ será substituído no momento que o comando trap foi lido da primeira vez, já que as aspas (") não protegem o cifrão ($) da interpretação do Shell.
>
>
Note also that the Shell search the command line once while the trap is interpreted (and that is why it is usual to put it at the beginning of the program) and again when one of the signals listed is received. So in the last example, the value of $$ will be replaced at the time the command = trap = was read the first time, since the quotes (") do not protect the dollar sign ($) the interpretation of Shell.
 
Changed:
<
<
Se você desejasse que a substituição fosse realizada somente quando recebesse o sinal, o comando deveria ser colocado entre apóstrofos ('). Assim, na primeira interpretação do trap, o Shell não veria o cifrão ($), porém os apóstrofos (') seriam removidos e finalmente o Shell poderia substituir o valor da variável. Neste caso, a linha ficaria da seguinte maneira:
>
>
If you wish that replacement was performed only when the received signal, the command should be enclosed in apostrophes ('). Thus, the first interpretation of trap the Shell would not see the dollar sign ($), but the apostrophes (') would be removed and finally the Shell could replace the variable value. In this case, the row would be as follows:
 
    trap 'rm -f /tmp/$$ ; exit' 0 1 2 3 15
Changed:
<
<
Suponha dois casos: você tem dois scripts que chamaremos de script1, cuja primeira linha será um trap e script2, sendo este último colocado em execução pelo primeiro, e por serem dois processos, terão dois PID distintos.
>
>
Suppose two cases: you have two scripts that we'll call script1, the first line will be a trap and script2, the latter being placed in the first run, and because they are two processes, will have two distinct PID.
 
  • 1º Caso: O ftp encontra-se em script1
    Neste caso, o argumento do comando trap deveria vir entre aspas (") porque caso ocorresse uma interrupção (<CTRL+C> ou <CTRL+\>) no script2, a linha só seria interpretada neste momento e o PID do script2 seria diferente do encontrado em /tmp/$$ (não esqueça que $$ é a variável que contém o PID do processo ativo);

Revision 521 Mar 2014 - Main.AngelaFerreira

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

Pub Talk Part X

Line: 213 to 213
 
Changed:
<
<

Sinais de Processos

>
>

Signs Processes

 
Changed:
<
<
Existe no Linux uma coisa chamada sinal (signal). Existem diversos sinais que podem ser mandados para (ou gerados por) processos em execução. Vamos de agora em diante dar uma olhadinha nos sinais mandados para os processos e mais à frente vamos dar uma passada rápida pelos sinais gerados por processos.
>
>
Exists in Linux something called signal (signal). There are many signals that can be sent to (or generated by) running processes. We will from now on take a peek on the signals sent to the process and later we will take a quick glance at the signals generated by processes.
 
Changed:
<
<

Sinais assassinos

>
>

Signs killers

 
Changed:
<
<
Para mandar um sinal a um processo, usamos normalmente o comando kill, cuja sintaxe é:
>
>
To send a signal to a process, we normally use kill command, whose syntax is:
 
    kill -sig PID
Changed:
<
<
Onde PID é o identificador do processo (Process IDentification ou Process ID). Além do comando kill, algumas seqüências de teclas também podem gerar sig. A tabela a seguir mostra os sinais mais importantes para monitorarmos:
>
>
Where PID is the process identifier (Process IDentification or Process ID). Besides the kill command, some key sequences can also generate sig. The following table shows the most important signs to monitor:
 
Changed:
<
<
Sinais Mais Importantes
 15   SIGTERM  Quando recebe um kill ou kill -TERM 
Sinal  Gerado por:
0 EXIT  Fim normal do programa
1 SIGHUP  Quando recebe um kill -HUP
2 SIGINT  Interrupção pelo teclado (<CTRL+C>)
3 SIGQUIT  Interrupção pelo teclado (<CTRL+\>)
>
>
Most Important Signs
 15   SIGTERM  When it receives a kill or kill -TERM 
Sinal  Generated by:
0 EXIT  Normal end of program
1 SIGHUP  When it receives a kill -HUP
2 SIGINT  The keyboard interrupt (<CTRL+C>)
3 SIGQUIT  Keyboard interrupt (<CTRL+\>)
 
Changed:
<
<
Além destes sinais, existe o famigerado -9 ou SIGKILL que, para o processo que o está recebendo, equivale a meter o dedo no botão de desliga do computador o que seria altamente indesejável já que muitos programas necessitam "limpar o meio de campo" ao seu término. Se o seu final ocorrer de forma prevista, ou seja se tiver um término normal, é muito fácil de fazer esta limpeza, porém se o seu programa tiver um fim brusco muita coisa pode ocorrer:
>
>
Besides these signs, there is the notorious -9 or SIGKILL that for the process that is receiving, equates to put my finger on the off computer button which would be highly undesirable since many programs require "clear the midfield" at its end. If your ultimate occur as intended, in other words if you have a normal termination, it is very easy to do this cleaning, but if your program has an abrupt end a lot can occur:
 
Changed:
<
<
  • É possível que em um determinado espaço de tempo, o seu computador esteja cheio de arquivos de trabalho inúteis
  • Seu processador poderá ficar atolado de processos zombies e defuncts gerados por processos filhos que perderam os pais;
  • É necessário liberar sockets abertos para não deixar os clientes congelados;
  • Seus bancos de dados poderão ficar corrompidos porque sistemas gerenciadores de bancos de dados necessitam de um tempo para gravar seus buffers em disco (commit).
>
>
  • It is possible that in a certain room of time, your computer is full of useless files work;
  • Your processor may jam the zombies and defuncts processes generated from processes children who lost their parents;
  • You must release opened sockets to not allow the frozen clients;
  • Your database may be corrupted because management systems databases require a time to record your buffers disk (commit).
 
Changed:
<
<
Enfim, existem mil razões para não usar um kill com o sinal -9 e para monitorar fins anormais de programas.
>
>
Anyway, there are a thousand reasons not to use a kill to the sign -9 and monitor abnormal purposes programs.
 
Changed:
<
<

O trap não atrapalha

>
>

The trap doesn't hurt

 
Changed:
<
<
Para fazer a monitoração descrita acima existe o comando trap cuja sintaxe é:
>
>
To make the monitoring described above exists trap command whose syntax is:
 
    trap "cmd1; cmd2; cmdn" S1 S2 ... SN
Changed:
<
<
ou
>
>
or
 
    trap 'cmd1; cmd2; cmdn' S1 S2 ... SN
Changed:
<
<
Onde os comandos cmd1, cmd2, cmdn serão executados caso o programa receba os sinais S1 S2 ... SN.
>
>
Where commands cmd1, cmd2, cmdn will be executed if the program receives the signals S1 S2 ... SN.
 
Changed:
<
<
As aspas (") ou os apóstrofos (') só são necessários caso o trap possua mais de um comando cmd associado. Cada um dos cmd pode ser também uma função interna, uma externa ou outro script.
>
>
The quotation marks (") or apostrophes (') are only needed if trap have more cmd command associated. Each cmd can also be a an internal function, a external or other script.
 
Changed:
<
<
Para entender o uso de aspas (") e apóstrofos (') vamos recorrer a um exemplo que trata um fragmento de um script que faz um ftp para uma máquina remota ($RemoComp), na qual o usuário é $Fulano, sua senha é $Segredo e vai transmitir o arquivo contido em $Arq. Suponha ainda que estas quatro variáveis foram recebidas em uma rotina anterior de leitura e que este script é muito usado por diversas pessoas da instalação. Vejamos este trecho de código:
>
>
To understand the use of quotation marks (") and apostrophes (') we will use an example that is a fragment of a script that makes a ftp for a remote machine ($RemoComp), in which the user is $Guy, your password is $Secret and will transmit the file contained in $Arq. Suppose further that these four variables were received in a previous reading routine and that this script is widely used by many people to installation. Consider this bit of code:
 
ftp -ivn $RemoComp << FimFTP >> /tmp/$$ 2>> /tmp/$$
Changed:
<
<
user $Fulano $Segredo
>
>
user $Guy $Secret
  binary get $Arq FimFTP?
Changed:
<
<
Repare que, tanto as saídas do dos diálogos do ftp, como os erros encontrados, estão sendo redirecionados para /tmp/$$, o que é uma construção bastante normal para arquivos temporários usados em scripts com mais de um usuário, porque $$ é a variável que contém o número do processo (PID), que é único, e com este tipo de construção evita-se que dois ou mais usuários disputem a posse e os direitos sobre o arquivo.
>
>
Note that the outputs of the dialogs ftp, as the errors found are being redirected to /tmp/$$, which is a fairly standard construction for temporary files used in scripts with more than one user, because $$ is the variable that contains the process number (PID), which is unique, and this type of construction is avoided that two or more users compete ownership and rights to the file.
 
Changed:
<
<
Caso este ftp seja interrompido por um kill ou um <CTRL+C>, certamente deixará lixo no disco. É exatamente esta a forma como mais se usa o comando trap. Como isto é trecho de um script, devemos, logo no seu início, como um de seus primeiros comandos, fazer:
>
>
If this ftp is interrupted by a kill or <CTRL+C>, certainly leave debris. This is precisely the way in which more you use the command trap. How is this excerpt from a script, we should, at the very beginning, as one of his first command, do:
 
    trap "rm -f /tmp/$$ ; exit" 0 1 2 3 15

Revision 420 Mar 2014 - Main.AngelaFerreira

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

Pub Talk Part X

Line: 78 to 78
 
  • Resolves and replaces the metacharacters;
  • Pass the already scrutinized every line for execution.
Changed:
<
<
Desta forma, quando chegou na fase de resolução de variáveis, que como eu disse é anterior à execução, a única variável existente era $var2 e por isso a tua solução produziu como saída $var1. O comando echo identificou isso como uma cadeia e não como uma variável.
>
>
Thus, when we arrived in the resolution phase of variables, which is as I said before the execution, the only variable existing was $var2 and therefore your solution produced as output $var1. The command echo identified it like a chain and not a variable.
 
Changed:
<
<
Problemas deste tipo são relativamente freqüentes e seriam insolúveis caso não existisse a instrução eval, cuja sintaxe é:
>
>
Problems of this type are relatively frequent and would be insoluble if not exist the instruction eval, whose syntax is:
 
    eval cmd
Changed:
<
<
Onde cmd é uma linha de comando qualquer que você poderia inclusive executar direto no prompt do terminal. Quando você põe o eval na frente, no entanto, o que ocorre é que o Shell trata cmd como se seus dados fossem parâmetros do eval e em seguida o eval executa a linha recebida, submetendo-a ao Shell, dando então na prática duas passadas em cmd.
>
>
Where cmd is a command line any that you could even run direct at a terminal prompt. When you put the eval ahead, however, what happens is that Shell works the cmd as if their data were parameters of eval and then the eval executes the received line, submitting to the Shell, then giving in practice two passes in cmd.
 
Changed:
<
<
Desta forma se executássemos o comando que você propôs colocando o eval à sua frente, teríamos a saída esperada, veja:
>
>
This way if we ran the command you suggested putting the eval ahead, we would have expected output, see:
 
$ eval echo $`echo $var2` 3
Changed:
<
<
Este exemplo também poderia ter sido feito da seguinte maneira:
>
>
This example could also have been done as follows:
 
$ eval echo \$$var2 3
Changed:
<
<
Na primeira passada a contrabarra (\) seria retirada e $var2 seria resolvido produzindo var1, para a segunda passada teria sobrado echo $var1, que produziria o resultado esperado.
>
>
In the first pass the backslash (\) would be removed and $var2 would be solved producing var1, for the second pass left would echo $var1, which would produce the expected result.
 
Changed:
<
<
Agora vou colocar um comando dentro de var2:
>
>
Now I put a command within of var2:
 
$ var2=ls
Changed:
<
<
Vou executar:
>
>
I'll run:
 
$ $var2
Changed:
<
<
10porpag1.sh alo2.sh listamusica logaute.sh 10porpag2.sh confuso listartista mandamsg.func 10porpag3.sh contpal.sh listartista3 monbg.sh alo1.sh incusu logado
>
>
10porpag1.sh alo2.sh listmusic logaute.sh 10porpag2.sh confuso listartist sendmsg.func 10porpag3.sh contpal.sh listartist3 monbg.sh alo1.sh incusu logged
 
Changed:
<
<
Agora vamos colocar em var2 o seguinte: ls $var1; e em var1 vamos colocar l*, vejamos:
>
>
Now we put in var2 the following: ls$var1, and var1 we put l*, see:
 
$ var2='ls $var1'
Line: 128 to 128
 $ $var2 ls: $var1: No such file or directory $ eval $var2
Changed:
<
<
listamusica listartista listartista3 logado logaute.sh
>
>
listmusic listartist listartist3 logged logaute.sh
 
Changed:
<
<
Novamente, no tempo de substituição das variáveis, $var1 ainda não havia se apresentado ao Shell para ser resolvida, desta forma só nos resta executar o comando eval para dar as duas passadas necessárias.
>
>
Again, at the time of replacement of variables, $var1 was not yet presented to the Shell to be resolved, in this way we can only run the command eval to give the two passed required.
 
Changed:
<
<
Uma vez um colega de uma excelente lista sobre Shell Script, colocou uma dúvida: queria fazer um menu que numerasse e listasse todos os arquivos com extensão .sh e quando o operador escolhesse uma opção, o programa correspondente seria executado. A minha proposta foi a seguinte:
>
>
Once a colleague of a excellent list on Shell Script, put a question: I wanted to make a menu that had numbered and list all files with extension .sh and when the operator chooses an option, the corresponding program would run. My proposal is as follows:
 
Changed:
<
<
$ cat fazmenu
>
>
$ cat domenu
 #!/bin/bash #
Changed:
<
<
# Lista numerando os programas com extensão .sh no # diretório corrente e executa o escolhido pelo operador
>
>
# List numbering programs with .sh in # current directory and executes the operator chooses
 # clear; i=1
Changed:
<
<
printf "%11s\t%s\n\n" Opção Programa
>
>
printf "%11s\t%s\n\n" Option Program
 CASE='case $opt in' for arq in *.sh do
Line: 155 to 156
 CASE="$CASE *) . erro;; esac"
Changed:
<
<
read -n3 -p "Informe a opção desejada: " opt
>
>
read -n3 -p "Inform the desired option: " opt
 echo eval "$CASE"
Changed:
<
<
Parece complicado porque usei muito printf para formatação da tela, mas é bastante simples, vamos entendê-lo: o primeiro printf foi colocado para fazer o cabeçalho e logo em seguida comecei a montar dinamicamente a variável $CASE, na qual ao final será feito um eval para execução do programa escolhido. Repare no entanto que dentro do loop do for existem dois printf: o primeiro serve para formatar a tela e o segundo para montar o case (se antes do comando read você colocar uma linha echo "$CASE", verá que o comando case montado dentro da variável está todo indentado. Frescura, né? :). Na saída do for, foi adicionada uma linha à variável $CASE, para no caso de se fazer uma opção inválida, ser executada uma função externa para dar mensagens de erro.
>
>
It looks complicated because I used much printf formatting for the screen, but it is very simple, we understand it: the first printf was placed to the header and then immediately I started dynamically assemble the variable $CASE, in which the end will be an eval to run the selected program. Note however that within the loop of the for there are two printf: the first is used to format the screen and the second to mount the case (before the read command if you put a row echo "$CASE", you'll see that the case command mounted inside the variable is all indented. Freshness, right? :). In for output, a row was added to the variable $CASE, for the case of making an invalid option, run an external function to give error messages.
 
Changed:
<
<
Vamos executá-lo para ver a saída gerada:
>
>
Let's run it to see the output generated:
 
Changed:
<
<
$ fazmenu.sh Opcao Programa
>
>
$ domenu.sh Option Program
  001 10porpag1.sh 002 10porpag2.sh
Line: 174 to 175
  004 alo1.sh 005 alo2.sh 006 contpal.sh
Changed:
<
<
007 fazmenu.sh
>
>
007 domenu.sh
  008 logaute.sh 009 monbg.sh 010 readpipe.sh 011 redirread.sh
Changed:
<
<
Informe a opção desejada:
>
>
Inform the desired option:
 
Changed:
<
<
Neste programa seria interessante darmos uma opção de término, e para isso seria necessário a inclusão de uma linha após o loop de montagem da tela e alterarmos a linha na qual fazemos a atribuição final do valor da variável $CASE. Vejamos como ele ficaria:
>
>
In this program would be interesting to give an option of termination, and this would require the inclusion of a line after loop of mounting the screen and alter the row in which we make final attribution of the variable value $CASE. Let's see how it would look:
 
Changed:
<
<
$ cat fazmenu
>
>
$ cat domenu
 #!/bin/bash #
Changed:
<
<
# Lista numerando os programas com extensão .sh no # diretório corrente e executa o escolhido pelo operador
>
>
# List numbering programs with .sh in # current directory and executes the operator chooses
 # clear; i=1
Changed:
<
<
printf "%11s\t%s\n\n" Opção Programa
>
>
printf "%11s\t%s\n\n" Option Program
 CASE='case $opt in' for arq in *.sh do
Line: 201 to 202
  "$(printf "%03d)\t %s;;" $i $arq) i=$((i+1)) done
Changed:
<
<
printf "\t%d\t%s\n\n" 999 "Fim do programa" # Linha incluida
>
>
printf "\t%d\t%s\n\n" 999 "End of program" # Row included
 CASE="$CASE
Changed:
<
<
999) exit;; # Linha alterada *) ./erro;;
>
>
999) exit;; # Row changed *) ./error;;
 esac"
Changed:
<
<
read -n3 -p "Informe a opção desejada: " opt
>
>
read -n3 -p "Inform the desired option: " opt
 echo eval "$CASE"

Revision 320 Mar 2014 - Main.AngelaFerreira

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

Pub Talk Part X

Line: 21 to 21
      - Well, beyond what you asked, I noticed that the program that called the function, would have previously defined the row that would be given the message and the number of columns. What I did was add two rows - in which employed parameter substitution - that if one of these variables were not informed, assign the function itself. The message row would be three rows above the end of the screen and the total of columns would be obtained by tput cols command. See how it fits:

Changed:
<
<
$ cat pergunta.func # A funcao recebe 3 parametros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)" TotCols=${TotCols:-$(tput cols)} # Se nao estava definido, agora esta LinhaMesg=${LinhaMesg:-$(($(tput lines)-3))} # Idem
>
>
$ cat question.func # The function receives 3 parameters in the following order: # $1 - Message to be given on the screen # $2 - Value to be accepted with default response # $3 - The other accepted value # Supposing that $1=Accept?, $2=y e $3=n, the row # put down in Message the value "Accept? (Y/n)" TotCols=${TotCols:-$(tput cols)} # If it was not defined, now it is LineMesg=${LineMesg:-$(($(tput lines)-3))} # Idem
 Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" TamMsg=${#Msg}
Changed:
<
<
Col=$(((TotCols - TamMsg) / 2)) # Para centrar Msg na linha tput cup $LinhaMesg $Col
>
>
Col=$(((TotCols - TamMsg) / 2)) # To centralize Msg on row tput cup $LineMesg $Col
 read -n1 -p "$Msg " SN
Changed:
<
<
SN=${SN:-$2} # Se vazia coloca default em SN SN=$(echo $SN | tr A-Z a-z) # A saida de SN serah em minuscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela
>
>
SN=${SN:-$2} # If empty puts default on SN SN=$(echo $SN | tr A-Z a-z) # The output of SN will be in lowercase tput cup $LineMesg $Col; tput el # Deletes the message screen
 
Changed:
<
<
     - Gostei, você já se antecipou ao que eu ia pedir. Só pra gente encerrar este papo de substituição de parâmetros, repare que a legibilidade está horrorível, mas a performance, isto é, velocidade de execução, está ótima. Como funções são coisas muito pessoais, já que cada um usa as suas, e quase não dão manutenção, eu sempre opto pela performance.
>
>
     - I liked, you already anticipated what I was going to ask. Just for we end this talk of substitution of parameters, note that the readability is awful, but the performance, this is, execution speed, is good. How functions are very personal things, as each uses their, and hardly give maintenance, I always opt for the performance.
 
Changed:
<
<
     - Hoje vamos sair daquela chatura que foi o nosso último papo e vamos voltar à lógica saindo da decoreba, mas volto a te lembrar, tudo que eu te mostrei da outra vez aqui no Boteco do Chico é válido e quebra um galhão, guarde aqueles guardanapos que rabiscamos que, mais cedo ou mais tarde, vão te ser muito úteis.
>
>
     - Today we get out of that boredom that was our last talk and we will return to logic out of memorization, but I will remind you, all that I showed you last time here in the Pub is valid and helps, save those napkins we scribble that sooner or later, because will be very useful for you.
 
Changed:
<
<

O comando eval

>
>

The eval command

 
Changed:
<
<
     - Vou te dar um problema que eu duvido que você resolva:
>
>
     - I'll give you a problem that I doubt you solve:
 
$ var1=3 $ var2=var1
Changed:
<
<
     - Te dei estas duas variáveis, e quero que você me diga como eu posso, só me referindo a $var2, listar o valor de $var1 (3).
>
>
     - I gave you these two variables, and want you to tell me how I can, only referring to $var2, list the value of $var1 (3).
 
Changed:
<
<
     - A isso é mole, é só fazer:
>
>
     - This is so easy, just do:
 
    echo $`echo $var2`
Changed:
<
<
     - Repare que eu coloquei o echo $var2 entre crases (`), que desta forma terá prioridade de execução e resultará em var1, montando echo$var1 que produzirá 3...
>
>
     - Notice that I put the echo $var2 between backticks (`), which thus has priority in execution and result var1, mounting echo$var1 will produce 3 ...
 
Changed:
<
<
     - A é? Então execute para ver se está correto.
>
>
     - Will be? Then run to see if it is correct.
 
$ echo $`echo $var2` $var1
Changed:
<
<
     - Ué! Que foi que houve? O meu raciocínio me parecia bastante lógico...
>
>
     - Huh! What happened? My reasoning seemed logical enough...
 
Changed:
<
<
     - O seu raciocínio realmente foi lógico, o problema é que você esqueceu de uma das primeiras coisas que te falei aqui no Boteco e vou repetir. O Shell usa a seguinte ordem para resolver uma linha de comandos:
  • Resolve os redirecionamentos;
  • Substitui as variáveis pelos seus valores;
  • Resolve e substitui os meta caracteres;
  • Passa a linha já toda esmiuçada para execução.
>
>
     - Your reasoning was logical really, the problem is that you forgot one of the first things I told you in this pub and I will repeat. The Shell uses the following order to solve a command line:
  • Resolve redirects;
  • Replaces the variables by their values;
  • Resolves and replaces the metacharacters;
  • Pass the already scrutinized every line for execution.
  Desta forma, quando chegou na fase de resolução de variáveis, que como eu disse é anterior à execução, a única variável existente era $var2 e por isso a tua solução produziu como saída $var1. O comando echo identificou isso como uma cadeia e não como uma variável.

Revision 218 Mar 2014 - Main.AngelaFerreira

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

Pub Talk Part X

Line: 8 to 8
  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:
<
<
     - E aê amigo, te dei a maior moleza, né? Um exerciciozinho muito simples...
>
>
     - Hey friend, I gave you a lot of easy, right? A simple exercise ...
 
Changed:
<
<
     - É mais nos testes que eu fiz, e de acordo com o que você ensinou sobre substituição de parâmetros, achei que deveria fazer outras alterações nas funções que desenvolvemos para torná-las de uso geral como você me disse que todas as funções deveriam ser, quer ver?
>
>
     - But the tests I did and in accordance with what you taught about parameter substitution, I thought I should make other changes in the functions developed to make them for general use, as you told me that all functions should be, would you like to see?
 
Changed:
<
<
     - Claro né mané, se te pedi para fazer é porque estou afim de te ver aprender, mas peraí, dá um tempo!
>
>
     - Of course! If I asked you to do is because I'm so to see you learn, but wait, gimme a break!
 
Changed:
<
<
     - Chico! Manda dois, um sem colarinho!
>
>
     - Waiter! Sends two, one without foam!
 
Changed:
<
<
     - Vai, mostra aí o que você fez.
>
>
     - Now show me what you did.
 
Changed:
<
<
     - Bem, além do que você pediu, eu reparei que o programa que chamava a função, teria de ter previamente definidas a linha em que seria dada a mensagem e a quantidade de colunas. O que fiz foi incluir duas linhas - nas quais empreguei substituição de parâmetros - que caso uma destas variáveis não fosse informada, a própria função atribuiria. A linha de mensagem seria três linhas acima do fim da tela e o total de colunas seria obtido pelo comando tput cols. Veja como ficou:
>
>
     - Well, beyond what you asked, I noticed that the program that called the function, would have previously defined the row that would be given the message and the number of columns. What I did was add two rows - in which employed parameter substitution - that if one of these variables were not informed, assign the function itself. The message row would be three rows above the end of the screen and the total of columns would be obtained by tput cols command. See how it fits:
 
$ cat pergunta.func

Revision 118 Mar 2014 - JulioNeves

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

Pub Talk Part X



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.

     - E aê amigo, te dei a maior moleza, né? Um exerciciozinho muito simples...

     - É mais nos testes que eu fiz, e de acordo com o que você ensinou sobre substituição de parâmetros, achei que deveria fazer outras alterações nas funções que desenvolvemos para torná-las de uso geral como você me disse que todas as funções deveriam ser, quer ver?

     - Claro né mané, se te pedi para fazer é porque estou afim de te ver aprender, mas peraí, dá um tempo!

     - Chico! Manda dois, um sem colarinho!

     - Vai, mostra aí o que você fez.

     - Bem, além do que você pediu, eu reparei que o programa que chamava a função, teria de ter previamente definidas a linha em que seria dada a mensagem e a quantidade de colunas. O que fiz foi incluir duas linhas - nas quais empreguei substituição de parâmetros - que caso uma destas variáveis não fosse informada, a própria função atribuiria. A linha de mensagem seria três linhas acima do fim da tela e o total de colunas seria obtido pelo comando tput cols. Veja como ficou:

$ cat pergunta.func # A funcao recebe 3 parametros na seguinte ordem: # $1 - Mensagem a ser dada na tela # $2 - Valor a ser aceito com resposta default # $3 - O outro valor aceito # Supondo que $1=Aceita?, $2=s e $3=n, a linha # abaixo colocaria em Msg o valor "Aceita? (S/n)" TotCols=${TotCols:-$(tput cols)} # Se nao estava definido, agora esta LinhaMesg=${LinhaMesg:-$(($(tput lines)-3))} # Idem Msg="$1 (`echo $2 | tr a-z A-Z`/`echo $3 | tr A-Z a-z`)" TamMsg=${#Msg} Col=$(((TotCols - TamMsg) / 2)) # Para centrar Msg na linha tput cup $LinhaMesg $Col read -n1 -p "$Msg " SN SN=${SN:-$2} # Se vazia coloca default em SN SN=$(echo $SN | tr A-Z a-z) # A saida de SN serah em minuscula tput cup $LinhaMesg $Col; tput el # Apaga msg da tela

     - Gostei, você já se antecipou ao que eu ia pedir. Só pra gente encerrar este papo de substituição de parâmetros, repare que a legibilidade está horrorível, mas a performance, isto é, velocidade de execução, está ótima. Como funções são coisas muito pessoais, já que cada um usa as suas, e quase não dão manutenção, eu sempre opto pela performance.

     - Hoje vamos sair daquela chatura que foi o nosso último papo e vamos voltar à lógica saindo da decoreba, mas volto a te lembrar, tudo que eu te mostrei da outra vez aqui no Boteco do Chico é válido e quebra um galhão, guarde aqueles guardanapos que rabiscamos que, mais cedo ou mais tarde, vão te ser muito úteis.

O comando eval

     - Vou te dar um problema que eu duvido que você resolva:

$ var1=3 $ var2=var1

     - Te dei estas duas variáveis, e quero que você me diga como eu posso, só me referindo a $var2, listar o valor de $var1 (3).

     - A isso é mole, é só fazer:

    echo $`echo $var2`

     - Repare que eu coloquei o echo $var2 entre crases (`), que desta forma terá prioridade de execução e resultará em var1, montando echo$var1 que produzirá 3...

     - A é? Então execute para ver se está correto.

$ echo $`echo $var2` $var1

     - Ué! Que foi que houve? O meu raciocínio me parecia bastante lógico...

     - O seu raciocínio realmente foi lógico, o problema é que você esqueceu de uma das primeiras coisas que te falei aqui no Boteco e vou repetir. O Shell usa a seguinte ordem para resolver uma linha de comandos:

  • Resolve os redirecionamentos;
  • Substitui as variáveis pelos seus valores;
  • Resolve e substitui os meta caracteres;
  • Passa a linha já toda esmiuçada para execução.

Desta forma, quando chegou na fase de resolução de variáveis, que como eu disse é anterior à execução, a única variável existente era $var2 e por isso a tua solução produziu como saída $var1. O comando echo identificou isso como uma cadeia e não como uma variável.

Problemas deste tipo são relativamente freqüentes e seriam insolúveis caso não existisse a instrução eval, cuja sintaxe é:

    eval cmd

Onde cmd é uma linha de comando qualquer que você poderia inclusive executar direto no prompt do terminal. Quando você põe o eval na frente, no entanto, o que ocorre é que o Shell trata cmd como se seus dados fossem parâmetros do eval e em seguida o eval executa a linha recebida, submetendo-a ao Shell, dando então na prática duas passadas em cmd.

Desta forma se executássemos o comando que você propôs colocando o eval à sua frente, teríamos a saída esperada, veja:

$ eval echo $`echo $var2` 3

Este exemplo também poderia ter sido feito da seguinte maneira:

$ eval echo \$$var2 3

Na primeira passada a contrabarra (\) seria retirada e $var2 seria resolvido produzindo var1, para a segunda passada teria sobrado echo $var1, que produziria o resultado esperado.

Agora vou colocar um comando dentro de var2:

$ var2=ls

Vou executar:

$ $var2 10porpag1.sh alo2.sh listamusica logaute.sh 10porpag2.sh confuso listartista mandamsg.func 10porpag3.sh contpal.sh listartista3 monbg.sh alo1.sh incusu logado

Agora vamos colocar em var2 o seguinte: ls $var1; e em var1 vamos colocar l*, vejamos:

$ var2='ls $var1' $ var1='l*' $ $var2 ls: $var1: No such file or directory $ eval $var2 listamusica listartista listartista3 logado logaute.sh

Novamente, no tempo de substituição das variáveis, $var1 ainda não havia se apresentado ao Shell para ser resolvida, desta forma só nos resta executar o comando eval para dar as duas passadas necessárias.

Uma vez um colega de uma excelente lista sobre Shell Script, colocou uma dúvida: queria fazer um menu que numerasse e listasse todos os arquivos com extensão .sh e quando o operador escolhesse uma opção, o programa correspondente seria executado. A minha proposta foi a seguinte:

$ cat fazmenu #!/bin/bash # # Lista numerando os programas com extensão .sh no # diretório corrente e executa o escolhido pelo operador # clear; i=1 printf "%11s\t%s\n\n" Opção Programa CASE='case $opt in' for arq in *.sh do printf "\t%03d\t%s\n" $i $arq CASE="$CASE "$(printf "%03d)\t %s;;" $i $arq) i=$((i+1)) done CASE="$CASE *) . erro;; esac" read -n3 -p "Informe a opção desejada: " opt echo eval "$CASE"

Parece complicado porque usei muito printf para formatação da tela, mas é bastante simples, vamos entendê-lo: o primeiro printf foi colocado para fazer o cabeçalho e logo em seguida comecei a montar dinamicamente a variável $CASE, na qual ao final será feito um eval para execução do programa escolhido. Repare no entanto que dentro do loop do for existem dois printf: o primeiro serve para formatar a tela e o segundo para montar o case (se antes do comando read você colocar uma linha echo "$CASE", verá que o comando case montado dentro da variável está todo indentado. Frescura, né? :). Na saída do for, foi adicionada uma linha à variável $CASE, para no caso de se fazer uma opção inválida, ser executada uma função externa para dar mensagens de erro.

Vamos executá-lo para ver a saída gerada:

$ fazmenu.sh Opcao Programa

001 10porpag1.sh 002 10porpag2.sh 003 10porpag3.sh 004 alo1.sh 005 alo2.sh 006 contpal.sh 007 fazmenu.sh 008 logaute.sh 009 monbg.sh 010 readpipe.sh 011 redirread.sh Informe a opção desejada:

Neste programa seria interessante darmos uma opção de término, e para isso seria necessário a inclusão de uma linha após o loop de montagem da tela e alterarmos a linha na qual fazemos a atribuição final do valor da variável $CASE. Vejamos como ele ficaria:

$ cat fazmenu #!/bin/bash # # Lista numerando os programas com extensão .sh no # diretório corrente e executa o escolhido pelo operador # clear; i=1 printf "%11s\t%s\n\n" Opção Programa CASE='case $opt in' for arq in *.sh do printf "\t%03d\t%s\n" $i $arq CASE="$CASE "$(printf "%03d)\t %s;;" $i $arq) i=$((i+1)) done printf "\t%d\t%s\n\n" 999 "Fim do programa" # Linha incluida CASE="$CASE 999) exit;; # Linha alterada *) ./erro;; esac" read -n3 -p "Informe a opção desejada: " opt echo eval "$CASE"

Sinais de Processos

Existe no Linux uma coisa chamada sinal (signal). Existem diversos sinais que podem ser mandados para (ou gerados por) processos em execução. Vamos de agora em diante dar uma olhadinha nos sinais mandados para os processos e mais à frente vamos dar uma passada rápida pelos sinais gerados por processos.

Sinais assassinos

Para mandar um sinal a um processo, usamos normalmente o comando kill, cuja sintaxe é:

    kill -sig PID

Onde PID é o identificador do processo (Process IDentification ou Process ID). Além do comando kill, algumas seqüências de teclas também podem gerar sig. A tabela a seguir mostra os sinais mais importantes para monitorarmos:

Sinais Mais Importantes
 15   SIGTERM  Quando recebe um kill ou kill -TERM 
Sinal  Gerado por:
0 EXIT  Fim normal do programa
1 SIGHUP  Quando recebe um kill -HUP
2 SIGINT  Interrupção pelo teclado (<CTRL+C>)
3 SIGQUIT  Interrupção pelo teclado (<CTRL+\>)

Além destes sinais, existe o famigerado -9 ou SIGKILL que, para o processo que o está recebendo, equivale a meter o dedo no botão de desliga do computador o que seria altamente indesejável já que muitos programas necessitam "limpar o meio de campo" ao seu término. Se o seu final ocorrer de forma prevista, ou seja se tiver um término normal, é muito fácil de fazer esta limpeza, porém se o seu programa tiver um fim brusco muita coisa pode ocorrer:

  • É possível que em um determinado espaço de tempo, o seu computador esteja cheio de arquivos de trabalho inúteis
  • Seu processador poderá ficar atolado de processos zombies e defuncts gerados por processos filhos que perderam os pais;
  • É necessário liberar sockets abertos para não deixar os clientes congelados;
  • Seus bancos de dados poderão ficar corrompidos porque sistemas gerenciadores de bancos de dados necessitam de um tempo para gravar seus buffers em disco (commit).

Enfim, existem mil razões para não usar um kill com o sinal -9 e para monitorar fins anormais de programas.

O trap não atrapalha

Para fazer a monitoração descrita acima existe o comando trap cuja sintaxe é:

    trap "cmd1; cmd2; cmdn" S1 S2 ... SN

ou

    trap 'cmd1; cmd2; cmdn' S1 S2 ... SN

Onde os comandos cmd1, cmd2, cmdn serão executados caso o programa receba os sinais S1 S2 ... SN.

As aspas (") ou os apóstrofos (') só são necessários caso o trap possua mais de um comando cmd associado. Cada um dos cmd pode ser também uma função interna, uma externa ou outro script.

Para entender o uso de aspas (") e apóstrofos (') vamos recorrer a um exemplo que trata um fragmento de um script que faz um ftp para uma máquina remota ($RemoComp), na qual o usuário é $Fulano, sua senha é $Segredo e vai transmitir o arquivo contido em $Arq. Suponha ainda que estas quatro variáveis foram recebidas em uma rotina anterior de leitura e que este script é muito usado por diversas pessoas da instalação. Vejamos este trecho de código:

ftp -ivn $RemoComp << FimFTP >> /tmp/$$ 2>> /tmp/$$
    user $Fulano $Segredo
    binary
    get $Arq
FimFTP

Repare que, tanto as saídas do dos diálogos do ftp, como os erros encontrados, estão sendo redirecionados para /tmp/$$, o que é uma construção bastante normal para arquivos temporários usados em scripts com mais de um usuário, porque $$ é a variável que contém o número do processo (PID), que é único, e com este tipo de construção evita-se que dois ou mais usuários disputem a posse e os direitos sobre o arquivo.

Caso este ftp seja interrompido por um kill ou um <CTRL+C>, certamente deixará lixo no disco. É exatamente esta a forma como mais se usa o comando trap. Como isto é trecho de um script, devemos, logo no seu início, como um de seus primeiros comandos, fazer:

    trap "rm -f /tmp/$$ ; exit" 0 1 2 3 15

Desta forma, caso houvesse uma interrupção brusca (sinais 1, 2, 3 ou 15) antes do programa encerrar (no exit dentro do comando trap), ou um fim normal (sinal 0), o arquivo /tmp/$$ seria removido.

Caso na linha de comandos do trap não houvesse a instrução exit, ao final da execução desta linha o fluxo do programa retornaria ao ponto em que estava quando recebeu o sinal que originou a execução deste trap.

Este trap poderia ser subdividido, ficando da seguinte forma:

    trap "rm -f /tmp/$$" 0
    trap "exit" 1 2 3 15

Assim ao receber um dos sinais o programa terminaria, e ao terminar, geraria um sinal 0, que removeria o arquivo. Caso seu fim seja normal, o sinal também será gerado e o rm será executado.

Note também que o Shell pesquisa a linha de comandos uma vez quanto o trap é interpretado (e é por isso que é usual colocá-lo no início do programa) e novamente quando um dos sinais listados é recebido. Então, no último exemplo, o valor de $$ será substituído no momento que o comando trap foi lido da primeira vez, já que as aspas (") não protegem o cifrão ($) da interpretação do Shell.

Se você desejasse que a substituição fosse realizada somente quando recebesse o sinal, o comando deveria ser colocado entre apóstrofos ('). Assim, na primeira interpretação do trap, o Shell não veria o cifrão ($), porém os apóstrofos (') seriam removidos e finalmente o Shell poderia substituir o valor da variável. Neste caso, a linha ficaria da seguinte maneira:

    trap 'rm -f /tmp/$$ ; exit' 0 1 2 3 15

Suponha dois casos: você tem dois scripts que chamaremos de script1, cuja primeira linha será um trap e script2, sendo este último colocado em execução pelo primeiro, e por serem dois processos, terão dois PID distintos.

  • 1º Caso: O ftp encontra-se em script1
    Neste caso, o argumento do comando trap deveria vir entre aspas (") porque caso ocorresse uma interrupção (<CTRL+C> ou <CTRL+\>) no script2, a linha só seria interpretada neste momento e o PID do script2 seria diferente do encontrado em /tmp/$$ (não esqueça que $$ é a variável que contém o PID do processo ativo);

  • 2º Caso: O ftp acima encontra-se em script2
    Neste caso, o argumento do comando trap deveria estar entre apóstrofos ('), pois caso a interrupção se desse durante a execução de script1, o arquivo não teria sido criado, caso ocorresse durante a execução de script2, o valor de $$ seria o PID deste processo, que coincidiria com o de /tmp/$$.

O comando trap, quando executado sem argumentos, lista os sinais que estão sendo monitorados no ambiente, bem como a linha de comando que será executada quando tais sinais forem recebidos.

Se a linha de comandos do trap for nula (vazia), isto significa que os sinais especificados devem ser ignorados quando recebidos. Por exemplo, o comando:

    trap "" 2

Especifica que o sinal de interrupção (<CTRL+C>) deve ser ignorado. No caso citado, quando não se deseja que sua execução seja interrompida. No último exemplo note que o primeiro argumento deve ser especificado para que o sinal seja ignorado, e não é equivalente a escrever o seguinte, cuja finalidade é retornar o sinal 2 ao seu estado padrão (default):

    trap 2

Se você ignora um sinal, todos os Subshells irão ignorar este sinal. Portanto, se você especifica qual ação deve ser tomada quando receber um sinal, então todos os Subshells irão também tomar a ação quando receberem este sinal, ou seja, os sinais são automaticamente exportados. Para o sinal que temos mostrado (sinal 2), isto significa que os Subshells serão encerrados.

Suponha que você execute o comando:

    trap "" 2

e então execute um Subshell, que tornará a executar outro script como um Subshell. Se for gerado um sinal de interrupção, este não terá efeito nem sobre o Shell principal nem sobre os Subshell por ele chamados, já que todos eles ignorarão o sinal.

Outra forma de restaurar um sinal ao seu default é fazendo:

    trap - sinal

Em korn shell (ksh) não existe a opção -s do comando read para ler uma senha. O que costumamos fazer é usar o comando stty com a opção -echo que inibe a escrita na tela até que se encontre um stty echo para restaurar esta escrita. Então, se estivéssemos usando o interpretador ksh, a leitura da senha teria que ser feita da seguinte forma:

    echo -n "Senha: "
    stty -echo
    read Senha
    stty echo

O problema neste tipo de construção é que caso o operador não soubesse a senha, ele provavelmente daria um <CTRL+C> ou um <CTRL+\> durante a instrução read para descontinuar o programa e, caso ele agisse desta forma, o que quer que ele escrevesse, não apareceria na tela do seu terminal. Para evitar que isso aconteça, o melhor a fazer é:

    echo -n "Senha: "
    trap "stty echo
          exit" 2 3
    stty -echo
    read Senha
    stty echo
    trap 2 3

Para terminar este assunto, abra uma console gráfica e escreva no prompt de comando o seguinte:

$ trap "echo Mudou o tamanho da janela" 28

Em seguida, pegue o mouse (arghh!!) e arraste-o de forma a variar o tamanho da janela corrente. Surpreso? É o Shell orientado a eventos... smile

Mais unzinho porque não pude resistir. Agora escreva assim:

$ trap "echo já era" 17

Em seguida faça:

$ sleep 3 &

Você acabou de criar um subshell que irá dormir durante três segundos em background. Ao fim deste tempo, você receberá a mensagem já era, porque o sinal 17 é emitido a cada vez que um subshell termina a sua execução.

Para devolver estes sinais aos seus defaults, faça:

$ trap 17 28

Ou

$ trap - 17 28

Acabamos de ver mais dois sinais que não são tão importante como os que vimos anteriormente, mas vou registrá-los na tabela a seguir:

Sinais Não Muito Importantes
  28     SIGWINCH     Mudança no tamanho da janela gráfica  
Sinal  Gerado por:
  17     SIGCHLD     Fim de um processo filho  

Muito legal este comando, né? Se você descobrir algum caso bacana de uso de sinais, por favor me informe por e-mail porque é muito rara a literatura sobre o assunto.

Comando getopts

O comando getopts recupera as opções e seus argumentos de uma lista de parâmetros de acordo com a sintaxe POSIX.2, isto é, letras (ou números) após um sinal de menos (-) seguidas ou não de um argumento; no caso de somente letras (ou números) elas podem ser agrupadas. Você deve usar este comando para "fatiar" opções e argumento passados para o seu script.

Sintaxe:

    getopts cadeiadeopcoes nome

A cadeiadeopcoes deve explicitar uma cadeia de caracteres com todas as opções reconhecidas pelo script, assim se ele reconhece as opções -a -b e -c, cadeiadeopcoes deve ser abc. Se você deseja que uma opção seja seguida por um argumento, ponha dois-pontos (:) depois da letra, como em a:bc. Isto diz ao getopts que a opção -a tem a forma:

    -a argumento

Normalmente um ou mais espaços em branco separam o parâmetro da opção; no entanto, getopts também manipula parâmetros que vêm colados à opção como em:

    -aargumento

cadeiadeopcoes não pode conter interrogação (?).

O nome constante da linha de sintaxe acima, define uma variável que cada vez que o comando getopts for executado, receberá a próxima opção dos parâmetros posicionais e a colocará na variável nome.

getopts coloca uma interrogação (?) na variável definida em nome se achar uma opção não definida em cadeiadeopcoes ou se não achar o argumento esperado para uma determinada opção.

Como já sabemos, cada opção passada por uma linha de comandos tem um índice numérico, assim, a primeira opção estará contida em $1, a segunda em $2, e assim por diante. Quando o getopts obtém uma opção, ele armazena o índice do próximo parâmetro a ser processado na variável OPTIND.

Quando uma opção tem um argumento associado (indicado pelo : na cadeiadeopcoes), getopts armazena o argumento na variável OPTARG. Se uma opção não possui argumento ou o argumento esperado não foi encontrado, a variável OPTARG será "matada" (unset).

O comando encerra sua execução quando:

  • Encontra um parâmetro que não começa por menos (-);
  • O parâmetro especial -- marca o fim das opções;
  • Quando encontra um erro (por exemplo, uma opção não reconhecida).

O exemplo abaixo é meramente didático, servindo para mostrar, em um pequeno fragmento de código o uso pleno do comando.

$ cat getoptst.sh #!/bin/sh

# Execute assim: # # getoptst.sh -h -Pimpressora arq1 arq2 # # e note que as informacoes de todas as opcoes sao exibidas # # A cadeia 'P:h' diz que a opcao -P eh uma opcao complexa # e requer um argumento, e que h eh uma opcao simples que nao requer # argumentos.

while getopts 'P:h' OPT_LETRA do echo "getopts fez a variavel OPT_LETRA igual a '$OPT_LETRA'" echo " OPTARG eh '$OPTARG'" done used_up=`expr $OPTIND - 1` echo "Dispensando os primeiros \$OPTIND-1 = $used_up argumentos" shift $used_up echo "O que sobrou da linha de comandos foi '$*'"

Para entendê-lo melhor, vamos executá-lo como está sugerido em seu cabeçalho:

$ getoptst.sh -h -Pimpressora arq1 arq2 getopts fez a variavel OPT_LETRA igual a 'h' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 2 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'

Desta forma, sem ter muito trabalho, separei todas as opções com seus respectivos argumentos, deixando somente os parâmetros que foram passados pelo operador para posterior tratamento.

Repare que se tivéssemos escrito a linha de comando com o argumento (impressora) separado da opção (-P), o resultado seria exatamente o mesmo, exceto pelo $OPTIND, já que neste caso ele identifica um conjunto de três opções/argumentos e no anterior somente dois. Veja só:

$ getoptst.sh -h -P impressora arq1 arq2 getopts fez a variavel OPT_LETRA igual a 'h' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 3 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'

Repare, no exemplo a seguir, que se passarmos uma opção inválida, a variável $OPT_LETRA receberá um ponto-de-interrogação (?) e a $OPTARG será "apagada" (unset).

$ getoptst.sh -f -Pimpressora arq1 arq2 # A opção -f não é valida ./getoptst.sh: illegal option -- f getopts fez a variavel OPT_LETRA igual a '?' OPTARG eh '' getopts fez a variavel OPT_LETRA igual a 'P' OPTARG eh 'impressora' Dispensando os primeiros $OPTIND-1 = 2 argumentos O que sobrou da linha de comandos foi 'arq1 arq2'

     - Me diz uma coisa: você não poderia ter usado um case para evitar o getopts?

     - Poderia sim, mas para que? Os comandos estão aí para serem usados... O exemplo dado foi didático, mas imagine um programa que aceitasse muitas opções e seus parâmetros poderiam ou não estar colados às opções, suas opções também poderiam ou não estar coladas, ia ser um case infernal e com getopts é só seguir os passos acima.

     - É... Vendo desta forma acho que você tem razão. É porque eu já estou meio cansado com tanta informação nova na minha cabeça. Vamos tomar a saideira ou você ainda quer explicar alguma particularidade do Shell?

     - Nem um nem outro, eu também já cansei mas hoje não vou tomar a saideira porque estou indo dar aula na UniRIO, que é a primeira universidade federal que está preparando no uso de Software Livre, seus alunos do curso de graduação em informática.

Mas antes vou te deixar um problema para te encucar: quando você varia o tamanho de uma tela, no seu centro não aparece dinamicamente em vídeo reverso a quantidade de linhas e colunas? Então! Eu quero que você reproduza isso usando a linguagem Shell.

     - Chico, traz rapidinho a minha conta! Vou contar até um e se você não trouxer eu me mando!

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.

-- JulioNeves - 18 Mar 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