



Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Os melhores documentos à venda: Trabalhos de alunos formados
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Comunidade
Peça ajuda à comunidade e tire suas dúvidas relacionadas ao estudo
Descubra as melhores universidades em seu país de acordo com os usuários da Docsity
Guias grátis
Baixe gratuitamente nossos guias de estudo, métodos para diminuir a ansiedade, dicas de TCC preparadas pelos professores da Docsity
Neste documento, o autor discute a substituição de parâmetros em shell script e a utilização do comando trap para monitorar sinais. Ele fornece exemplos práticos e explica a ordem de resolução de comandos no shell. Além disso, ele aborda a execução de comandos dentro de variáveis e a importância da legibilidade do código, mesmo que a performance seja ótima.
Tipologia: Notas de estudo
1 / 6
Esta página não é visível na pré-visualização
Não perca as partes importantes!
aê amigo, te dei a maior moleza na última aula né? Um exerciciozinho muito simples…
Vou te dar um problema que eu duvido que você resolva: $ var1= $ var2=var Te dei essas duas variáveis e quero que você me diga como eu posso, me referindo apenas à variável a var2 , listar o valor de var1 (que, no nosso caso, é 3).
echo $var2
01 # A função recebe 3 parâmetros na seguinte ordem: 02 # $1 - Mensagem a ser mostrada na tela 03 # $2 - Valor a ser aceito com resposta padrão 04 # $3 - O outro valor aceito 05 # Supondo que $1=Aceita?, $2=s e $3=n, a linha 06 # abaixo colocaria em Msg o valor "Aceita? (S/n)" 07 TotCols=${TotCols:-$(tput cols)} # Se não estava definido, agora está 08 LinhaMesg=${LinhaMesg:-$(($(tput lines)-3))} # Idem 09 Msg="$1 (echo $2 | tr a-z A-Z
/echo $3 | tr A-Z a-z
)" 10 TamMsg=${#Msg} 11 Col=$(((TotCols - TamMsg) / 2)) # Para centralizar Msg na linha 12 tput cup $LinhaMesg $Col 13 read -n1 -p "$Msg " SN 14 SN=${SN:-$2} # Se vazia coloca o padrão em SN 15 SN=$(echo $SN | tr A-Z a-z) # A saída de SN será em minúsculas 16 tput cup $LinhaMesg $Col; tput el # Apaga Msg da tela
Dave Hamilton - www.sxc.hu
julho 2005 edição 10
Repare que eu coloquei o echo $var2 entre crases ( ` ), porque dessa forma ele terá prioridade de execução e resultará em var. E echo $var1 produzirá 3…
echo $var2
$varecho $var2
3 Esse exemplo também poderia ter sido feito de outra maneira. Dá só uma olhada: $ eval echo $$var 3 Na primeira passada a contrabarra ( * ) seria retirada e $var seria resolvido produzindo var1. Na segunda passada teria so- brado echo $var1 , que produziria o resultado esperado. Agora vou colocar um comando dentro de var2 e executar: $ var2=ls $ $var 10porpag1.sh alo2.sh incusu logado 10porpag2.sh ArqDoDOS.txt1 listamusica logaute.sh 10porpag3.sh confuso listartista mandamsg.func alo1.sh contpal.sh listartista3 monbg.sh Agora vamos colocar em var2 o seguinte: ls $var1 ; e em var1 vamos colocar l , vejamos o resultado: $ var2='ls $var1' $ var1='l*' $ $var ls: $var1: No such file or directory $ eval $var listamusica listartista listartista3 logado logaute.sh Novamente, no tempo de substituição das variáveis, $var ainda não havia se apresentado ao Shell para ser resolvida. Assim, só nos resta executar o comando eval para dar as duas passadas necessárias. Uma vez um colega da excelente lista de discussão groups.yahoo.com/ group/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 corres- pondente fosse executado. Veja minha proposta na listagem 2 :**01 #!/bin/bash 02 # 03 # Lista que enumera os programas com extensão .sh no 04 # diretório corrente e executa o escolhido pelo operador 05 # 06 clear; i= 07 printf "%11s\t%s\n\n" Opção Programa 08 CASE='case $opt in' 09 for arq in .sh 10 do 11 printf "\t%03d\t%s\n" $i $arq 12 CASE="$CASE 13 "$(printf "%03d)\t %s;;" $i $arq) 14 i=$((i+1)) 15 done 16 CASE="$CASE 17 ). erro;; 18 esac" 19 read -n3 -p "Informe a opção desejada: " opt 20 echo 21 eval "$CASE"
Para fazer a monitoração de sinais existe o comando trap , cuja sintaxe pode ser uma das mostradas a seguir: trap "cmd1; cmd2; cmdn" S1 S2 … SN 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 as apóstrofes ( ' ) só são necessárias caso o trap possua mais de um comando cmd associado. Cada uma delas pode ser tam- bém uma função interna, uma externa ou outro script. Para entender o uso de aspas ( " ) e apóstrofes ( ' ) vamos recorrer a um exemplo que trata um fragmento de um script que faz uma transferência de arquivos via FTP para uma máquina remota ( $RemoComp ), na qual o usuário é $Fulano , sua senha é $Segredo e o arquivo a ser enviado é $Arq. Suponha ainda que essas quatro variáveis foram recebidas por uma rotina anterior de leitura e que esse script seja muito usado por diversas pessoas. Vejamos o trecho de código a seguir: ftp -ivn $RemoComp << FimFTP >> /tmp/$$ U 2>> /tmp/$$ user $Fulano $Segredo binary get $Arq FimFTP Repare que tanto as saídas dos diálo- gos do FTP como os erros encontrados estão sendo redirecionados para /tmp/$$ , o que é uma construção bastante comum 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. Com esse tipo de construção evita-se que dois ou mais usuários disputem a posse e os di- reitos sobre um arquivo. Caso a transferência seja interrompida por um kill ou um [CTRL]+[C] , certa- mente deixará lixo no disco. É exatamen- te essa a forma mais comum de uso do comando trap. Como isso é trecho de um script devemos, logo no início dele, digitar o comando: trap "rm -f /tmp/$$ ; exit" 0 1 2 3 15 Dessa forma, caso houvesse uma inter- rupçã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 não houvesse a instrução exit na linha de comando do trap , ao final da execução dessa linha o fluxo do pro- grama retornaria ao ponto em que estava quando recebeu o sinal que originou a execução desse trap. Note também que o Shell pesquisa a linha de comando uma vez quando o trap é interpretado (e é por isso que é usual colocá-lo no início do programa) e nova- mente quando um dos sinais listados é recebido. Então, no último exemplo, o va- lor de $$ será substituído no momento em que o comando trap é lido pela primeira vez, já que as aspas ( " ) não protegem o cifrão ( $ ) da interpretação do Shell. Se você quisesse fazer a substituição somente ao receber o sinal, o comando deveria ser colocado entre apóstrofes ( ' ). Assim, na primeira interpretação do trap , o Shell não veria o cifrão ( $ ), as apóstro- fes ( ' ) seriam removidas e, finalmente, o Shell poderia substituir o valor da variá- vel. Nesse caso, a linha ficaria assim: 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 , colocado em execução por script1. Por serem dois processos diferentes, terão dois PIDs distintos. 1º Caso : O comando ftp encontra-se em script1. Nesse 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 nesse mo- mento 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 comando ftp encontra-se em script2. Nesse caso, o argumento do comando trap deveria estar entre apóstrofes ( ' ), pois caso a interrupção se desse durante a execução de script1 , o arquivo não teria sido criado; caso ela ocorresse durante a execução de script2 , o valor de $$ seria o PID desse 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á exe- cutada quando tais sinais forem recebidos. Se a linha de comandos do trap for nula (vazia), isso significa que os sinais espe- cificados devem ser ignorados quando recebidos. Por exemplo, o comando trap "" 2 especifica que o sinal de interrup- ção ( [CTRL]+[C] ) deve ser ignorado. No último exemplo, note que o primeiro ar- gumento deve ser especificado para que o sinal seja ignorado e não é equivalente a escrever trap 2 , cuja finalidade é retornar o sinal 2 ao seu estado padrão. (^) ➟
0 EXIT Fim normal do programa 1 SIGHUP Quando o programa recebe um kill -HUP 2 SIGINT Interrupção pelo teclado. ( [CTRL]+[C] ) 3 SIGQUIT Interrupção pelo teclado ( [CTRL]+[] ) 15 SIGTERM Quando o programa recebe um kill ou kill -TERM
Se você ignorar um sinal, todos os sub- shells irão ignorá-lo. Portanto, se você especificar qual ação deve ser tomada quando receber um sinal, todos os sub- shells irão tomar a mesma ação quando receberem esse sinal. Ou seja, os sinais são automaticamente exportados. Para o sinal mostrado (sinal 2), isso significa que os sub-shells serão encerrados. Suponha que você execute o comando trap "" 2 e então execute um sub-shell, que tornará a executar outro script como um sub-shell. Se for gerado um sinal de interrupção, este não terá efeito nem sobre o Shell principal nem sobre os sub-shell por ele chamados, já que todos eles ignorarão o sinal. Em korn shell ( ksh ) não existe a opção -s do comando read para ler uma senha. O que costumamos fazer é usar usar o comando stty com a opção -echo , que inibe a escrita na tela até que se encon- tre um stty echo para restaurar essa 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 com esse tipo de constru- ção é que, caso o operador não soubes- se a senha, ele provavelmente teclaria [CTRL]+[C] ou um [CTRL]+[] durante a instrução read para descontinuar o pro- grama e, caso agisse dessa forma, o seu terminal estaria sem echo. 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 esse assunto, abra um console gráfico e escreva no prompt de comando o seguinte: $ trap "echo Mudou o tamanho da janela" 28 Em seguida, pegue o mouse e arraste-o de forma a variar o tamanho da janela corrente. Surpreso? É o Shell orientado a eventos… Mais unzinho, porque não consigo resistir. Escreva isto: $ trap "echo já era" 17 Em seguida digite: $ sleep 3 & Você acabou de criar um sub-shell que irá dormir durante três segundos em background. Ao fim desse tempo, você receberá a mensagem “já era”, porque o sinal 17 é emitido a cada vez em que um sub-shell termina a sua execução. Para devolver esses sinais ao seu comporta- mento padrão, digite: trap 17 28. Muito legal esse comando, né? Se você descobrir algum material bacana sobre uso de sinais, por favor me informe por email, porque é muito rara a literatura sobre o assunto.
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 agrupa- das. Você deve usar esse comando para "fatiar" opções e argumentos passados para o seu script. A 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ê desejar que uma opção seja seguida por um argumento, ponha um sinal de dois pontos ( : ) depois da letra, como em a:bc. Isso 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 um si- nal de interrogação (? ). O nome constante da linha de sintaxe acima define uma variável que receberá, a cada vez que o comando getopts for executado, o próximo dos parâmetros posicionais e o 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 ín- dice 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 cadeiade- opcoes ), getopts armazena o argumento na variável OPTARG. Se uma opção não possuir argumento ou se o argumento esperado não for encontrado, a variável OPTARG será "apagada" (com unset ). O co- mando encerra sua execução quando: P Encontra um parâmetro que não come- ça com um hífen ( - ). P O parâmetro especial -- indica o fim das opções. P Quando encontra um erro (por exemplo, uma opção não reconhecida). O exemplo da listagem 4 é meramente didático, servindo para mostrar, em um pequeno fragmento de código, o uso ple- no do comando.
julho 2005 edição 10