Você está na página 1de 37

1

Programando em Shell Script


Quase tudo no Linux pode ser feito via linha de comando. possvel baixar e instalar programas automaticamente, alterar qualquer tipo de configurao do sistema, carregar programas ou executar operaes diversas durante o boot, etc. Dentro do KDE possvel at mesmo controlar programas grficos, minimizando uma janela, abrindo um novo email, j com o corpo da mensagem preenchido no kmail, exibir uma mensagem de aviso e assim por diante. Um script um arquivo de texto, com uma seqncia de comandos que so executados. Dentro de um script voc pode utilizar qualquer comando de terminal (incluindo programas grficos) e tambm funes lgicas suportadas pelo shell, que incluem operaes de tomada de deciso, comparao, etc. Voc pode at mesmo acessar bancos de dados ou configurar outras mquinas remotamente. A princpio, o shell script lembra um pouco os arquivos .bat do DOS, que tambm eram arquivos de texto com comandos dentro, da mesma forma que um ser humano e uma ameba conservam muitas coisas em comum, como o fato de possurem DNA, se reproduzirem e sintetizarem protenas. Mas, assim como um humano muito mais inteligente e evoludo que uma ameba, um shell script pode ser incomparavelmente mais poderoso e elaborado que um simples .bat do DOS. possvel escrever programas elaborados em shell script, substituindo aplicativos que demorariam muito mais tempo para ser escritos em uma linguagem mais elaborada. Seus scripts podem tanto seguir a velha guarda, com interfaces simples de modo texto (ou mesmo no ter interface alguma), de forma a desempenhar tarefas simples, quanto possuir uma interface grfica elaborada, escrita usando o kommander e funes do kdialog. Um exemplo de trabalho desenvolvido em shell script o Painel de controle do Kurumin, que utiliza um conjunto de painis grficos, criados usando o Kommander, que ativam um emaranhado de scripts para desempenhar as mais diversas tarefas.

O programa de instalao do Kurumin escrito em shell script, assim como a maior parte dos programas encarregados de configurar o sistema durante o boot, os painis para instalar novos programas, configurar servidores, e tudo mais. O principal motivo para uso de scripts em shell ao invs de programas escritos em C ou C++ por exemplo a rapidez de desenvolvimento, combinado com a facilidade de editar os scripts existentes para corrigir problemas ou adicionar novos recursos. Voc vai encontrar uma grande quantidade de scripts de configurao tambm no Slackware, Debian e muitas outras distribuies. Um shell script um conjunto de comandos de terminal, organizados de forma a desempenhar alguma tarefa. O modo de comando do Linux extremamente poderoso, o que d uma grande flexibilidade na hora de escrever scripts. Voc pode inclusive incluir trechos com comandos de outras linguagens interpretadas, como perl ou python por exemplo. O primeiro passo para escrever um script, descobrir uma forma de fazer o que precisa via linha de comando. Vamos comear um um exemplo simples: O comando "wget" permite baixar arquivos, podemos us-lo para baixar o ISO do Kurumin, por exemplo: $ wget -c http://fisica.ufpr.br/kurumin/kurumin-4.0.iso (o "-c" permite continuar um download interrompido) Depois de baixar o arquivo, importante verificar o md5sum para ter certeza que o arquivo est correto: $ md5sum kurumin-4.0.iso Estes dois comandos podem ser usados para criar um script rudimentar, que baixa o Kurumin e verifica o md5sum. Abra o kedit ou outro editor de textos que preferir e inclua as trs linhas abaixo: #!/bin/sh wget -c http://fisica.ufpr.br/kurumin/kurumin-4.0.iso md5sum kurumin-4.0.iso O "#!/bin/sh" indica o programa que ser usado para interpretar o script, o prprio bash. Por norma, todo script deve

2
comear com esta linha. Na verdade, os scripts at funcionam sem ela, mas no custa fazer as coisas certo desde o incio. Existe a possibilidade de escrever scripts usando outros interpretadores, ou mesmo comandos como o sed. Neste caso o script comearia com "#!/bin/sed" por exemplo. Note que a tralha, "#", usada para indicar um comentrio. Toda linha comeada com ela ignorada pelo bash na hora que o script executado, por isso a usamos para desativar linhas ou incluir comentrios no script. A linha "#!/bin/sh" a nica exceo para esta regra. Ao terminar, salve o arquivo com um nome qualquer. Voc pode usar uma extenso como ".sh" para que outras pessoas saibam que trata-se de um shell script, mas isto no necessrio. Lembre-se que no Linux as extenses so apenas parte do nome do arquivo. Marque a permisso de execuo para ele nas propriedades do arquivo, ou use o comando: $ chmod +x teste.sh Execute-o colocando um "./" na frente do nome do arquivo, o que faz o interpretador entender que ele deve executar o "teste.sh" est na pasta atual. Caso contrrio ele tenta procurar nas pastas /bin/, /usr/bin e /usr/local/bin que so as pastas onde ficam os executveis do sistema e no acha o script. $ ./teste.sh O md5sum soma os bits do arquivo e devolve um nmero de 32 caracteres. No mesmo diretrio do servidor onde foi baixado o arquivo, est disponvel um arquivo "kurumin-4.0.md5sum.txt" que contm o md5sum correto do arquivo. O resultado do md5sum do arquivo baixado deve ser igual ao do arquivo, caso contrrio significa que o arquivo veio corrompido e voc precisa baixar de novo. Voc j deve estar cansado de baixar as novas verses do Kurumin e j sabe de tudo isso. Podemos aproveitar para ensinar isso ao nosso script, fazendo com que, depois de baixar o arquivo, ele verifique o md5sum e baixe o arquivo de novo caso ele esteja corrompido. Isto vai deixar o script um pouco mais complexo: #!/bin/sh wget -c http://fisica.ufpr.br/kurumin/kurumin-4.0.iso md5sum=`md5sum kurumin-4.0.iso` if [ "$md5sum" != "ce770ea8740522750f6bb67a8603f173 kurumin-4.0.iso" ]; then rm -f kurumin-4.0.iso ./teste.sh else echo "O arquivo foi baixado corretamente" fi Voc vai perceber que ao executar este segundo script, ele vai tentar baixar o arquivo novamente sempre que o md5sum no bater, se necessrio vrias vezes. Para isso, comeamos a utilizar algumas operaes lgicas simples, que lembram um pouco as aulas de pseudo-cdigo que os alunos de cincias da computao tm no primeiro ano. No script anterior, usamos simplesmente o comando "md5sum kurumin-4.0.iso". Ele simplesmente mostra o md5sum do arquivo na tela, sem fazer nada mais. Neste segundo script esta linha ficou um pouco diferente: md5sum=`md5sum kurumin-4.0.iso`. A diferena que ao invs de mostrar o mds5um na tela, armazenamos o resultado numa varivel, chamada "md5sum". O sinal usado aqui no o apstrofo, como mais comum em outras linguagens, mas sim a craze (o mesmo do ""). O shell primeiro executa os comandos dentro das crazes e armazena o resultado dentro da varivel. As variveis podem armazenar qualquer tipo de informao, como um nmero, um texto ou o resultado de um comando. Elas podem ser comparadas, podemos verificar se o texto dentro da varivel "md5sum" igual ao texto que est no arquivo do servidor e fazer o script decidir se deve baixar o arquivo de novo ou no. Para comparar duas informaes num shell script, usamos o smbolo "!=" (no igual, ou seja: diferente). Para saber se o arquivo foi baixado corretamente, comparamos a varivel md5sum com o md5sum correto do arquivo: "$md5sum" != "ce770ea8740522750f6bb67a8603f173 kurumin-4.0.iso"

Alm do !=, Outros operadores lgicos que podem ser usados so:

== : Igual > : Maior >= : Maior ou igual < : Menor <= : Menor ou igual Mas, s comparar no adianta. Precisamos dizer ao script o que fazer depois. Lembre-se que os computadores so burros, voc precisa dizer o que fazer em cada situao. Neste caso temos duas possibilidades: o md5sum pode estar errado ou certo. Se estiver errado, ele deve baixar o arquivo de novo, caso contrrio no deve fazer nada. Usamos ento um "if" (se) para criar uma operao de tomada de deciso. Verificamos o mds5um, se ele for diferente do correto, ento (then) ele vai deletar o arquivo danificado e comear o download de novo. Caso contrrio (else) ele vai simplesmente escrever uma mensagem na tela. if [ "$md5sum" != "ce770ea8740522750f6bb67a8603f173 kurumin-4.0.iso" ]; then rm -f kurumin-4.0.iso ./teste.sh else echo "O arquivo foi baixado corretamente" fi Veja que dentro da funo then, usei o comando "rm -f kurumin-4.0.iso" para deletar o arquivo e depois executei de novo o "./teste.sh" que vai executar nosso script de novo, dentro dele mesmo! Isso vai fazer com que o script fique em loop, obssessivamente, at conseguir baixar o arquivo corretamente. Uma coisa interessante nos scripts que eles podem ser executados dentro deles mesmos e alterados durante a execuo. O script pode at mesmo deletar a s mesmo depois de rodar uma vez, uma espcie de script suicida! :-P Por exemplo, o instalador do Kurumin, cria o script /etc/rc5.d/S99printconf ao instalar o sistema. Por estar dentro da pasta /etc/rc5.d, ele executado durante o boot. Este script roda o printconf, que detecta as impressoras instaladas. Depois disso o script deleta a s mesmo, fazendo que que seja executado uma nica vez, durante o primeiro boot depois da instalao: #!/bin/sh printconf -v rm -f /etc/rc5.d/S99printconf Estes dois exemplos so scripts simples, que simplesmente executam alguns comandos, sem oferecer nenhum tipo de interatividade. Se voc quisesse que o primeiro script baixasse outro arquivo, teria que edit-lo manualmente.

Fazendo Perguntas
Voc pode incluir perguntas no script, para coletar as informaes necessrias para montar e executar algum comando complicado. Por exemplo, o mais legal de ter uma placa de recepo de TV poder gravar programas, usando o micro como um videocassete. Porm, programas grficos como o xawtv e o zapping no oferecem uma boa qualidade de gravao. Entre os programas de modo texto, o mencoder o que oferece melhor qualidade, mas ele oferece muitas opes e por isso no exatamente um exemplo de amigabilidade. O comando para gravar a programao do canal 12 da TV aberta durante uma hora, compactando em Divx 4 seria: $ mencoder tv:// -tv driver=v4l2:input=0:normid=4:channel=12: chanlist=us-bcast:width=640:height=480:device=/dev/video0: adevice=/dev/dsp0:audiorate=32000: forceaudio:forcechan=2:buffersize=64 -quiet -oac mp3lame -lameopts preset=medium -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=3000:keyint=132 -vop pp=lb -endpos 01:00:00 -o /home/kurumin/video.avi As partes do comando que mudariam de uma chamada a outra seriam o canal (channel=12) o tempo de gravao ("endpos 01:00:00", para uma hora) e o arquivo que ser gerado (/home/kurumin/video.avi). Podemos fazer com que nosso script pergunte estas informaes, armazenando tudo em variveis e no final monte o comando. Isto transformaria um comando indigesto, de quase 400 caracteres num script amigvel que sua av poderia usar.

4
Existem vrias formas de exibir uma pergunta na tela e armazenar a resposta numa varivel. A forma mais simples seria usar o comando "echo" para mostar a pergunta e o comando "read" para ler a resposta, como em: echo "Qual canal gostaria de gravar? (ex: 12)" read canal echo "Qual o tempo de gravao? (ex: 01:00:00)" read tempo echo "Em qual arquivo o vdeo ser salvo? (ex: /home/kurumin/video.avi)" read arquivo O "read" faz com que o script pare e fique esperando uma resposta. Ao digitar qualquer coisa e pressionar enter, ele vai para a prxima pergunta e assim por diante at executar o ltimo comando. Teramos ento trs variveis, "canal", "tempo" e "arquivo" que poderamos utilizar para montar o comando principal, que, dentro do script, ficaria: mencoder tv:// -tv driver=v4l2:input=0:normid=4:channel=$canal: chanlist=us-bcast:width=640:height=480:device=/dev/video0: adevice=/dev/dsp0:audiorate=32000: forceaudio:forcechan=2:buffersize=64 -quiet -oac mp3lame -lameopts preset=medium -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=3000:keyint=132 -vop pp=lb -endpos $tempo -o $arquivo Veja que ao criar uma varivel, simplesmente a chamamos pelo nome, mas ao utiliz-la depois precisamos usar um smbolo de dlar, "$". isso que faz o bash diferenciar a varivel "arquivo" da palavra (ou comando) "arquivo". Isto j seria o suficiente para ter um script funcional. A desvantagem neste caso que o script roda em modo texto e possui um visual muito pobre.

Existem programas que permitem incrementar o script, transformando as perguntas em janelas grficas. Os trs mais usados so o dialog, o Xdialog e o kdialog. O dialog o mais antigo e tradicional. Ele no gera geralmente uma janela grfica, mas sim uma janela de modo texto, que lembra os tempos do Clipper. A vantagem que ele permite que o script seja executado em modo texto puro ou remotamente (via ssh ou telnet), mesmo em conexes lentas. Por exemplo, para mostrar um aviso na tela, o comando seria: dialog --msgbox "Seu micro est pegando fogo" 10 50 O "10 50" indica o tamanho da janela, em caracteres. O dialog capaz de exibir vrios tipos de janelas, para abrir e salvar arquivos, escolher entre opes, etc. Voc pode ver todas as opes atravs do "man dialog".

No nosso caso, precisamos ler a resposta, por isso usamos o parmetro "--inputbox" do dialog:

dialog --inputbox "Canal a gravar (ex: 12)" 10 60 "12" 2> /tmp/resposta.tmp canal=`cat /tmp/resposta.tmp` O "10 60" indica o tamanho da janela, como j vimos. O "12" que vem a seguir o valor default, que assumido caso voc simplesmente pressione Enter. interessante usar um valor padro nas perguntas, ele ao mesmo tempo serve como um exemplo do que deve ser respondido e como uma garantia que a resposta no vir em branco. O "2> /tmp/resposta.tmp" faz com que a resposta seja gravada num arquivo de texto. Em seguida, o "canal=`cat /tmp/resposta.tmp`" cria a varivel "canal", com a resposta. O comando cat serve para listar o contedo de um arquivo de texto. Originalmente ele simplesmente escreveria na tela. Mas, usado desta forma, a sada do cat (o texto dentro do arquivo) armazenado na varivel, sem ser mostrado na tela. O resultado o mesmo do exemplo anterior, mas desta vez com uma interface um pouco melhor:

O Xdialog possui quase as mesmas opes e sintaxe do dialog, mas gera janelas grficas. Nem todas as distribuies trazem o Xdialog instalado por padro, nestes casos voc pode baixar a verso mais recente no: http://xdialog.dyns.net/ Em distribuies derivadas do Debian voc pode instala-lo via apt-get, o pacote est disponvel nos servidores principais. No caso das distribuies que usam pacotes rpm procure no http://www.rpmfind.net/linux/RPM/ Veja que o comando exatamente igual ao exemplo anterior, muda apenas o comando: Xdialog --inputbox "Canal a gravar (ex: 12)" 10 60 "12" 2> /tmp/resposta.tmp canal=`/tmp/resposta.tmp` Nossa janela em kdialog:

Este o script completo, que desenvolvi para o Kurumin usando janelas em kdialog, com comentrios das outras funes usadas:

6
#!/bin/sh # Gravar-TV # Script para gravar TV usando uma placa de captura. # Escrito por Carlos E. Morimoto <morimoto@guiadohardware.net> para o Kurumin kdialog --title "Gravar-TV" --msgbox "Este script permite gravar programas de TV, usando uma placa de captura. Ao gravar, voc precisa fechar o TVtime ou qualquer outro programa de sintonia de TV que esteja aberto. Os vdeos so gravados com resoluo de 640x480, compactados em divx4, com uma qualidade prxima do DVD. Certifique-se de ter espao suficiente no HD. Cada hora de gravao gera um arquivo de aproximadamente 1.3 GB" var1=`kdialog --title "Gravar-TV" --inputbox "Canal a gravar (ex: 12)" "12"` var2=`kdialog --title "Gravar-TV" --inputbox "Durao da gravao (00:01:00 = 1 minuto)" "00:01:00"` # A opo --getsavename do kdialog abre uma janela do gerenciador de # arquivos, para que o usurio aponte a pasta e o nome do arquivo. # A opo :label1 faz com que a janela mostre apenas arquivos de vdeo var3=`kdialog --getsavefilename :label1 "*.avi *.mpg *.wmf |Arquivos de vdeo"` # As quebras de linha dentro do texto da opo faz com que o texto # fique formatado da mesma forma dentro da janela. var4=`kdialog --combobox "Padro de sintonia: us-bcast = TV aberta us-cable = TV a cabo" "us-bcast" "us-cable"` # A opo --passivepopup mostra um aviso que some depois do tempo especificado # neste caso depois de 6 segundos, ou quando o aviso clicado. kdialog --title "Gravando" --passivepopup "Gravando o canal $var1 por: $var2 horas no arquivo: $var3 Feche a janela de terminal para abortar" 6 & # Aqui vai o comando de gravao, montado usando todas as informaes coletadas # acima: mencoder tv:// -tv driver=v4l2:input=0:normid=4:channel=$var1:chanlist=$var4: width=640:height=480:device=/dev/video0:adevice=/dev/dsp0:audiorate=32000:forceaudio: forcechan=2:buffersize=64 -quiet -oac mp3lame -lameopts preset=medium -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=3000:keyint=132 -vop pp=lb -endpos $var2 -o $var3 # Depois do comando de gravao, ou seja, depois que a gravao termina, # mostrada mais uma janela de texto: kdialog --title "Gravar-TV" --passivepopup "Ok! A gravao terminou." 5 Este outro script, tambm escrito para o Kurumin, serve para montar compartilhamentos de rede em NFS. Diferentemente do script de gravar TV, ele foi escrito para funcionar tanto dentro do modo grfico (usando janelas em Xdialog) ou em modo texto puro, usando o dialog. Uma funo no incio do script se encarrega de detectar se o modo grfico est aberto ou no. Voc pode encontrar todos os scripts desenvolvidos para o Kurumin dentro da pasta /usr/local/bin/ do sistema, ou online no: http://www.guiadohardware.net/kurumin/bin/ Eles so intencionalmente escritos de forma simples, at elementar para facilitar o entendimento.

#!/bin/sh # Monta um compartilhamento NFS, por Carlos E. Morimoto # Esta funo permite que o script funcione tanto dentro do modo grfico, usando # o Xdialog, quanto em modo texto, usando o dialog. case "`tty`" in /dev/tty[1-8]) MODE=text DIALOG=dialog ;; /dev/pts/*|/dev/ttyp*) MODE=x export XDIALOG_HIGH_DIALOG_COMPAT=1 [ -x /usr/bin/gdialog ] && DIALOG=gdialog [ -x /usr/bin/Xdialog ] && DIALOG=Xdialog [ $DIALOG = dialog ] && MODE=text ;; *) esac # Este script corresponde ao cone "NFS - Montar Compartilhamento" no iniciar. # Ele facilita o acesso a compartilhamentos NFS que normalmente so uma tarefa # um tanto quanto indigesta para os iniciantes. # Comea perguntando ao usurio qual compartilhamento ser montado: $DIALOG --title "Acessar compartilhamento NFS" \ --backtitle "Acessar compartilhamento NFS" \ --ok-label "Continuar" --cancel-label "Sair" \ --inputbox "O NFS um protocolo que permite compartilhar arquivos facilmente entre mquinas Linux. Para compartilhar uma pasta no Kurumin clique no Iniciar > Sistema > NFS - Ativar Servidor.\n\n Este script um cliente que permite acessar compartilhamentos em outras mquinas. Para isso voc precisa apenasx informar o endereo IP do servidor, seguido da pasta que ele est compartilhando.\n\n Ex: 192.168.0.3:/home/arquivos" 21 70 '192.168.0.3:/home/arquivos' > /dev/null 2> /tmp/nfs1 retval=$? compartilhamento=`cat /tmp/nfs1` # O texto digitado armazenado na varivel "compartilhamento" que usaremos adiante. # Alm de saber qual compartilhamento ser montado, preciso saber onde ele ser montado: $DIALOG --title "Acessar compartilhamento NFS" \ --backtitle "Acessar compartilhamento NFS" \ --ok-label "Continuar" --cancel-label "Sair" \ --inputbox "Preciso saber agora em qual pasta local voc deseja que o compartilhamento fique acessvel. Um recurso interessante do NFS que os arquivos ficam acessveis como se fossem arquivos locais, voc pode at mesmo gravar um CD diretamente a partir da pasta com o compartilhamento.\n\n Voc pode usar qualquer pasta dentro do seu diretrio de usurio. Se a pasta no existir vou tentar cri-la para voc.\n\n Ex: /mnt/nfs" 21 70 '/mnt/nfs' > /dev/null 2> /tmp/nfs2 retval=$? localmount=`cat /tmp/nfs2` # Mais uma varivel, agora armazenando o texto com o diretrio local onde o # compartilhamento ser montado, localmount # Para o caso de alguma mente perturbada tentar montar o compartilhamento # numa pasta que no existe, vamos cri-la primeiro, antes de montar. O # comando mkdir no destrutvel, se a pasta j existir ele no far nada: mkdir $localmount # Vamos iniciar alguns servios necessrios para o NFS funcionar. No sabemos # se eles vo estar ou no abertos na mquina do usurio, por isso melhor # ter certeza. # Ao mesmo tempo em que os comandos so executados, eles so escritos na tela, # o que tem uma funo didtica. O sleep 2 faz com que o script pare por dois # segundos ao executar cada um dos comandos, dando tempo para que ele leia # alguma mensagem de erro.

8
Echo " " echo "Executando comando:" echo "sudo /etc/init.d/portmap/start" /etc/init.d/portmap start sleep 1 echo " " echo "Executando comando:" echo "sudo /etc/init.d/nfs-common start" /etc/init.d/nfs-common start sleep 1 BT="Acessar compartilhamento NFS" T1="Acessar compartilhamento NFS" M1="Voc gostaria de adicionar uma entrada no /etc/fstab e um cone no desktop, para que este compartilhamento possa ser acessado mais tarde com mais facilidade? Ao responder yes voc poder acessar os arquivos posteriormente apenas clicando no cone que ser criado no desktop." $DIALOG --title "$T1" --yesno "$M1" 18 60 x=$? if [ $x = 0 ] ; then echo '# Acessa compartilhamento de rede nfs, adicionado pelo nfs-montar:' >> /etc/fstab echo "$compartilhamento $localmount nfs noauto,users,exec 0 0" >> /etc/fstab echo " " >> /etc/fstab $DIALOG --msgbox "Vou abrir agora o arquivo /etc/fstab para que voc possa revisar e, caso necessrio, alterar a entrada includa. Delete as linhas repetidas no final do arquivo caso necessrio." kedit /etc/skel-fix/editar-fstab & sleep 2 sudo kedit /etc/fstab sleep 10 # Por fim criado um cone no desktop permitindo montar o mesmo compartilhamento # facilmente depois. Os cones do KDE so apenas arquivos de texto comuns. # Esta parte me fez quebrar um pouco a cabea. Se o usurio for criar vrios cones, # cada um precisar ter um nome de arquivo diferente. Eu poderia pedir para que ele # digitasse um nmero por exemplo e usa-lo como nome para o arquivo, mas nada # impedidiria que ele simplesmente digitasse o mesmo nmero repetidamente, o # que no resolveria o nosso problema :-P # Existe um dispositivo chamado /dev/urandom que gera nmeros aleatrios, ento # usei-o para gerar uma string de 8 caracteres que vou usar como nome de arquivo. # Armazeno os 8 caracteres num arquivo usando o dd e depois carrego-os numa varivel # que usada como nome de arquivo. O que aparece escrito no desktop no o nome # do arquivo mas sim o campo "Name" dentro do texto. # Atualmente isso feito atravs do script "passgen" do Nawtage, que gera os 8 # caracteres a partir do /dev/urandom. nome=`passgen` # Estas duas linhas comentadas fazem algo semelhante, usando o # o /dev/urandom: #rm -f of=/tmp/kramdom #dd if=/dev/urandom of=/tmp/kramdom bs=8 count=1 clear echo "[Desktop Entry]" >> ~/Desktop/$nome echo "Type=FSDevice" >> ~/Desktop/$nome echo "Dev=$compartilhamento" >> ~/Desktop/$nome echo "MountPoint=$localmount" >> ~/Desktop/$nome echo "FSType=nfs" >> ~/Desktop/$nome echo "ReadOnly=0" >> ~/Desktop/$nome echo "Icon=hdd_mount" >> ~/Desktop/$nome echo "UnmountIcon=hdd_unmount" >> ~/Desktop/$nome echo "Name=$compartilhamento" >> ~/Desktop/$nome fi

# As duas variveis que foram lidas acima so usadas para montar o comando que monta o compartilhamento echo "Executando comando:" echo "mount -t nfs $compartilhamento $localmount" mount -t nfs $compartilhamento $localmount sleep 2 # Remove os arquivos temporrios que foram usados: sudo rm -f /tmp/nfs1 sudo rm -f /tmp/nfs2 # Concluindo, abrimos uma janela do Konqueror j mostrando os arquivos do # compartilhamento, provendo gratificao imediata. Estamos na era do # fast-food de software... :-P konqueror $localmount # Ao fechar a janela do Konqueror o compartilhamento desmontado: umount $localmount exit 0 Uma dvida freqente sobre o uso das aspas. Num script voc pode tanto utilizar aspas duplas, ", quanto aspas simples ', mas as duas possuem funes ligeiramente diferentes. As aspas duplas fazem com que o contedo seja interpretado literalmente, isso permite incluir nomes de arquivos com espaos entre outras coisas. As aspas simples fazem o mesmo, mas de uma forma mais estrita, sem interpretar variveis. Por exemplo, o comando: echo "mount -t nfs $compartilhamento $localmount" do script anterior usa duas variveis. Ao executar o script elas seriam substitudas pelos valores correspondentes, fazendo com que fosse mostrado na tela algo como: "mount -t nfs 192.168.0.1/arquivos /mnt/nfs". Porm, se usssemos aspas simples: echo 'mount -t nfs $compartilhamento $localmount', o resultado do comando seria diferente. O bash escreveria a frase literalmente, sem interpretar as variveis: "mount -t nfs $compartilhamento $localmount" Ou seja, s usamos aspas simples quando realmente queremos usar um bloco de texto que no deve ser interpretado de forma alguma nem conter variveis. No restante do tempo, usamos sempre aspas duplas.

Mais dicas sobre o kdialog


O Kdialog oferece uma quantidade generosa de opes de caixas de dilogo. Alm do --msgbox, temos tambm o --sorry e --error, que podem ser usadas de acordo com o contexto: $ kdialog --sorry "Desculpe, no foi possvel criar o arquivo, verifique as permisses da pasta."

$ kdialog --error "O arquivo est corrompido. Experimente baix-lo novamente"

A opo --yesno permite fazer perguntas. A resposta armazenada na varivel "$?". Se a resposta for "sim", ela assume o valor 0, caso seja "no" ela armazena o valor 1. Se por acaso a janela for fechada, sem uma resposta, a varivel tambm fica com o valor 1: $ kdialog --yesno "Sua conexo muito lenta! A atualizao do sistema vai demorar duas semanas. Quer continuar mesmo assim? :-P" Como temos apenas duas possibilidades, voc pode usar um if para especificar o que o script deve fazer em cada caso:

10

resposta=$? if [ "$resposta" = "0" ] then apt-get upgrade fi if [ "$resposta" = "1" ] then kdialog --msgbox "Ok, abortando..." fi Aqui usei dois if, uma para o sim e outro para o no. Voc pode economizar algumas linhas usando um else: resposta=$? if [ "$resposta" = "0" ] then apt-get upgrade else kdialog --msgbox "Ok, abortando..." fi Existe uma pequena variao do --yesno que a opo "--warningcontinuecancel", onde a legenda dos botes muda para continuar/cancelar. Outra variao a opo "--yesnocancel" que mostra uma caixa com trs opes. Respondendo sim ou no, a varivel $? assume o valor 0 ou 1, mas respondendo "Cancelar" ela assume o valor 2.

A opo "Cancelar" pode ser usada para fechar o script, usando o comando "exit", que encerra a execuo, sem executar o resto dos comandos. Isto pode ser til num script longo, com muitos passos. importante que nestes casos voc encontre uma forma de desfazer as alteraes feitas nas opes anteriores, deixando tudo como estava antes de executar o script. Como agora temos trs possibilidades de resposta, podemos utilizar a funo "case", que permite especificar aes para um nmero indefinido de opes. kdialog --yesnocancel "Sua conexo muito lenta! A atualizao do sistema vai demorar duas semanas. Quer continuar mesmo assim? :-P" resposta=$? case $resposta in 0) apt-get upgrade ;; 1) kdialog --msgbox "Ok, abortando..." ;; 2) exit 0 ;; *) kdialog -- msgbox "Ops, isto no deveria acontecer... :-P" ;; esac Depois do "case $resposta in" voc adiciona cada uma das possibilidades de valor para a varivel, seguida de um parntese. No final de cada linha vai obrigatoriamente um ponto e vrgula duplo, que faz o bash entender que deve passar para a prxima opo. Se precisar colocar vrios comandos dentro de uma mesma opo, voc pode separ-los por um nico ponto e vrgula como em: 1) apt-get -f install; apt-get update; apt-get upgrade ;; O esac funciona da mesma forma que o else, uma opo "default" que executada se nenhuma das outras for vlida. O kdialog oferece trs opes de dilogos para abrir, salvar arquivos e selecionar pastas. Vimos uma delas no script gravar-tv, o --getsavefilename. As outras duas opes so o --getopenfilename (para selecionar um arquivo a ser aberto) e o --getexistingdirectory As trs opes so semelhantes no sentido de que permitem escolher um arquivo ou diretrio, muda basicamente a forma como o dilogo apresentado ao usurio.

11
A sintaxe um pouco diferente da das caixas de dilogo. Voc pode especificar uma pasta padro e tambm um filtro, com os formatos de arquivos que sero mostrados. O dilogo pode mostrar apenas arquivos de imagem e salvar com a extenso .png por exemplo. Um dilogo simples seria:

A varivel $arquivo criada com o nome escolhido, como por exemplo "/home/kurumin/Desktop/teste.txt". O dilogo no vai reclamar caso voc tente salvar o arquivo num diretrio onde o usurio no tm permisso de escrita. preciso que o prprio script verifique isso na hora de realmente criar ou modificar o arquivo. O "*.txt |Arquivos de texto" permite especificar os formatos de arquivo que sero mostrados na janela, e a legenda do filtro. Para mostrar apenas arquivos de imagem, deixando a extenso .png como padro, voc poderia utilizar algo como "*.png *.jpg *.gif *bmp |Arquivos de Imagem". A opo --getexistingdirectory mais simples, voc s precisa especificar um diretrio padro, como por exemplo: $ pasta=`kdialog --getexistingdirectory "/home/kurumin"`

Como no exemplo anterior, a varivel $pasta ser criada com o diretrio escolhido. Existem ainda trs opes diferentes de menus de seleo, criados usando as opes: --menu, --checklist e --combobox Na opo --menu mostrado um menu com as opes. onde voc s pode escolher uma. Como por exemplo: $ operacao=`kdialog --menu "O que voc gostaria de fazer?" a "Redimensionar a imagem" b "Girar a imagem" c "Deletar a imagem" d "Converter para outro formato"`

A varivel $operacao assume um dos 4 valores possveis, a, b, c ou d. Voc pode usar um case para especificar os comandos referentes a cada uma das opes.

12

imagem=`kdialog --getopenfilename "/home/kurumin/" "*.png *.gif *.jpg *.bmp |Arquivos de Imagem"` operacao=`kdialog --menu "O que voc gostaria de fazer?" a "Redimensionar a imagem" b "Girar a imagem" c "Deletar a imagem" d "Converter para outro formato"` case $operacao in a) mv $imagem $imagem-OLD; tamanho=`kdialog --inputbox "Redimensionar para qual tamanho?" "640x480"`; convert -size $tamanho "$imagem"-OLD $imagem ;; b) jpegorient +90 $imagem ;; c) rm -f $imagem ;; d) formato=`kdialog --inputbox "Converter a imagem para qual formato?" ".jpg"`; convert $imagem "`echo $imagem | perl -pe 's/\.[^.]+$//'`$formato" ;; *) kdialog -- msgbox "Cancelado" ;; esac Este script usa um pouco de cada coisa que j aprendemos, junto com algumas coisas novas. O convert permite realizar vrias operaes com imagens via linha de comando, ideal para uso em scripts. Ele possui muitas opes, que voc pode ver no manual (man convert). Na opo d usei uma funo em perl, que copiei do script de um dos servicemenus do Konqueror, o: /usr/share/apps/konqueror/servicemenus/imageconverter.desktop Lembre-se que a melhor fonte de aprendizado e pesquisa para desenvolver scripts so justamente outros scripts. A opo --combobox similar, mas as opes so mostradas dentro de uma caixa de seleo. A sintaxe tambm muda. Ao invs de especificar as opes, a, b, c, d. etc. voc pode especificar diretamente as opes: $ operacao=`kdialog --combobox "O que deseja fazer?" "girar" "redimensionar" "deletar" "converter"`

A terceira opo, --checklist permite que seja escolhida mais de uma opo, ideal para fornecer um menu de alternativas que no conflitam entre s e podem ser escolhidas simultaneamente: $ fazer=`kdialog --checklist "O que gostaria de fazer?" 1 "Instalar o programa" off 2 "Ler o manual" on 3 "Ler o Wiki" off`

A varivel $fazer vai armazenar uma linha contendo todas as opes selecionadas. Marcando as opes 2 e 3 como no screenshot, ela assume o valor: "2" "3" Um ltimo exemplo, tambm til, a opo --textbox, que exibe arquivos de texto. Ela diferente de abrir o arquivo dentro do kedit por exemplo pois no permite editar, apenas ler. Serve como um "extrato para simples conferncia". Voc pode us-lo tambm para exibir a sada de comandos de modo texto, como por exemplo o ifconfig, que mostra as configuraes da rede. Diferente das outras opes do kdialog, voc deve especificar tambm as dimenses da janela: ifconfig > /tmp/ifconfig.txt kdialog --textbox /tmp/ifconfig.txt 500 320

13

Controlando aplicativos via DCOP


Dentro do KDE voc pode utilizar mais um recurso interessante, o DCOP. Ele permite que o script envie sinais para os programas grficos abertos. Por exemplo, para abrir o kmix e logo em seguida minimiz-lo ao lado do relgio voc pode usar o comando: $ kmix & $ dcop kmix kmix-mainwindow#1 hide O dcop oferece muitas funes, com o tempo voc acaba decorando as mais usadas, mas no incio a melhor forma de aprender ir vendo e testando as opes disponveis. Abra o aplicativo que deseja controlar e rode o comando: dcop, sem argumentos. Ele mostrar uma lista dos programas do KDE, que suportam chamadas que esto abertos: $ dcop kwin kicker kded kmix knotify kio_uiserver kcookiejar konsole-16265 klauncher konqueror-21806 khotkeys kopete kdesktop ksmserver Veja que alguns aplicativos, como o konqueror e o konsole aparecem com nmeros ao lado. Estes so os aplicativos que podem ser abertos vrias vezes, os nmeros servem para identificar cada instncia. Usar funes do dcop para eles um pouco mais complicado, pois cada vez que so abertos usam um nmero diferente. Nestes casos uso um "filtro" para obter o nome da primeira instncia, seja qual for o nmero de identificao e coloc-lo numa varivel que posso usar depois: konqueror-dcop=`dcop | grep konqueror | head -n 1` Executando o comando dentro do script, acabo com o valor "konqueror-21806", a identificao do konqueror atual carregada dentro da varivel. Para ver uma lista das opes disponveis para o aplicativo, rode o comando dcop seguido do aplicativo, como em:

14

$ dcop $konqueror-dcop qt KBookmarkManager-/home/kurumin/.kde/share/apps/konqueror/bookmarks.xml KBookmarkNotifier KDebug KIO::Scheduler KonqFavIconMgr KonqHistoryManager KonqUndoManager KonquerorIface (default) MainApplication-Interface html-widget1 html-widget2 html-widget3 konqueror-mainwindow#1 ksycoca Cada uma destas opes possui uma lista de funes. Por exemplo, a opo konqueror-mainwindow#1 controla a janela principal do konqueror. Para ver as funes relacionadas a ela, rode um: $ dcop $konqueror-dcop konqueror-mainwindow#1 Este comando retorna uma longa lista de opes. Voc pode fazer de tudo, desde esconder a janela at mudar a fonte, ttulo, pgina exibida ou cone na barra de tarefas. Algumas opes bsicas so: $ dcop $konquerordcop konqueror-mainwindow#1 maximize $ dcop $konquerordcop konqueror-mainwindow#1 minimize $ dcop $konquerordcop konqueror-mainwindow#1 hide $ dcop $konquerordcop konqueror-mainwindow#1 reload $ dcop $konquerordcop konqueror-mainwindow#1 show Este exemplo parece complicado, mas a maioria dos aplicativos suporta a opo "default" que permite que voc v direto funo desejada. Por exemplo, para fazer o kmail aberto baixar novas mensagens use o comando: $ dcop kmail default checkMail

Criando interfaces no Kommander


O Kommander permite criar interfaces grficas para shell scripts, usando a biblioteca Qt do KDE. Ele dividido em duas partes, o kmdr-editor o editor que permite criar as interfaces, enquanto o kmdr-executor executa os arquivos gerados por ele. Ao instalar o pacote do Kommander voc obtm os dois componentes. Nas distribuies derivadas do Debian voc pode instala-lo com um "apt-get install kommander". Pacotes rpm para vrias distribuies podem ser encontrados no http://www.rpmfind.net/ Em ltimo caso, voc pode baixar uma verso genrica no: http://kde-apps.org/content/show.php?content=12865 A interface do kmdr-editor lembra um pouco a do VB ou Delphi, mas mais simples por conter muito menos funes. Lembre-se que o objetivo do kommander desenvolver interfaces para scripts, ele prov poucas funes por s s. Ao criar um novo projeto, no Arquivo > Novo voc tem a opo de criar um dilogo ou um assistente. Um dilogo cria uma interface simples, com botes e abas, do tipo onde voc escolhe entre um conjunto de opes e clica no Ok para acionar o script. J o assistente permite criar uma seqncia de telas interligadas, til para criar programas de instalao por exemplo. Os arquivos gerados no kmdr-editor no so binrios, mas sim arquivos em xml, que so interpretados e executados pelo kmdr-executor. Estes arquivos contm os "fontes" da interface. No possvel criar diretamente um binrio atravs do kommander, sempre necessrio ter o kmdr-executor para executar os arquivos xml. Voc pode ver os fontes do Painel de Controle do Kurumin, junto com outros painis que desenvolvi usando o Kommander dentro da pasta /etc/Painel no Kurumin. Vamos a um exemplo rpido. Que tal criar uma interface mais amigvel para aquele script para gravar programas de TV que havamos criado usando o kdialog? Usando o kommander poderamos criar uma interface muito mais elaborada e profissional para ele. Abra o kmdr-editor e crie um dilogo:

15

Vou criar um script simples, com um conjunto de opes para escolher o canal, tempo de gravao e o arquivo que ser criado, que armazenaro as informaes em um conjunto de variveis e um boto que executa o script principal, montando o comando do mencoder. Para dificultar um pouco, vou acrescentar mais uma opo, que permite escolher a qualidade da gravao. Para as opes de escolha do canal e tempo de gravao, vou usar o widget "Line Edit", que cria uma linha editvel. Vou usar dois, um para cada opo, junto com dois "TextLabel", duas legendas simples em texto. Voc pode escolher o texto padro das opes dando um duplo clique sobre elas. Na janela de propriedades voc pode configurar opes como o tipo e tamanho das fontes, cores, alinhamento do texto, etc. Estas opes mudam de acordo com o widget usado. Por enquanto no estou me preocupando com o visual, apenas em adicionar as opes. mais fcil se preocupar primeiro com a parte tcnica e deixar para cuidar da parte visual depois que o script estiver funcionando.

16

O texto dentro das duas caixas precisa ser armazenado em variveis para que possamos utiliz-los mais tarde dentro do script principal. Para que isso acontea, clique com o boto direito sobre cada uma das caixas e acesse a opo "Edit Text Associations". No campo, digite "@widgetText".

Isso faz com que o kommander crie uma varivel contendo o texto digitado dentro da caixa. Esta varivel tem o mesmo nome do widget, nome este que voc escolhe nas propriedades. Para facilitar a minha vida depois, vou nomear as duas caixas como "canal" e tempo", indicando exatamente o que ambas fazem:

17

preciso incluir tambm um widget para salvar o arquivo. O Kommander oferece uma funo bem similar ao --getsavefilename do kdialog, o widget "File Selector". Adicione um no programa, como fizemos com as duas caixas de texto. O File Selector pode ser usado para abrir um arquivo, escolher uma pasta ou salvar um arquivo. Precisamos indicar a funo do nosso nas propriedades. Para isso, configure a opo "selectionType" como "Save" (indicando que a janela servir para salvar um arquivo). Veja que aproveitei tambm para configurar a opo "selectionFilter" como "*.avi *.mpg *.wmf", que faz com que a janela do gerenciador de arquivos mostre apenas arquivos de vdeo, com as trs extenses expecificadas e salve os arquivos com a exteno .avi, mesmo que o usurio no especifique a extenso. A opo "selectionCaption" permite escolher o ttulo da janela para salvar.

No se esquea de configurar a opo "Edit Text Associations" do widget como "@widgetTex" como fizemos com as duas caixas de texto e escolher um nome nas propriedades. No meu caso deixei o nome como "arquivo". Voc pode ver um preview da interface que est editando clicando no Visualizao > Preview Form. Isto perfeito para ir testando cada opo conforme for adicionando, sem deixar que os erros se acumulem. Falta incluir a opo para escolher a qualidade de gravao, dois parmetros que podem ser especificados na linha de comando do mencoder. Vou criar dois botes separados, uma para escolher a resoluo do vdeo (640x480 ou 320x240) e escolher o bitrate, que determina a qualidade e tamanho final do arquivo. No caso da resoluo vou oferecer apenas duas opes, por isso vou usar o widget "RadioButton", criando dois botes. Estes botes precisam ser exclusivos, ou seja, apenas um deles pode ser selecionado de cada vez. Para isso, vou precisar coloc-los dentro de um "ButtonGroup", outro widget, que permite agrupar vrios botes, para faz-los se comportarem da forma desejada. Isto j vai envolver um nmero maior de passos. Primeiro crie o ButtonGroup do tamanho desejado e coloque dois botes dentro dele. Nas propriedades, escolha nomes para os trs. No meu caso coloquei "resolucao" (para o ButtonGroup), resoluao1 e resolucao2 para os botes. Nas propriedades do ButtonGroup, configure a opo "RadioButtonExclusive" como "Verdadeiro". Isso faz com que apenas um dos botes dentro dele possa ser marcado de cada vez. Dentro das propriedades do primeiro boto, deixe a opo "Checked" como "Verdadeiro". Isso faz com que ele fique marcado por padro. Lembre-se que ao desenvolver uma interface importante fazer com que todas as opes sempre tenham algum valor padro, isso diminui a possibilidade de erros por parte do usurio, j que o script vai funcionar mesmo que ele no configure todas as opes.

18

Falta agora configurar o "Edit Text Associations" dos dois botes, para armazenar o contedo da varivel que ser criada caso cada um deles seja pressionado. Desta vez no vou usar o "@WidgetText" pois os botes no contm texto algum. Vou indicar manualmente um valor padro para cada um dos dois botes. Um deles conter o valor "width=640:height=480" e o outro ter o valor "width=320:height=240", que so as opes que poder ser includas na linha de comando do mencoder que ser criada ao executar o programa. Lembre-se que apenas um dos dois botes pode ser marcado de cada vez, por isso apenas uma das duas opes ser usada.

Os dois botes esto dentro do ButtonGroup e apenas um deles pode ser marcado de cada vez. O valor da vriavel do ButtonGroup ("resolucao" no meu caso) passa a ser o valor padro do boto que for selecionado. Ou seja, se for marcado o primeiro boto, a varivel "resolucao" receber o valor "width=640:height=480". Para que isso funcione, preciso configurar o "Edit Text Associations" do ButtonGroup como "@widgetTex". Na hora de usar a varivel, uso a varivel "resolucao", correspondente ao ButtonGroup e no as variveis dos botes. Esta a moral da histria de usar o ButtonGroup ao invs de botes isolados. Voc pode colocar vrios botes dentro dele, fazer com que apenas um boto possa ser clicado de cada vez, determinar um valor padro para cada boto e fazer com que a varivel do ButtonGroup contenha apenas o valor do boto que foi selecionado. Para escolher o bitrate que ser usado ao gerar o arquivo, vou usar um "SpinBoxInt", um widget que cria uma caixa onde voc pode escolher um valor numrico usando duas setas. Nas propriedades, voc escolhe um valor mximo, um valor mnimo, um valor padro e o "lineStep", que determina quanto o nmero aumenta ou diminui cada vez que um dos botes pressionado. No "Edit Text Associations" do SpinBox, coloque "@widgetTex", como sempre. Isso faz com que a varivel contenha o nmero escolhido. No se esquea de escolher um nome para ele nas propriedades. No meu caso escolhi "bitrate". Para melhorar o visual, coloquei o SpinBox dentro de um "GroupBox", que cria um quadrado, similar ao ButtonGroup, mas com funo puramente esttica.

19
Como disse acima, o bitrate determina a qualidade do vdeo gerado, especificando o nmero de kbits que sero reservados para cada segundo de vdeo. Um bitrate de 1500 kbits gera arquivos com cerca de 11 MB por minuto de vdeo, quase 700 MB por hora. O tamanho do arquivo aumenta ou diminui proporcionalmente de acordo com o bitrate. Um bitrate muito alto resultaria num arquivo gigantesco e um muito baixo resultaria num arquivo tosco, com uma qualidade muito ruim. Por isso usamos o SpinboxInt para determinar uma margem de valores razoveis. Voc poderia adicionar mais um SpinBoxInt para oferecer tambm a opo de alterar o bitrate do som, mas no meu caso no vou incluir isto, por o som compactado em MP3 representa uma percentagem pequena do tamanho do arquivo. Depois dessa trabalheira toda, temos as variveis: canal, tempo, arquivo, resolucao e bitrate, que usaremos para gerar a linha de comando. Precisamos agora de um gatilho, um boto que executa o comando final. Vamos usar um simples "ExecButton". Dentro do "Edit Text Associations" do boto, vo as linhas: verificador="@arquivo" if [ -z "$verificador" ]; then kdialog --msgbox "Voc esqueceu de indicar o arquivo onde o vdeo ser salvo ;-)" exit 0 fi kdialog --title "Gravando" --passivepopup "Gravando o canal $var1 por: @tempo horas no arquivo: @arquivo Feche a janela de terminal para abortar" 6 & xterm -e "mencoder tv:// -tv driver=v4l2:input=0:normid=4:channel=@canal:chanlist=us-bcast: @resolucao:device=/dev/video0:adevice=/dev/dsp0:audiorate=48000: forceaudio:forcechan=2:buffersize=64 -quiet -oac mp3lame -lameopts preset=medium -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=@bitrate:keyint=132 -vop pp=lb -endpos @tempo -o @arquivo " kdialog --title "Gravar-TV" --passivepopup "Ok! A gravao terminou." 5 & Veja que so os mesmos comandos que usamos no primeiro script, foi precisa apenas adaptar o uso das variveis. Num script em shell normal as variveis so identificadas por um dlar, "$", enquanto as variveis criadas atravs da interface no Kommander so identificadas por uma arroba, "@". A funo que acrescentei no incio do arquivo verifica se foi escolhido o arquivo onde salvar o arquivo, a varivel "@arquivo" do Kommander. As funes condicionais do bash (if, case, etc.) no entendem as variveis do Kommander diretamente, por isso precisei primeiro criar a varivel "verificador", com o contedo da varivel @arquivo do Kommander. O "-z" um comparador, significa " nula", ou seja, ela serve para verificar se a varivel est vazia. Caso esteja, exibida uma mensagem na tela e o script fechado, graas ao "exit 0". Como o script executado pela janela principal do Kommander, o script fecha, mas a janela principal continua aberta.

20

Voc pode usar funes do Kdialog, funes lgicas e outros comandos que usaria num script tradicional. O Kommander apenas acrescenta algumas possibilidades novas. Depois de revisar tudo, voc pode finalmente testar o programa, executando-o no kmdr-executor: $ kmdr-executor gravar-tv.kmdr A segunda parte do trabalho envolve dar uma melhorada no aspecto visual. Voc pode acrescentar imagens e cones usando o widget "PixmapLabel". Os cones do sistema vo por padro dentro da pasta /usr/share/icons, e so um bom ponto de partida. Voc pode usar tambm imagens e cones personalizados, salvos em .png. Todas as imagens usadas so salvas como parte do arquivo, como se fosse um documento do OpenOffice, voc no precisa se preocupar em distribuir as imagens junto com o programa, a nica dependncia o kmdr-executor, junto com os comandos usados dentro do script A maioria dos widgets, como as etiquetas de texto, caixas, etc. Possuem vrias opes de cores e fontes dentro das propriedades, que permitem fazer um bom trabalho. Esta a verso final do script, que desenvolvi para uso no Kurumin:

Outro recurso interessante do Kommander e vem sendo melhorado rapidamente nas novas verses so as conexes. Elas permitem adicionar elementos dinmicos na interface, um textLabel cujo contedo muda quando voc clica num boto ou mostra informaes sobre um arquivo escolhido num File Selector e assim por diante. As conexes ainda so um recurso incipiente, a cada nova verso do Kommander muita coisa muita, novas opes so adicionadas, etc. Por isso, vou dar apenas uma introduo e deixar para explicar com mais profundidade numa futura atualizao deste texto. Para seguir este exemplo, voc precisa estar usando o Kommander 1.0 Final ou mais recente.

21
Vamos usar algumas conexes para criar um editor de imagens primitivo. Comece criando um novo projeto e desenhe uma interface contendo um FileSelector, um textLabel, um PixmapLabel e quatro botes que usaremos para adicionar algumas funes de edio. Por enquanto no inclu cdigo algum, apenas desenhei os widgets

O objetivo fazer com que o arquivo de imagem escolhido no FileSelector seja exibido no PixmapLabel, ao mesmo tempo em que a localizao e nomes completos do arquivo so mostrados no textLabel. As duas coisas atualizadas automaticamente, sem que seja necessrio pressionar nenhum boto. Os botes vo conter mais algumas funes estticas para deletar a imagem, girar e limpar os dois campos (novamente usando conexes). Vamos comear fazendo com que a imagem seja exibida no PixmapLabel. Procure a ferramenta de conexo na interface principal. Clique primeiro sobre o FileSelector e arraste at o PixmapLabel. Isso cria uma conexo entre eles

Na janela de propriedades que ser aberta, voc ver duas janelas, uma com os sinais disponveis no FileSelector e do outro lado as propriedades do PixmapLabel que podem ser alteradas atravs deles. Marque a opo "widgetTextChanged(const QString)" do lado do FileSelector e a opo "setWidgetText(const QString)" do lado do PixmapLabel. Clique no "Conectar" para efetivar a conexo:

22

O que fizemos aqui foi especificar que quando o texto dentro do FileSelector for mudado (ou seja, quando for escolhido algum arquivo) o contedo do PixmapLabel muda, exibindo o contedo do arquivo. Se fosse uma caixa de texto, seria mostrado o contedo do arquivo na forma de texto, mas como estamos usando uma caixa de imagem, ser mostrado um preview da imagem. Crie agora uma nova conexo, ligando o FileSelector e o textLabel. Na janela de propriedades, marque a opo "widgetTextChanged(const QString)" para o FileSelector (o mesmo do passo anterior) e a opo "Populate()" para o textLabel.

O textLabel est originalmente vazio, sem contedo algum. A funo Populate vai "popul-lo" (piadinha infame :-P) com o resultado de um comando que definiremos no passo a seguir. Isso disparado sempre que o contedo do FileSelector muda. Sempre que escolhido um arquivo diferente, o comando executado novamente e o contedo do textLabel muda.

23
Para definir o comando, clique com o boto direito sobre o textLabel e acesse a opo "Editar texto do Kommander". Dentro da janela, acesse a opo "Texto para: Population" que est no canto superior direito.

O comando comea com "@exec" com o comando propriamente dito entre parnteses. Dentro dos parnteses voc pode separar uma seqncia de comandos por ponto e vrgula, usar o pipe e outros componentes de um shell script normal. Neste exemplo, estou usando o comando: @exec(identify "@arquivo.text" | cut -d " " -f 2-10) O identify um comando de texto que exibe as propriedades da imagem, como formato e resoluo. Nas propriedades do meu FileSelector mudei o nome para "arquivo", logo o @arquivo.text se refere ao contedo do FileSelector, ou seja, o nome do arquivo que foi escolhido. O "| cut -d " " -f 2-10" opcional, ele serve apenas para "limpar" a sada do identify, retirando o nome do arquivo. Salve o arquivo e clique no Executar > Executar dilogo para ver um preview dele funcionando. Veja que ao escolher um arquivo de imagem no FileSelector a imagem realmente exibida no PixmapLabel, enquanto o textLabel mostra as informaes fornecidas pelo identify

Apesar disso, ainda existe um pequeno bug, est sendo exibido apenas um pedao da imagem. Para que seja exibido um preview reduzido da imagem, acesse as propriedades do PixmapLabel e mude a opo "scaledContents" para verdadeiro (true). A partir da a imagem passa a ser redimensionada corretamente.

24

Falta agora s dar funes aos botes de edio, que a parte mais fcil. Dentro do boto "Deletar a imagem" (boto direito > Editor texto do Kommander) inclua a funo: kdialog --yesno "Tem certeza?" retval=$? if [ "$retval" = "0" ]; then rm -f @arquivo.text fi Nos botes Girar no sentido horrio e girar no sentido anti-horrio, inclua (respectivamente) as funes: jpegorient +90 @arquivo.text jpegorient +270 @arquivo.text O jpegorient mais um comando de edio de imagem em modo texto, que faz parte do imageMagik. Ele permite justamente girar a imagem no sentido desejado, muito usado em scripts. O ltimo boto, Limpar, vai servir apenas para limpar o contedo do PixmapLabel e do textLabel. Para isso, crie uma conexo entre o boto e o PixmapLabel. Marque de um lado a opo "Pressed" e do outro a opo "clear()". Faa o mesmo entre ele e o textLabel.

Nosso programinha est quase pronto, existe apenas um ltimo "bug": ao clicar nos botes de girar, a imagem alterada, mas no automaticamente atualizada na janela do programa. Se voc for perfeccionista e quiser resolver isso, crie uma conexo entre cada um dos dois botes de girar e o PixmapLabel. Marque a opo "Pressed()" para o boto e "Populate()" para o PixmapLabel.

25

Acesse agora as propriedades do PixmapLabel e, dentro do "Texto para: Population" coloque "@arquivo.text". Isso far com que cada vez que um dos dois botes for pressionado, a nova conexo dispare uma atualizao da imagem:

Voc pode baixar o arquivo do programa pronto (5 KB) aqui: http://www.guiadohardware.net/kurumin/Painel/exemplo2.kmdr O manual oficial do Kommander est disponvel no: http://www.kde.me.uk/kommander-tutorial/kommander-docs-html/ Este artigo do Linux.com contm vrias dicas e exemplos: http://applications.linux.com/applications/04/12/17/2033227.shtml?tid=49&tid=26&tid=47

Usando os servicemenus do KDE


Mais uma aplicao interessante para os shell scripts so os menus de contexto do KDE, que aparecem ao clicar com o boto direito sobre os arquivos e pastas. Uma determinada operao pode aparecer para todos os arquivos, todas as pastas, ou apenas para alguns formatos de arquivos especficos. Ao clicar sobre uma pasta, voc tem a opo de criar um CD de dados no K3B, ao clicar num arquivo .zip voc tem a opo de descompacta-lo, e assim por diante. Voc pode adicionar servicemenus para todo tipo de tarefa.

26

Os scripts dos servicemenus vo na pasta: /usr/share/apps/konqueror/servicemenus

Todos os arquivos dentro da pasta so scripts, que seguem um padro prprio, comeando pelo nome, que deve sempre terminar com ".desktop". Por exemplo, o servicemenu responsvel por "Acessar arquivos dentro do ISO" aparece apenas ao clicar sobre um arquivo com a extenso .iso. O arquivo "montar-iso.desktop" tem o seguinte contedo: [Desktop Entry] Actions=montar Encoding=UTF-8 ServiceTypes=application/x-iso [Desktop Action montar] Exec=acessar-iso-servicemenu %U Icon=cdrom_unmount Name=Acessar arquivos dentro do ISO A linha "ServiceTypes=application/x-iso" importante neste caso, pois nela que voc especifica a que tipos de arquivos o servicemenu se destina. por isso que eles tambm so chamados em Portugus de "Menus de contexto", pois so mostradas opes diferentes para cada tipo de arquivo. Voc pode ver todos os formatos de arquivos reconhecidos pela sua instalao do KDE, e adicionar novas extenses caso necessrio no Painel de Controle do KDE, em Componentes do KDE > Associaes de arquivos.

27

Veja que no incio do script voc especifica as aes disponveis no parmetro "Actions". Mais adiante, voc cria uma seo para cada ao especificada contendo o nome (da forma como aparecer no menu) cone e o comando que ser executado ao acionar a ao no menu. Neste exemplo executado o comando "acessar-iso-servicemenu %U". O "%U" uma varivel, que contm o nome do arquivo clicado. Este parmetro pode ser usado apenas nos scripts dos servicemenus, no em scripts regulares. O "acessar-iso-servicemenu" um script separado, que pode ir em qualquer uma das pastas de executveis do sistema: /usr/local/bin/ usr/bin/, /bin, ou outras pastas adicionadas manualmente no patch. Este script contm os arquivos para montar o arquivo ISO numa pasta e abrir uma janela do Konqueror mostrando o contedo. Ao fechar a janela do Konqueror, o arquivo desmontado, para evitar problemas casa o usurio tente montar vrios arquivos ISO em seqncia: #!/bin/sh kdesu "mkdir /mnt/iso; umount /mnt/iso; mount -t iso9660 -o loop $1 /mnt/iso" clear konqueror /mnt/iso kdesu umount /mnt/iso

O kdesu um componente do KDE que permite executar comandos como root. Ao executar um "kdesu konqueror" por exemplo, ele pede a senha de root numa janela e depois executa o comando, abrindo uma janela do Konqueror com permisses de root. Voc pode executar uma seqncia de comandos dentro de uma nica instncia do kdesu (para que ele pea a senha apenas uma vez), colocando os comandos entre aspas, separados por ponto e vrgula, como no exemplo. Note que neste segundo script no uso a varivel "%U" (que pode ser usada apenas dentro do script do servicemenu) mas sim a varivel "$1". Quando voc executa um comando qualquer, via linha de comando, a varivel "$1" o primeiro parmetro, colocado depois do comando em s. Para entender melhor, vamos criar um script "teste", com o seguinte contedo: #!/bin/sh echo $1 echo $2 echo $3

28

Execute o script, incluindo alguns parmetros e voc ver que ele vai justamente repetir todos os parmetros que incluir.

Quando clicamos sobre um arquivo chamado "kurumin.iso" e acionamos o servicemenu, a varivel "%U" contm o nome do arquivo. O servicemenu por sua vez chama o segundo script, adicionando o nome do arquivo depois do comando, o que automaticamente faz com que a varivel "$1" tambm contenha o nome do arquivo. Ou seja, as variveis "%U" e "$1" neste caso vo sempre possuir o mesmo contedo, muda apenas o contexto em que so usadas. Voc pode usar este tipo de troca de parmetro para desmembrar seus scripts, criando "mdulos" que possam ser usados em outros scripts. Por exemplo, os cones mgicos do Kurumin utilizam o sudo para executar comandos como root (como por exemplo usar o apt-get para instalar um programa) sem ficar pedindo a senha de root a todo instante. O sudo pode ser ativado e desativado a qualquer momento, fornecendo a senha de root, de forma que voc pode mant-lo desativado, e ativar apenas ao executar algum script que precisa deles. Para que isso funcione, os scripts sempre executam uma funo, que verifica se o sudo est ativado. Caso esteja eles so executados diretamente, sem pedir senha, caso contrrio eles pedem a senha de root. Isto foi implementado incluindo esta funo no incio de cada script: sudo-verificar if [ "$?" = "2" ]; then exit 0; fi O script "sudo-verificar", chamado por eles, tem o seguinte contedo: #!/bin/sh # Script para ser usado por scripts que utilizam o sudo. # Por Carlos E. Morimoto sudoativo=`sudo whoami` if [ "$sudoativo" != "root" ]; then kdialog --warningyesno "O script que voc executou precisa utilizar o sudo para executar alteraes no sistema. Atualmente o Kurumin est operando em modo seguro, com o sudo desativado para o usurio atual. Voc gostaria de mudar para o modo root, ativando o sudo? Para isso ser necessrio fornecer a senha de root. Caso prefira abortar a instalao, responda No. Voc pode tambm executar o script desejado diretamente como root." retval=$? if [ "$retval" = "0" ] then sudo-ativar fi if [ "$retval" = "1" ] then exit 2 fi fi Este script verifica se o sudo est ativo usando o comando "whoami" que retorna o nome do usurio que o chamou. Caso o sudo esteja ativo, ento o "sudo whoami" executado pelo root e retorna "root". uma estratgia simples, mas que funciona. Caso o retorno no seja "root", significa que o sudo est desativado, o que dispara a pergunta. Respondendo "sim" ele executa o script "sudo-ativar", que pede a senha de root. Caso seja respondido "no" ou caso a janela com a pergunta seja fechada, ele roda o comando "exit 2".

29
O comando "exit" usado para terminar o script. Voc pode incluir um parmetro depois do exit, (no nosso caso o "2") que um status de sada, repassado ao primeiro script. Isto permite que os scripts "conversem". Como vimos, depois de chamar o "sudo-verificar", o primeiro script verifica o status de sada do comando "sudoverificar", usando a funo: "if [ "$?" = "2" ]; then exit 0; fi". Ou seja, se o status de sada do sudo-verificar for "2", o que significa que o sudo est desativado e o usurio no quis fornecer a senha de root, ento o primeiro script roda o comando "exit" e tambm finalizado. Ok, demos uma grande volta agora. Mas, voltando aos servicemenus, possvel incluir vrias aes dentro de um mesmo script, que se aplicam a um mesmo tipo de arquivo. Voc pode por exemplo adicionar uma opo de redimensionar imagens, colocando vrias opes de tamanho, ou uma opo para converter arquivos de udio para vrios outros formatos. Este um exemplo de script com vrias aes, que permite redimensionar imagens: [Desktop Entry] ServiceTypes=image/* Actions=resize75;resize66;resize50;resize33;resize25; X-KDE-Submenu=Redimensionar a imagem [Desktop Action resize75] Name=Redimensionar para 75% do tamanho original Icon=thumbnail Exec=img-resize 75 %u [Desktop Action resize66] Name=Redimensionar para 66% do tamanho original Icon=thumbnail Exec=img-resize 66 %u [Desktop Action resize50] Name=Redimensionar para 50% do tamanho original Icon=thumbnail Exec=img-resize 50 %u [Desktop Action resize33] Name=Redimensionar para 33% do tamanho original Icon=thumbnail Exec=img-resize 33 %u [Desktop Action resize25] Name=Redimensionar para 25% do tamanho original Icon=thumbnail Exec=img-resize 25 %u Veja que nas primeiras linhas necessrio especificar que ele s se aplica a imagens (ServiceTypes=image/*) e depois especificar todas as aes disponveis, adicionando uma seo para cada uma mais adiante. No existe limite para o nmero de aes que podem ser adicionadas neste caso, s depende da sua pacincia :)

Como no exemplo anterior, este script chama um script externo, o "img-resize" para executar as operaes. Ele um script simples, que usa o "convert" (que vimos ao estudar sobre o Kommander) para fazer as converses:

30
#!/bin/sh echo "Convertendo $2 para $1% do tamanho original." echo "Backup da imagem original salvo em: $2.original" cp $2 $2.original convert -quality 90 -sample $1%x$1% $2 $2-out rm -f $2 mv $2-out $2 sleep 1 echo "Ok!" Os parmetros "$1" e "$2" so recebidos do script do servicemenu. O $1 a percentagem de redimensionamento da imagem, enquanto o $2 o nome do arquivo. Voc pode ainda chamar funes de aplicativos do KDE dentro dos servicemuenus, usando funes do dcop, que estudamos anteriormente. Este o script do servicemenu que permite adicionar arquivos playlist do Kaffeine: [Desktop Entry] ServiceTypes=all/all Actions=kaffeine_append_file Encoding=UTF8 [Desktop Action kaffeine_append_file] Name=Append to Kaffeine Playlist Name[hu]=Felvtel a Kaffeine Lejtszlistba Name[de]=Zur Kaffeine Stckliste hinzufgen Name[sv]=Lgg till i Kaffeine spellista Exec=dcop kaffeine KaffeineIface appendURL %u Icon=kaffeine Veja que ele usa a funo " dcop kaffeine KaffeineIface appendURL %u" para contatar o Kaffeine e instru-lo a adicionar o arquivo na playlist. Os servicemenus podem ser internacionalizados, com tradues das legendas para vrias lnguas. Para adicionar a traduo para o Portugus neste servicemenu do Kaffeine, basta adicionar a linha "Name[pt_BR]=Adicionar na Playlist do Kaffeine" Para que a opo seja exibida apenas apenas ao clicar sobre arquivos de vdeo, e no mais sobre qualquer arquivo, substitua a linha "ServiceTypes=all/all" por "ServiceTypes=video/*"

Detectando Hardware
A forma como o suporte a dispositivos no Linux implementado atravs de mdulos, combinada com ferramentas como o pciutils (includo por padro em todas as distribuies) facilitam bastante as coisas para quem escreve ferramentas de deteco. Hoje em dia, quase todas as distribuies detectam o hardware da mquina durante a instalao ou durante o boot atravs de ferramentas como o kudzu (do Red Hat), drakconf (do Mandrake) Yast (SuSE) e hwsetup (do Knoppix). Estas ferramentas trabalham usando uma biblioteca com as identificaes dos dispositivos suportados e os mdulos e parmetros necessrios para cada um. A biblioteca com as identificaes de uso comum e faz parte do pacote pciutils. Voc pode checar os dispositivos instalados atravs dos comandos lspci (para placas PCI e AGP), lsusb e lspnp (para placas ISA com suporte a plug-andplay): kurumin@kurumin:/$ lspci 0000:00:00.0 Host bridge: Intel Corp. 82852/82855 GM/GME/PM/GMV Processor to I/O Controller (rev 02) 0000:00:00.1 System peripheral: Intel Corp. 82852/82855 GM/GME/PM/GMV Processor to I/O Controller (rev 02) 0000:00:00.3 System peripheral: Intel Corp. 82852/82855 GM/GME/PM/GMV Processor to I/O Controller (rev 02) 0000:00:02.0 VGA compatible controller: Intel Corp. 82852/855GM Integrated Graphics Device (rev 02) 0000:00:02.1 Display controller: Intel Corp. 82852/855GM Integrated Graphics Device (rev 02) 0000:00:1d.0 USB Controller: Intel Corp. 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (rev 03) 0000:00:1d.7 USB Controller: Intel Corp. 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 03) 0000:00:1e.0 PCI bridge: Intel Corp. 82801 Mobile PCI Bridge (rev 83) 0000:00:1f.0 ISA bridge: Intel Corp. 82801DBM (ICH4-M) LPC Interface Bridge (rev 03)

31
0000:00:1f.1 IDE interface: Intel Corp. 82801DBM (ICH4-M) IDE Controller (rev 03) 0000:00:1f.5 Multimedia audio controller: Intel Corp. 82801DB/DBL/DBM AC'97 Audio Controller (rev 03) 0000:00:1f.6 Modem: Intel Corp. 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (rev 03) 0000:01:08.0 Ethernet controller: Intel Corp. 82801DB PRO/100 VE (MOB) Ethernet Controller (rev 83) 0000:01:0b.0 CardBus bridge: Toshiba America Info Systems ToPIC100 PCI to Cardbus Bridge with ZV Support (rev 33) kurumin@kurumin:/$ lsusb Bus 002 Device 001: ID 0000:0000 Bus 001 Device 008: ID 0566:3001 Monterey International Corp. Bus 001 Device 007: ID 0566:1001 Monterey International Corp. Bus 001 Device 006: ID 058f:9254 Alcor Micro Corp. Hub Bus 001 Device 001: ID 0000:0000 kurumin@kurumin:/$ lspnp lspnp: /proc/bus/pnp not available Os PCs novos no possuem mais suporte a placas ISA, por isso a mensagem de erro ao rodar o "lspnp" no meu caso. Voc pode escrever scripts para detectar automaticamente componentes que no so originalmente detectados, ou para softmodems, placas Wireless e outros mdulos avulsos que tenha instalado manualmente. Isto muito fcil quando voc sabe de antemo qual a sada do comando lspci/lsusb/pspnp referente ao dispositivo e quais so os mdulos e parmetros necessrios para ativ-los. Por exemplo, as placas de vdeo onboard, com chipset Intel precisam que o mdulo "intel-agp" esteja ativo, para que o suporte a 3D no Xfree funcione corretamente. Num micro com uma placa destas, o lspci retorna: 0000:00:02.0 VGA compatible controller: Intel Corp. 82852/855GM Integrated Graphics Device (rev 02) A identificao do modelo muda de acordo com a placa usada, mas o "VGA compatible controller: Intel Corp." no. Um exemplo simples de script para detectar e ativar o mdulo intel-agp caso necessrio poderia ser: intelonboard=`lspci | grep "VGA compatible controller: Intel Corp."` if [ -n "$intelonboard" ]; then modprobe intel-agp fi O grep permite filtrar a sada do comando lspci, mostrando apenas linhas que contenham a string definida. Ou seja, o comando s vai retornar alguma coisa em micros com placas de vdeo Intel. Carregamos a resposta numa varivel. O "if [ -n" permite testar se existe algum valor dentro da varivel (-n = no nulo), sintoma de que uma placa Intel est presente e ento carregar o mdulo apropriado. Outras condicionais que voc usar para testar valores so: -e : Usado para verificar se um arquivo existe, ex: if [ -e "/etc/fstab" ]; then <comandos>; fi -f : similar ao -e, tambm serve para verificar se um arquivo existe, mas ele aceita apenas arquivos normais, deixando de fora links, diretrios e dispositivos. -d : Tambm similar ao -e, serve para verificar se um diretrio existe. -L : Usado para verificar se o arquivo um link simblico apontando para outro arquivo -s : Para testar se o arquivo maior que zero bytes, ou seja, se o arquivo est em branco. -x : Verifica se o arquivo executvel. -ef : EqualFile, permite verificar se dois arquivos so iguais. Ex: if [ "/etc/fstab" -ef "/etc/fstab.bk" ] then <comandos>; fi Voc pode ainda usar o parmetro "-a" (E) para incluir mais de uma condio dentro da mesma funo, como em: if [ "$cdrom1" != "$cdrom2" -a "$cdrom2" != "/etc/sr0" ] ; then <comandos>; fi Aqui os comandos so executados apenas caso a varivel $cdrom1 seja diferente da $cdrom2 E a $cdrom2 no seja "/dev/sr0". Outra possibilidade usar o "-o" (OU) para fazer com que os comandos sejam executados caso qualquer uma das condies seja verdadeira.

Alterando arquivos de configurao


Caso sejam executados pelo root, os scripts podem tambm alterar arquivos de configurao do sistema, alterando

32
linhas existentes ou incluindo novas configuraes. O comando mais usado para fazer substituies o sed. Para simplesmente adicionar linhas no final do arquivo voc pode usar o echo, o mesmo comando que usamos para escrever mensagens na tela. Por exemplo, um erro comum ao acessar parties do Windows formatadas em NTFS a partio ser montada com permisso de leitura apenas para o root. Voc s consegue ver os arquivos abrindo o gerenciador de arquivos como root, o que desconfortvel . Isto acontece por que o default do mount montar parties NTFS e FAT com permisso de acesso apenas para o root. Para que outros usurios possam visualizar os arquivos necessrio montar incluindo a opo "umask=000". A tarefa relativamente simples, basta abrir o arquivo /etc/fstab, e adicionar a opo na linha referente partio. Ao invs de: /dev/hda1 /mnt/hda1 auto noauto,users,exec 0 0 Ficaramos com: /dev/hda1 /mnt/hda1 auto noauto,users,exec,umask=000 0 0 At a tudo bem. O problema que este parmetro pode ser usado apenas em parties FAT ou NTFS. Se voc usar em parties formatadas em ReiserFS ou EXT, elas no montam. Ou seja, ao fazer isso via script, precisamos primeiro ter certeza de que a partio est formatada em NTFS, antes de alterar o /etc/fstab. Uma forma de fazer isto verificando a sada do comando "fdisk -l", que mostra detalhes sobre as parties, como em: # fdisk -l /dev/hda Disk /dev/hda: 20.0 GB, 20003880960 bytes 255 heads, 63 sectors/track, 2432 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/hda1 * 1 401 3221001 7 HPFS/NTFS /dev/hda2 402 1042 5148832+ 83 Linux /dev/hda3 1116 2432 10578802+ 5 Extended /dev/hda4 1043 1115 586372+ 83 Linux /dev/hda5 1116 1164 393561 82 Linux swap / Solaris /dev/hda6 1165 2432 10185178+ 83 Linux Podemos ento usar o grep filtrar a sada e carregar o resultado dentro de uma varivel, de modo que ela contenha alguma coisa apenas caso a partio testada esteja formatada em NTFS, como em: winntfs=`fdisk -l /dev/hda | grep hda1 | grep NTFS` Em seguida viria o comando do sed para alterar a linha no /etc/fstab, caso a parties testada estivesse realmente formatada em NTFS: if [ -n "$winntfs" ]; then # O gigantesco comando abaixo forma uma nica linha: sed -e 's/\/dev\/hda1\ \/mnt\/hda1\ auto\ noauto,users,exec\ 0\ 0/\/dev\/hda1\ \/mnt\/hda1\ auto\ noauto,users,exec,umask=000\ 0\ 0/g' /etc/fstab > /etc/fstab2 rm -f /etc/fstab mv /etc/fstab2 /etc/fstab fi Veja que a linha do sed um pouco longa. A sintaxe bsica para fazer substituies : sed -e 's/texto/novo-texto/g' arquivo > novo-arquivo Ele sempre gera um novo arquivo com as alteraes, por isso depois do comando voc ainda precisa remover o arquivo original e renomear o novo arquivo. Caso dentro da string de texto a substituir existam espaos ou caracteres especiais, use barras intertidas (\) como no exemplo, para demarc-los. As barras invertidas indicam que o caractere seguinte no deve ser interpretado. Este outro exemplo do uso do sed, para fazer as alteraes no arquivo de configurao do X, necessrias depois de instalar o driver da nVidia, que mostra algumas mensagens na tela, explicando o que est sendo feito: sed -e 's/nvidia/nv/g' /etc/X11/XF86Config-4 > /etc/X11/XF86Config-4nv0 sed -e 's/nv/nvidia/g' /etc/X11/XF86Config-4nv0 > /etc/X11/XF86Config-4nv1 echo "Ativando driver: Localizando expressao *nv* e substituindo por *nvidia*"; sleep 1 sed -e 's/fbdev/nvidia/g' /etc/X11/XF86Config-4nv1 > /etc/X11/XF86Config-4nv2

33
echo "Ativando driver: Localizando expressao *fbdev* e substituindo por *nvidia*"; sleep 1 sed -e 's/vesa/nvidia/g' /etc/X11/XF86Config-4nv2 > /etc/X11/XF86Config-4nv3 echo "Ativando driver: Localizando expressao *vesa* e substituindo por *nvidia*"; sleep 1 sed -e '\/Load\ \ "dri"/D' /etc/X11/XF86Config-4nv3 > /etc/X11/XF86Config-4nv4 echo "Ativando driver: Removendo a linha *Load dri*"; sleep 1 sed -e '\/Load\ \ "GLcore"/D' /etc/X11/XF86Config-4nv4 > /etc/X11/XF86Config-4nv5 echo "Ativando driver: Removendo a linha *Load GLcore*"; sleep 1 sed -e '\/Load\ \ "dbe"/D' /etc/X11/XF86Config-4nv5 > /etc/X11/XF86Config-4nv6 echo "Ativando driver: Removendo a linha *Load dbe*"; sleep 1 rm -f /etc/X11/XF86Config-4 mv /etc/X11/XF86Config-4nv7 /etc/X11/XF86Config-4 rm -f /etc/X11/XF86Config-4nv* Voc pode ver mais dicas e exemplos do uso do sed na pgina do Aurlio: http://aurelio.net/sed/

Corrigindo Erros
Quase todos os programas geram uma sada erro caso algo anormal ocorra. Esta sada erro pode ser monitorada pelo script, de forma a corrigir problemas comuns de forma automtica, ou pelo menos, avisar o usurio de que algo de errado ocorreu. Por exemplo, ao gravar o lilo com sucesso, ele exibir uma mensagem como esta: # lilo Added Kurumin * Added memtest86 Caso exista algum erro no arquivo de configurao, ele avisa do problema e por segurana no salva as alteraes: # lilo Added Kurumin * Added memtest86 Fatal: First sector of /dev/hda4 doesn't have a valid boot signature Em alguns casos, um comando que no faz sua parte dentro do script pode causar uma pequena tragdia. Por exemplo, durante a instalao do Kurumin o usurio tem a opo de revisar a configurao do arquivo, visualizando diretamente o arquivo de configurao. Caso alguma coisa d errado, o lilo simplesmente no gravado e o sistema no d boot depois de instalado. Uma forma simples de monitorar a sada de erro usar um "2>>" para direcion-la para um arquivo de texto, que pode ser vasculhado pelo grep em busca de mensagens de erro. O programa de instalao do Kurumin usa a funo abaixo para detectar erros de gravao do lilo:

34

# Toda funo roda dentro de um while, de forma que repetida at que o problema seja # solucionado: while [ "$lilogravado" != "1" ] do clear # Remove o arquivo temporrio usado rm -f /tmp/lilo.txt # Grava o lilo, direcionando a sada de erros para o arquivo de texto. # A varivel "$TR" contm o diretrio onde o sistema est sendo instalado. lilo -t -r $TR 2>> /tmp/lilo.txt # O grep usado para verificar se o arquivo contm a palavra "Fatal", sintoma de que o lilo # no foi gravado: testelilo=`cat /tmp/lilo.txt | grep Fatal` # Caso a palavra seja encontrada, executado o restante do script, que exibe a mensagem # de erro e pede que o usurio edite novamente o arquivo de configurao do lilo. Depois # disso o script executado novamente. if [ -n "$testelilo" ]; then BT="Instalador do Kurumin" M1="Existe um erro no arquivo de configurao do lilo que est impedindo a instalao. Vou abrir novamente o arquivo para que voc possa revis-lo. Procure por erros de digitao e em ultimo caso experimente desfazer as alteraes feitas.\n\n Ao fechar a janela do Kedit, vou tentar gravar o lilo novamente e avisar caso o erro persista. O erro informado :\n\n $testelilo" $DIA --backtitle "$BT" --title "Lilo" --msgbox "$M1" 18 76 kedit $TR/etc/lilo.conf # Quando finalmente o lilo gravado sem erros, a varivel lilogravado assume o valor 1, # encerrando o loop do while. else lilogravado="1" fi done Em alguns casos voc pode querer que o script salve a sada de texto de uma operao para verificar erros, mas ao mesmo tempo mostre a sada normalmente na tela. Voc pode fazer isso usando o comando "tee". Por exemplo, um erro comum ao tentar instalar programas via apt-get a partir do testing ou unstable (onde os pacotes so atualizados com muita freqncia) o apt tentar baixar verses antigas dos pacotes, que no esto mais disponveis. Isso corrigido facilmente rodando o "apt-get update" que baixa a lista com as verses atuais. Mas, nosso script pode detectar este erro e se oferecer para rodar o apt-get automaticamente quando necessrio. Vamos chamar nosso script de "apt-get". Ele vai ser apenas um "wrapper", que vai repassar os comandos para o apt-get "real" que est na pasta /usr/bin. Ou seja, quando voc chamar o "./apt-get install abiword" vai estar usando nosso script, que vai direcionar os parmetros para o apt-get e em seguida verificar se houve o erro:

35

#!/bin/sh rm -f /tmp/apt # Executa o apt-get "real", passando os parmetros recebidos na linha de comando: apt-get $1 $2 | tee /tmp/apt # Verifica se algum pacote no pde ser baixado: erro1=`cat /tmp/apt | grep "404 Not Found"` if [ -n "$erro1" ]; then echo " " echo "Alguns pacotes no puderam ser baixados. Isto significa que" echo "provavelmente a lista de pacotes do apt-get est desatualizada." echo "Gostaria de rodar o apt-get update para atualizar a lista e " echo "repetir a instalao? (S/n)" read resposta if [ "$resposta" = "n" ]; then exit 1 else apt-get update apt-get $1 $2 | tee /tmp/apt # Verifica novamente, caso o erro persista exibe uma segunda mensagem: erro1=`cat /tmp;/apt | grep "404 Not Found"` if [ -n "$erro1" ]; then echo "O erro se repetiu. Isto significa que ou o pacote no est mais" echo "disponvel, o servidor est fora do ar, ou sua conexo com a web" echo "est com problemas. (pressione Enter para sair)" read pausa fi fi fi Ao executar um "./apt-get install abiword", usando nosso script num micro com a lista de pacotes desatualizada, voc ver a mensagem:

A partir da voc poderia ir incluindo mais funes para corrigir outros problemas comuns. Este tipo de script pode ser muito til em migraes, para aparar as arestas nos programas em que os usurios estejam tendo dificuldades, tornando o sistema mais inteligente.

36

Mais exemplos teis


A funo "for" pode ser usada para executar tarefas repetitivas, como por exemplo: for arquivo in *.mp3 do lame -b 64 "$arquivo" "64k-$arquivo" done Isto vai gerar uma cpias de todos os arquivos mp3 da pasta atual encodados com bitrate de 64k, gerando arquivos menores, teis para escutar num MP3 Player com pouca memria por exemplo. Voc pode fazer com que o mesmo comando seja executado vrias vezes, usando uma varivel incremental com o comando "seq", como em: for numero in $(seq 1 10) do touch arquivo$numero.txt done Isto vai fazer com que sejam criados 10 arquivos de texto em branco, numerados de 1 a 10. O comando cut outro recurso muito usado e til. Ele permite "filtrar" a sada de outros comandos, de forma a obter apenas a informao que interessa. Imagine por exemplo que voc precisa descobrir o sistema de arquivos que uma determinada partio do sistema est formatada, de forma a usar a informao mais adiante no script. O comando "mount" mostra todas as parties montadas: $ mount /dev/hda1 on / type reiserfs (rw,noatime) none on /proc type proc (rw,nodiratime) /sys on /sys type sysfs (rw) /dev/hda2 on /home type reiserfs (rw,noatime,notail) /dev/hda3 on /home type ext3 (rw) /dev/hda6 on /mnt/hda6 type reiserfs (rw) Digamos que voc esteja interessado apenas na partio hda2. O grep permite eliminar as outras linhas, deixando apenas a referente a ela. Use um pipe ( | ) depois do mount para direcionar a sada para o grep: $ mount | grep /dev/hda2 /dev/hda2 on /home type reiserfs (rw,noatime,notail) Mas, como queremos apenas o sistema de arquivos em que a partio est formatada, podemos usar mais um pipe para direcionar a sada para o cut, de forma que ele elimine o resto da linha: $ mount | grep /dev/hda2 | cut -d " " -f 5 Reiserfs A opo "-f' permite especificar os campos que sero mostrados, enquanto a opo "-d" permite especificar o separador entre os campos. No exemplo usei um -d " " para especificar que um espao separa cada campo e que quero apenas o quinto campo, que onde est a informao sobre o sistema de arquivos. Da enorme sada do mount, sobra apenas "reiserfs" que a informao que queremos. Voc pode ler sobre as outras opes do cut no: man cut Imagine que voc precisa de um script para listar os usurios cadastrados no sistema. Voc poderia usar o sed para filtrar o contedo do arquivo /etc/shadow, o arquivo que contm a lista de usurios e senhas do sistema.

Um exemplo (reduzido) do contedo deste arquivo seria: # cat /etc/shadow

37
root:RRPHE1yRTfEKo:12840:0:99999:7::: daemon:*:11453:0:99999:7::: bin:*:11453:0:99999:7::: proxy:*:11453:0:99999:7::: kurumin:gMBaRFGpJx86c:12840:0:99999:7::: saned:!:12766:0:99999:7::: Veja que a lista inclui tambm os usurios ocultos do sistema, usados por programas e servios, que no interessam neste caso. As linhas referentes a estes usurios ocultos possuem sempre um "!" ou um "*" depois do primeiro ":". Podemos usar o sed para filtrar o arquivo, de forma que sobrem apenas as linhas dos usurios vlidos (no caso root e kurumin), usando a opo "D" para deletar as linhas que contenham "!" ou "*". Um exemplo de script para fazer isso seria: # Remove as linhas com "*" sed -e '\/*/D' /etc/shadow > /tmp/usuarios1 # Remove as linhas com "!" sed -e '\/!/D' /tmp/usuarios1 > /tmp/usuarios2 # Remove o restante da linha, deixando apenas o nome do usurio. # (o cut mostra apenas o primeiro campo da linha, antes do ":" cat /tmp/usuarios2 | cut -d: -f1 >> /tmp/usuarios # Aqui temos duas variveis com os nomes dos usurios, que podem ser usadas # de acordo com a situao. # A primeira, "usurios" mantm as quebras de linha, com um usurio por linha # enquanto a "userlist" contm todos os usurios na mesma linha. usuarios=`cat /tmp/usuarios` userlist=`echo $usuarios` # Remove os arquivos temporrios rm -f /tmp/usuarios /tmp/usuarios1 /tmp/usuarios2 # Uma mensagem de aviso: kdialog --msgbox "Os usurios atualmente cadastrados no sistema so: $userlist" Sempre que precisar fazer operaes aritmticas dentro de um script, use o comando "bc". Ele uma calculadora de modo texto, que permite realizar todo tipo de operaes. Para multiplicar o nmero dentro da varivel $numero por trs, o comando seria: $ echo "$numero * 3" | bc Para dividir $numero por 4: $ echo "$numero / 4" | bc O bc oferece um nmero assustador de opes, se voc quiser ir alm das quatro operaes bsicas, d uma olhada no man bc.

Você também pode gostar