Apostila de Shell Script

August 8, 2018 | Author: Estefferson Torres | Category: Shell (Computing), System Software, Software, Areas Of Computer Science, Computer Programming
Share Embed Donate


Short Description

Descrição: Apostila de Shell Script para iniciantes....

Description

   Shell­Scripts                                                                           1

eBook

Shell Scripts Adbeel Goes Filho

Fortaleza – Ceará ­ Brasil

Versão 2006.04.25

Adbeel Goes Filho

   Shell­Scripts                                                                           2

ADBEEL GOES FILHO

Shell Scripts

VIRTVS Fortaleza 2006

Adbeel Goes Filho

   Shell­Scripts                                                                           3

CopyFree (C) 2006 da VIRTVS Engenharia e Informática Ltda Congregamos todos os esforços para fornecer informações de ampla qualidade, contudo, devido ao  dinamismo da área de informática, os autores não assumem responsabilidade pelos resultados e usos  das informações fornecidas.  Recomentamos amplamente aos leitores testar as informações antes de sua efetiva utilização, ao  tempo em que agradecemos antecipadamente por críticas e sugestões prestadas. Copyright (c) 2000,  Adbeel Goes Filho. É garantida a permissão para copiar, distribuir e/ou modificar este documento sob os termos da  GNU Free Documentation License, versão 1.1 ou qualquer outra versão posterior publicada pela  Free Software Foundation; sem obrigatoriedade de Seções Invariantes na abertura e ao final dos  textos. Uma copia da licença deve ser incluída na seção intitulada GNU Free Documentation License. Copyright (c) 2000,  Adbeel Goes Filho. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU  Free   Documentation   License,   Version   1.1   or   any   later   version   published   by   the   Free   Software  Foundation; with the Invariant Sections being LIST THEIR TITLES, with the Front­Cover Texts  being LIST, and with the Back­Cover Texts being LIST. A copy of the license is included in the section entitled "GNU Free Documentation License". Este trabalho foi editado e composto eletronicamente utilizando somente ferramentes livres:

Conhecimentos necessários para a leitura deste trabalho: Entendimento   básico   de   sistemas   operacionais,   Comandos   básicos   de   Unix,   Linux,   Solaris,  FreeBSD   ou   outro   sistema   operacional   com   base   Unix,   Linguagem   de   programação,   Edição  eletrônica de textos. Editor Responsável Satis Diagramação e Produção Virtvs VIRTVS Engenharia e Informática Rua Cel. Ribeiro da Silva, 391. CEP 60.325­210. Monte Castelo. Fortaleza – CE. Telefone: +55 (85) 3283­3124 www.virtvs.com.br Adbeel Goes Filho

   Shell­Scripts                                                                           4

 

SOBRE O AUTOR Adbeel Goes Filho [email protected]     [email protected]      [email protected]  Engenheiro Civil pela Universidade Federal do Ceará (UFC). Especialista em Ciência da Computação pela Universidade Federal do Ceará (UFC). Mestre em Ciência da Computação pela Universidade Federal do Ceará (UFC). Especialista em Matemática Computacional e Otimização de Sistemas. Doutorando em Engenharia Civil – Recursos Hídricos (UFC) Acadêmico de Administração de Empresas pela Universidade Estadual do Ceará  (UECE). Professor do Curso de Graduação em Informática da Universidade de Fortaleza (UNIFOR). Coordenador de Gestão Estratégica do Departamento Nacional de Obras Contra as Secas (DNOCS). Diretor de Engenharia e Informática da VIRTVS Engenharia e Informática Ltda Consultor nas áreas de engenharia civil e informática em empresas e instituições públicas. Consultor na área de custos e acompanhamento de projetos de engenharia civil. Consultor da PERITUS Projetos e Pesquisas Ltda, na área de organização, projetos e informática. Ex­professor dos cursos de Processamento de Dados, Engenharia Civil, Agronomia, Engenharia e Alimentos,  Geologia, Matemática e Estatistica da Universidade Federal do Ceará (UFC). Ex­professor do Curso de Bacharelado em Computação da Faculdade Lourenço Filho. Ex­diretor de engenharia e informática da Rhodes Engenharia e Informática Ltda. Ex­Analista de Sistemas da Fundação Cearense de Meteorologia (FUNCEME).

Adbeel Goes Filho

   Shell­Scripts                                                                           5

AGRADECIMENTOS

VIRTVS Engenharia e Informática Ltda Departamento Nacional de Obras Contra as Secas – DNOCS Universidade Federal do Ceará – UFC Universidade de Fortaleza – UNIFOR Faculdade Lourenço Filho ­ FLF

AGRADECIMENTOS ESPECIAIS

Aos meus pais Elsie Studart e Adbeel Goes de Oliveira Aos meus avós (in memoriam) Angelina Goes de Oliveira e Luis Rodrigues de Oliveira Olga Sales Lopes Gurgel e Benjamim Studart Gurgel A minha esposa Cristine Studart de Santana A meu grande mestre Prof. Dr. Gerardo Valdisio Rodrigues Viana Ao meu orientador acadêmico e de vida Prof. Dr. Clécio Fontelles Thomaz Ao meu orientador e incentivador Prof. Dr. Nilson Campos Aos meus grandes mestres: Antônio Gouveia Neto Afrodisio Durval Gondim Pamplona Amaury Aragão Araújo Genésio Martins de Araújo Suetônio Mota Vicente de Paula Barbosa Vieira A todos os outros que, pelo esquecimento, tipico da natureza humana, deixamos de citar.

Adbeel Goes Filho

   Shell­Scripts                                                                           6

Marcas Registradas Durante este trabalho aparecem várias marcas registradas, contudo, o autor declara estar utilizando  tais nomes apenas para fins editorais, em benefício exclusivo da marca registrada, sem a mínima  intenção de infrigir regras de sua utilização.

Adbeel Goes Filho

   Shell­Scripts                                                                           7

Sumário Capitulo 1. Introdução........................................................................................................................................10 1.O Shell ......................................................................................................................................................10 2.O que são os shell scripts ? ......................................................................................................................12 3.Definições .................................................................................................................................................14 4.Variáveis ...................................................................................................................................................14 5.Formato dos Arquivos de Shell Script .......................................................................................................22 6.Exercicios..................................................................................................................................................34 Capitulo 2. Execução de Programas..................................................................................................................36 7.Execução em foreground e background ....................................................................................................36 8.Redirecionamento......................................................................................................................................37 9.Metacaracteres e Wildcards......................................................................................................................40 10.Sequências de Escape ANSI...................................................................................................................44 11.Códigos de Escape .................................................................................................................................49 12.Conclusões..............................................................................................................................................50 13.Exercicios.................................................................................................................................................51 Capitulo 3. Comandos Condicionais..................................................................................................................52 Capitulo 4. Comandos de Repetição.................................................................................................................62 14.while.........................................................................................................................................................62 15.for ............................................................................................................................................................63 16.until..........................................................................................................................................................66 17.case .........................................................................................................................................................66 18.break e continue......................................................................................................................................67 19.Redirecionando loops..............................................................................................................................69 20.select ......................................................................................................................................................75 21.Funções...................................................................................................................................................78 22.Tornando seu script amigável..................................................................................................................87 23.dialog.......................................................................................................................................................89 Capitulo 5. Comandos Avançados.....................................................................................................................94 1.cut..............................................................................................................................................................94 2.wc..............................................................................................................................................................98 3.tee..............................................................................................................................................................98 4.sort.............................................................................................................................................................99 5.grep..........................................................................................................................................................100 6.sed...........................................................................................................................................................106 Capitulo 6. Bibliografia......................................................................................................................................113 Capitulo 7. Apêndice A – Endereços Internet...................................................................................................114 Capitulo 8. Anexos............................................................................................................................................115 1.Exemplos..................................................................................................................................................116 2.Laboratórios.............................................................................................................................................132 3.Exercicios.................................................................................................................................................140 5.GNU Free Documentation License..........................................................................................................143

Adbeel Goes Filho

   Shell­Scripts                                                                           8

Abreviações Utilizadas *IX

Sistema operacional fundamentado em Unix

LP

Linguagem de programação

SO

Sistema Operacional

SS

Shell­script

Adbeel Goes Filho

   Shell­Scripts                                                                           9

 

Capitulo 1. Introdução 1. O Shell  Shell,   ou   interpretador   de   comandos,   é   o   programa   disparado   logo   após   o   login  responsável por "pegar" os comandos do usuário, interpretá­los e executar uma determinada ação.  Estas   ações   são  subrotinas  conhecidas   pelo    nome  de  system  calls.  Por  exemplo,  quando   você  escreve no console "ls" e pressiona , o shell lê essa string e verifica se existe algum comando  interno (embutido no próprio shell, também chamado de intrínseco) com esse nome. Se houver, ele  executa esse comando interno. Caso contrário, ele vai procurar no PATH por algum programa que  tenha   esse   nome.   Se   encontrar,   ele   executa   esse   programa,   caso   contrário,   ele   retorna   uma  mensagem de erro. Para cada terminal ou console aberto, existe um shell sendo executado. Quando  você entra no seu Linux, ele apresenta o login, para digitar o usuário e a senha. Ao digitar um par  usuário/senha   correto,   o   Linux   abre   automaticamente   um  shell,   que   vai   ficar   esperando   seus  comandos.  Funcionando como uma ponte, o Shell é a ligação entre o usuário e o kernel. O kernel  é quem acessa o hardware da máquina, como disco rígido, placa de vídeo e modem. Por exemplo,  para o usuário acessar um arquivo qualquer, toda esta hierarquia é seguida: USUÁRIO ­­> SHELL ­­> KERNEL ­­> HARDWARE  Antes de Começar Se você está acessando o sistema como usuário administrador (root), saia e entre como  um usuário normal. É muito perigoso estudar Shell usando o superusuário, você pode danificar o  sistema com um comando errado.

Veja o exemplo abaixo:  Welcome to Linux Slackware 7.1 kernel 2.2.16.  virtvs login: eu Password: 

Adbeel Goes Filho

   Shell­Scripts                                                                           10

Linux 2.2.16.  Last login: Mon Sep 25 10:41:12 ­0300 2000 on tty1.  No mail.  virtvs@mucuripe:~$  Essa última linha é o shell. Se você digitar o comando "ps", verá que um dos programas rodando é o  seu shell . O comando “ps” lista os processos em : virtvs@mucuripe:~$ ps  PID TTY TIME CMD  164 tty2 00:00:00 bash  213 tty2 00:00:00 ps  virtvs@mucuripe:~$  Ou seja, o shell utilizado nesse console é o bash, que está rodando com PID 164. Existem diversos tipos de  shell: bash, csh, ksh, ash, etc. Por exemplo, o AIX/6000  possui 5 tipos de  shell  disponíveis: korn  shell  (ksh), bourne  shell  (bsh, sh), C  shell  (csh), trusted  shell (tsh), restricted shell (rsh). O default para este sistema é o ksh. O mais utilizado atualmente é o  bash (GNU Bourne­Again SHell). Por isso o tomaremos como referência.  Resumindo essa seção, é importante saber que para cada terminal ou console aberto,  tem­se um shell rodando. Assim, se você tem 3 xterms abertos na interface gráfica, vai ter um shell  para cada xterm. Ao executar o shell script, o shell atual (no qual você deu o comando) abre um novo  shell para executar o script. Assim, os scripts são executados em um shell próprio (a menos que se  especifique, ao chamar o script, para executá­lo no shell atual). Isso será importante quando formos  tratar de variáveis de ambiente. O uso de alias Alias é um novo nome, ou apelido, para o comando. Pode ser usado para abreviar  longas linhas de comando ou fazer com que comandos comportem­se diferente da execução padrão. Sintaxe:

alias [nome[=string]]

Exemplo: alias cls=clear alias ls='ls ­logt' alias dir=ls

Adbeel Goes Filho

   Shell­Scripts                                                                           11

2. O que são os  shell scripts ?  Shell scripts são conjuntos de comandos armazenados em um arquivo texto que são  executados seqüencialmente. Nesta primeira parte, faremos uma introdução sobre o shell, o formato  desses   arquivos   e  variáveis   de   ambiente.   Shell   pode   ser   standard   ou   restrito,   na   verdade   é   um  comando que possibilita gerar textos com lógica de programação. É muito utilizado para montagem  de ambientes de login e abertura de novos processos que indicam nova seção.  Existe vários tipos de shells, a mais utilizada é a sh, que é um link da bash, ou seja /bin/sh é link de /bin/bash  Detalhes importantes Qualquer shell­script criado necessita na "primeira linha" de indicar onde se encontra  o  shell  interpretador, ou seja o destino, que por padrão é  #!/bin/sh, porém pode ter casos de se  localizar em outro diretório. Também devo dizer que todo shellscript deve ter permissão para obter a  execução. Caso não seja informada esta primeira linhx o shell usará a default do sistema. Sintaxe :  $chmod a+x shellscript Para colocar comentários assim como no PERL, utilize o # (chamado culturalmente de sustenido) O Primeiro Shell Script O primeiro Shell Script a fazer será o "sistema" do exemplo anterior, de simplesmente juntar três  comandos num mesmo script. Passos Para Criar um Shell Script 1. Escolher um nome para o script Já temos um nome: sistema.  Use apenas letras minúsculas e evite acentos, símbolos e espaço em branco 2. Escolher o diretório onde colocar o script Para que o script possa ser executado de qualquer parte do sistema, mova­o para um diretório que  esteja no seu PATH. Para ver quais são estes diretórios, use o comando: echo $PATH Se não tiver permissão de mover para um diretório do PATH, deixe­o dentro de seu HOME 3. Criar o arquivo e colocar nele os comandos

Adbeel Goes Filho

   Shell­Scripts                                                                           12

Use o VI ou outro editor de textos de sua preferência para colocar todos os comandos dentro do  arquivo. 4. Colocar a chamada do Shell na primeira linha A primeira linha do script deve ser: #!/bin/bash Para que ao ser executado, o sistema saiba que é o Shell quem irá interpretar estes comandos. 5. Tornar o script um arquivo executável Use o seguinte comando para que seu script seja reconhecido pelo sistema como um comando  executável: chmod +x sistema Problemas na Execução do Script "Comando não encontrado" O Shell não encontrou o seu script. Verifique se o comando que você está chamando tem exatamente o mesmo nome do seu script.  Lembre­se   que   no   Linux   as   letras   maiúsculas   e   minúsculas   são   diferentes,   então   o   comando  "SISTEMA" é diferente do comando "sistema". Caso o nome esteja correto, verifique se ele está no  PATH do sistema. O comando "echo $PATH" mostra quais são os diretórios conhecidos, mova seu script para dentro de um deles,  ou chame­o passando o caminho completo. Se o script estiver no diretório corrente, chame­o com um "./" na frente, assim: $./sistema Caso contrário, especifique o caminho completo desde o diretório raiz: $/tmp/scripts/sistema "Permissão Negada" O Shell encontrou seu script, mas ele não é executável. Use o comando "chmod +x seu­script" para  torná­lo um arquivo executável. "Erro de Sintaxe" O Shell encontrou e executou seu script, porém ele tem erros. Um   script   só   é   executado  quando   sua   sintaxe   está   100%   correta.  Verifique   os   seus   comandos,  geralmente   o   erro   é   algum   IF   ou   aspas   que   foram   abertos   e   não   foram   fechados.   A   própria  mensagem informa o número da linha onde o erro foi encontrado.

Adbeel Goes Filho

   Shell­Scripts                                                                           13

3. Definições  Branco e TAB ou espaço são a mesma coisa. Um nome é uma sequência de letras,  digitos ou  underscores  começando com uma letra ou  underscore. Um parâmetro é um nome um  digito ou algum desses caracteres: *, #, ?, ­, $, e !.  Comando  : é uma sequência de não brancos separados por brancos. A primeira sequência ou  argumento é o argumento 0.  Pipeline  : é uma sequência de um ou mais comandos separados por | (ou, para compatibilidade  histórica, pelo ^). A função de uma pipeline é sincronizar a entrada ou saida padrão para um arquivo  do tipo FIFO.  Uma lista  :   é   uma   sequência   de  pipelines  separadas   por;.   &,   &&,   or   ||,   e   opcionalmente,  terminada por ; ou &.  Exemplos de comandos do shell: for name [ in word ... ] do list done  case word in [ pattern [ | pattern ] ...) list ;; ] ... esac  if list then list [ else list then list ] ... [ else list ] fi  while list do list done 

4. Variáveis  Uma variável é onde o shell armazena determinados valores para utilização posterior.  São áreas de memória onde podem ser armazenados dados. Estes dados podem ser números, textos,  listas   de   arquivos   e   até   mesmo   resultados   da   saida   de   comandos   que   podem   ser   utilizados  posteriormente. Existem duas categorias de variáveis que podemos definir no ambiente Unix: 1. Variáveis locais  – disponíveis somente para o Shell corrente, não sendo acessadas  pelos subprocessos; 2. Variáveis ambientais ou globais – disponíveis tanto para o Shell corrente como para  os   subprocessos   que   venham   a   usar   o   conteúdo   das   variáveis   definidas.   Para  transformar uma variável com escopo global utilize o comando export. Exemplo:   export  Para a visualização das variáveis locais, usa­se o comando  set. Para verificar quais  variáveis estão exportadas, usa­se o comando env.  Toda variável possui um nome e um valor associado a ela, podendo ser este último  vazio. Para listar as variáveis atualmente definidas no  shell  digite o comando  set.  Para se definir  uma variável, basta utilizar a síntaxe (Sem espaço ao redor do =):  nome_da_variável=conteúdo Por exemplo, queremos definir uma variável chamada "cor" com o valor de "azul": Adbeel Goes Filho

   Shell­Scripts                                                                           14

virtvs@mucuripe:~$ cor=azul  Para utilizar o valor de uma variável, é só colocar um sinal de "$" seguido do nome da  variável ­ o shell automaticamente substitui pelo valor da variável: virtvs@mucuripe:~$ echo cor  cor  virtvs@mucuripe:~$ echo $cor  azul  Em  alguns  casos,  é  aconselhável   colocar   o  nome  da   variável  entre   chaves  {}.   Por  exemplo,   se  quero imprimir  "azul­escuro",  como faria  ? Simplesmente  echo $cor­escuro ?  Não  funcionaria, pois o bash vai procurar uma variável de nome "cor­escuro". Portanto,   temos que  colocar o nome "cor" entre chaves para delimitar o nome da variável: virtvs@mucuripe:~$ echo ${cor}­escuro  azul­escuro  Algumas variáveis já são predefinidas no  shell, como o PATH, que, como foi dito  antes, armazena o caminho dos programas. Por exemplo, a minha variável PATH contém: virtvs@mucuripe:~$ echo $PATH  /usr/local/bin:/usr/bin: /bin: /usr/X11R6/bin: /usr/openwin/bin:/usr/games: /opt/kde/bin:  /usr/share/texmf/bin: /etc/script  ou seja, quando digito um comando, como "ls", o shell vai começar a procurá­lo em  /usr/local/bin,   se   não   encontrá­lo,   vai   procurar   em   /usr/bin   e   assim   por   diante.   Repare   que   os  diretórios são separados por um sinal de dois pontos (:). É importante destacar que o  shell  possui várias variáveis pré­definidas, ou seja, que  possuem um significado especial para ele, entre elas: PATH, PWD, PS1, PS2, USER e UID. Assim, quando iniciamos um novo  shell  (ao executar o nosso script), essas variáveis  especiais são "herdadas" do shell pai (o que executou o shell filho). Outras variáveis definidas pelo  usuário, como a variável "cor" não são passadas do shell pai para o filho. Quando o script terminar, o seu shell (shell filho) simplesmente desaparece e com ele  também as suas variáveis, liberando o espaço ocupado na memória.  Para   tornar   uma   variável   imune   à   alteração   ou   deleção,   deve­se   usar   o   comando  readonly   Variáveis somente leitura não podem ser apagadas. Elas somente deixarão de existir no  momento em que for efetuado o logout da sessão de terminal, ou se o programa que criou a variável  for encerrado, exceto no caso de o Shell­script estar rodando na mesma instância de interpretador  que iniciou a execução do script­Shell. readonly nome Para apagar uma variável, use o comando unset: Adbeel Goes Filho

   Shell­Scripts                                                                           15

unset nome Variáveis Array Também conhecidas como vetores. Este tipo de variável serve para armazenar vários  valores sob um nome e um índice. A maneira de declarar variáveis array é a seguinte: NomeDaVariavel[Indice]=Valor sendo que Indice deve ser necessariamente um valor inteiro. Imaginemos que Maria queira armazenar uma lista de suas frutas favoritas em uma variável array.  Para isso ela faria o seguinte: $ FRUTA[0]=goiaba $ FRUTA[1]=manga $ FRUTA[2]=pera $ FRUTA[3]=laranja Supondo que ele colocou esta lista em ordem decrescente de gosto, para sabermos qual é a sua fruta  favorita basta digitarmos: $ echo ${FRUTA[0]}    Se colocarmos $FRUTA[0] e  shell  exibirá goiaba[0] (goiaba concatenado com [0]. Desta forma  nota­se a necessidade  do uso de {} Agora vejamos uma coisa interessante. Se eu declarar uma variável assim: $FRUTA=goiaba e depois quiser fazer um array com o nome FRUTA eu posso fazer assim: $ FRUTA[1]=manga Desta maneira 'goiaba' passa a ser armazenada em FRUTA[0]    Outra coisa interessante é que podemos declarar um array inteiro numa única linha de comando.  Para isto usamos a sintaxe: NomeDoArray=(valor1 valor2 ... valorn) Desta maneira Maria economizaria teclado digitando isto: $FRUTA=(goiaba manga pera laranja) Adbeel Goes Filho

   Shell­Scripts                                                                           16

E para vermos toda a lista de uma vez só, podemos usar o seguinte comando: $ echo ${FRUTA[*]} Existem várias outras especificações para arrays, aqui é só o básico. E se você precisar usar arrays  de maneira mais complexa que isso procure a documentação oficial do bash. Ambiente do usuário O   ambiente   do   usuário   descreve   a   sessão   para   o   sistema,   contendo   as   seguintes  informações, geralmente armazenadas em variáveis de ambiente: . Caminho para o diretório home ­ HOME; . Para onde enviar seu correio eletrônico ­ MAIL; . Fuso horário local ­ TZ; . Com que nome você se logou ­ LOGNAME; . Onde seu shell pesquisará os comandos ­ PATH; . Seu tipo de terminal ­ TERM; . Outras definições necessárias. A variável PS1 Esta é a "Prompt String 1" ou "Primary Prompt String". Nada mais é do que o prompt  que nos mostra que o  shell  está esperando um comando. Quando você muda PS1 você muda a  aparência do prompt. Na minha máquina o padrão é '\u@\h:\w\$ ' onde \u significa o nome do  usuário, \h significa o nome do host e \w é o diretório atual, o que dá a seguinte aparência: meleu@meleu:/usr/doc/Linux­HOWTOs$    Veja algumas possibilidades (Verifique mais no manual do bash):               \d     mostra a data atual               \h     mostra o hostname               \s    o nome do shell               \t     a hora atual (no estilo 24 horas)               \T     a hora atual (no estilo 12 horas)               \u     nome do usuário que está usando o shell               \w     nome do diretório atual (caminho todo)               \W     nome do diretório atual (somente o nome do diretório) Se você estiver afim de ter a impressão de que está no shell do root basta trocar o '$' por '#' Para aprender a fazer um monte de gracinhas com o PS1 dê uma lida no Bash­Prompt­HOWTO  A variável PS2

Adbeel Goes Filho

   Shell­Scripts                                                                           17

Esta é a "Secondary Prompt String". É usada quando um comando usa mais de uma  linha. Por exemplo: $ echo m\ > e\ > l\ > e\ > u meleu $ echo 'm > e > l > e > u' m e l e u Este sinal '> ' (maior­espaço) é o PS2. Você pode usar os mesmos caracteres especiais que o PS1  usa. A variável MAIL Nada mais é do que o arquivo onde são guardados seus emails. Aqui na minha máquina  eu uso o sendmail como servidor de email, portanto: meleu@meleu:~$ echo $MAIL /var/spool/mail/meleu porém se estivesse usando qmail seria: meleu@meleu:~$ echo $MAIL /home/meleu/Mailbox A variável SHLVL Esta variável armazena quantos shells você executou a partir da primeira shell.  Imagine que você está usando o bash e executou o bash de novo, nesta situação o seu  SHLVL vale 2. Veja isto:   $ echo $SHLVL 1 $ bash          # estou executando o bash a partir do bash $ echo $SHLVL Adbeel Goes Filho

   Shell­Scripts                                                                           18

2 $ exit          # saí do segundo bash exit $ echo $SHLVL 1 Quando você inicializa scripts a partir do comando "source" o script é executado no  shell pai, portanto se tiver um "exit" no script você vai executar um logoff. É aí que está a utilidade  da variável SHLVL. Quando você está no shell primário o valor de SHLVL é 1. Então você pode,  através de um "if" por exemplo, executar o "exit" só se SHLVL for diferente de 1. A variável PROMPT_COMMAND Esta é bem interessante. Ela armazena um comando que será executado toda hora que o  prompt é exibido. Veja: $ PROMPT_COMMAND="date +%T" 19:24:13 $ cd 19:24:17 $ ls GNUstep/  bons.txt  pratica/  teste  worldwritable.txt Mail/     hacking/  progs/    txts/ 19:24:19 $ 19:24:32 $  # isso eh uma linha sem nenhum comando 19:24:49 $ Esta variável é útil quando queremos brincar com o prompt, para aprender mais sobre isso leia o  Bash­Prompt­HOWTO (v. 10. Referências). A variável IFS O shell usa esta variável para dividir uma string em palavras separadas. Normalmente  o IFS é um espaço, uma tabulação (Tab) e um caractere nova linha (\n). Desta maneira: isto eh uma string são quatro palavras, pois IFS é um espaço e as palavras estão separadas por espaço. Agora se eu  mudar IFS para um ':' desta maneira: IFS=':' então a string:

Adbeel Goes Filho

   Shell­Scripts                                                                           19

isto:eh:uma:string conterá quatro palavras. Isto é útil para casos como neste exemplo: #!/bin/bash IFS=':' for item in $PATH ; do         echo $item done Se IFS for uma variável nula (vazia), tudo será considerado uma única palavra. Por exemplo: se o  IFS for nulo, toda essa linha será considerada uma única palavra    A variável RANDOM Quando você exibe esta variável ("echo $RANDOM") é exibido um número aleatório  entre 0 e 32767.    #!/bin/bash NUM="98$(echo $RANDOM)0" CONT=$(echo ­n $NUM | wc ­c)    # quantos digitos tem? while [ $CONT ­lt 8 ]; do       # se nao tiver 8 digitos acrescenta 0's         NUM=${NUM}0         CONT=$(echo ­n $NUM | wc ­c) done echo $NUM Outras Variáveis Outras variáveis que são muito usadas: MAILCHECK ; HISTFILE ; HOSTNAME ; LS_OPTIONS ; LS_COLOR ; MANPATH ; SHELL ;  TERM ; USER ; PS3 . Estas   são   as   mais   utilizadas,   porém   existem   muitas   outras.   Para   ver   quais   são   as  variáveis definidas no momento basta entrar com o comando "set". E para ver apenas as variáveis de  ambiente use "env". Olhe a man page do bash na seção "Shell Variables" para mais detalhes. Configurando variáveis do Shell nome=conteúdo Não deve haver espaço antes ou depois do sinal de igual. Isso assegura que a atribuição seja feita  corretamente, não sendo interpretada com o um comando com argumentos separados por espaço. Poderemos tambem acessar substrings em variaveis na forma  Adbeel Goes Filho

   Shell­Scripts                                                                           20

#a=”13/05/2004”  #b=${a:6:4} #echo $b #2004 A variável PATH Armazena a relação de diretório, usada pelo Shell para pesquisa de comandos.  Os  diretórios a serem pesquisados devem estar separados por (:). Lembre­se que os nomes de variáveis  são sensíveis ao contexto, ou seja PATH não é igual a PaTh. Exemplo: export PATH=/usr/bin:/usr/sbin:.

Exercícios 1. Crie um alias limpatela que execute o comando clear. 2. Mude o prompt do sistema para que apareça: @$ 3. Coloque o alias criado anteriormente no seu shell. 4. Elabore um shell­script para gerar 10 números aleatórios.

Adbeel Goes Filho

   Shell­Scripts                                                                           21

5. Formato dos Arquivos de Shell Script  A primeira linha de todo shell­script deve começar com algo do tipo (Se não colocar é  assumido o shell padrão):  #!/bin/bash a qual indica com qual shell deverá ser executado o script. Nesse exemplo, estamos falando para o  shell atual executar o script com o shell /bin/bash. Se quisermos que o nosso script seja executado  com o shell csh, devemos colocar nessa primeira linha:  #!/bin/csh Como usaremos o bash como nosso  shell  de referência, todas as linhas dos nossos  scripts começarão com #!/bin/bash  Digamos que você executa freqüentemente o comando:  find / ­name file ­print  que   procura   na   raiz   (/)   por   um   arquivo   de   nome   "file".   Só   que   é   incômodo   ficar  digitando esse comando toda vez que se quer procurar um arquivo. Então vamos criar um  shell  script que contenha esse comando. Vamos chamar esse shell script de "procura". Seu conteúdo fica  assim: #!/bin/bash  find / ­name file ­print  Tornemos agora o arquivo executável: chmod 755 ./procura . Porém, ao tentar executar o nosso  script, teremos um problema. ./procura  Este script irá procurar por um arquivo chamado "file". Como especificar qual arquivo  queremos   procurar   ?   Seria   ideal   executarmos   o   nosso   script   seguido   do   nome   do   arquivo   que  queremos procurar. Por exemplo, queremos saber onde está o arquivo "netscape":  ./procura netscape É ai que entram as "variáveis de parâmetro".  Vamos substituir no nosso script a linha find / ­name file ­print por  find / ­name $1 ­print Quando o bash lê a variável "$1", ele a substitui pelo primeiro parâmetro passado na  linha de comando para o nosso script. Então, se executamos ./procura netscape , a variável "$1" será  substituída por "netscape", como a gente queria. Repare que a variável "$2" conteria o segundo  parâmetro passado para o script e assim por diante. Sendo assim, qualquer comando colocado abaixo de  find  seria executado após ele.  Adbeel Goes Filho

   Shell­Scripts                                                                           22

Esse é o essencial do shell script: poder automatizar a execução de programas e comandos como se  estivessem sendo digitados diretamente no console ou terminal.  1.

Capacidades de substituição do Shell

Uma característica interessanto no shell é a capacidade de podermos manipular textos,  números e até saída de comandos através de variáveis. Existem 3 tipos de substituição no Shell: 1. Substituição de variáveis \ parâmetros; 2. Substituição de comandos; 3. Substituição do til; Substituição de variáveis \ parâmetros Cada variável tem um valor  associado a ela. Quando o nome de uma variável  for  precedido por uma sinal de $ (dólar), o Shell substituirá o parâmetro pelo conteúdo da variável. Este  procedimento é conhecido com Substituição de Variável.  Uma das maneiras de exibir o conteúdo  de uma variável é usando o comando echo. Existem dois tipos de parâmetros: posicional e o de palavra chave. Se o parâmetro é um  digito,   então   é   posicional.   Palavras   chave   (também   conhecida   como   variáveis)   podem   ter   seus  valores escritos.  ${variavel:­string} Se "variavel" não tiver sido definida ou for vazia será substituída por "string". O valor  da variável não é alterado. Veja este exemplo: $ echo ${URL:­"http://unsekurity.virtualave.net"} http://unsekurity.virtualave.net $ echo $URL # observe que URL nao foi alterado ${variavel:=string}  

Se "variavel" não estiver sido definida ou for vazia, receberá "string". Exemplo:

$ echo ${WWW:="http://meleu.da.ru"} http://meleu.da.ru $ echo $WWW http://meleu.da.ru ${variavel:?string} Se "variavel" não estiver sido definido ou for vazia, "string" será escrito em stderr (saída de erro  padrão). O valor da variável não é alterado. Veja um exemplo:

Adbeel Goes Filho

   Shell­Scripts                                                                           23

$ echo ${EDITOR:?"Nenhum editor de texto"} bash: EDITOR: Nenhum editor de texto $ echo $EDITOR ${variavel:+string} Se   "variavel"   estiver   definida,   será   substituída   por   "string"   mas   seu   valor   não   será   alterado.  Exemplo: $ echo ${BROWSER:+"BROWSER definido como \"$BROWSER\""} BROWSER definido como "links" Variáveis Somente­Leitura Como sabemos as variáveis podem ter seu valor modificado pelo usuário, mas se nós  quisermos variáveis que NÃO possam ter seus valores alterados basta declararmos tal variável como  somente­leitura. Para tornar uma variável read­only podemos usar o comando "readonly" ou então  "declare ­r". Veja os exemplos a seguir, ambos possuem o mesmo resultado: $ readonly NOME="Meleu Zord" $ echo $NOME Meleu Zord $ declare ­r NOME="Meleu Zord" $ echo $NOME Meleu Zord $ NOME=Fulano bash: NOME: readonly variable $ echo $NOME Meleu Zord Um bom uso deste tipo de variável é para garantir que variáveis importantes de um  determinado script não possam ser sobregravadas, evitando assim algum resultado crítico. O comando "readonly" quando usado sem parâmetros (ou o comando "declare" apenas  com o parâmetro "­r") nos mostra todas as variáveis declaradas como somente­leitura. No exemplo a  seguir se for usado "declare ­r" no lugar de "readonly" teríamos a mesma saída. $ readonly declare ­ar BASH_VERSINFO='([0]="2" [1]="05" [2]="0" [3]="1" [4]="release" [5]="i386­slackware­linux­gnu")' declare ­ir EUID="1005" declare ­ir PPID="1" Adbeel Goes Filho

   Shell­Scripts                                                                           24

declare ­r SHELLOPTS="braceexpand:hashall:histexpand:monitor:ignoreeof:interactive­comments:emacs" declare ­ir UID="1005" Existem variáveis somente­leitura que são inicializadas pelo shell, como USER, UID.  TODAS as variáveis  readonly  uma vez declaradas não podem ser "unsetadas" ou ter seus valores  modificados. O único meio de apagar as variáveis  readonly  declaradas pelo usuário é saindo do  shell (logout). Parâmetros Podemos passar parâmetros para o shell­script assim como na maioria dos programas.  Os parâmetros são variáveis, digamos, especiais. Para começar elas não obedecem as regras de  nomeclatura de variáveis, pois elas usam números; e também nós não podemos mudar o valor destas  variáveis pelas vias "tradicionais", para mudar o valor destas nós temos que contar com a ajuda do  shift e/ou do set (como veremos adiante). Veja esta relação: $0   

é o nome do shell­script (parâmetro zero);

$1 a $9  

$1 é o primeiro parâmetro, $9 o nono, e assim por diante;

${10}, ${11}..

quando o número do parâmetro possui mais de um dígito é necessário o uso  das chaves;

$* 

todos os parâmetros em uma única string  (exceto o $0)

$@  

todos os parâmetros, cada um em strings separadas (exceto $0)

$# 

número de parâmetros (sem contar com o $0).

$?

valor de retorno do último comando (explicado mais adiante);

$$ 

PID do script;

$!                      

PID do último comando iniciado com &

Adbeel Goes Filho

   Shell­Scripts                                                                           25

Exemplo: #!/bin/bash # # "basename" serve para eliminar o caminho do arquivo e mostrar # somente o último nome dele. Neste caso: parametros.sh echo "Nome do script: `basename $0`" echo "Número total de parâmetros: $#" echo "Primeiro parâmetro: $1" echo "Segundo parâmetro: $2" echo "Décimo quinto parâmetro: ${15}" echo "Todos os parâmetros: $*" $ ./parametros.sh a b c d e f g h i j l m n o p q r s t u v x z Nome do script: parametros.sh Número total de parâmetros: 23 Primeiro parâmetro: a Segundo parâmetro: b Décimo quinto parâmetro: p Todos os parâmetros: a b c d e f g h i j l m n o p q r s t u v x z Se você não entendeu direito a diferença entre o $* e o $@, então dê uma olhada no seguinte script  (se   não   entendê­lo   tudo   bem,   siga   em   frente   e   quando   aprender   sobre   o   "if"   e   o   "for"   leia­o  novamente): Exemplo: #!/bin/bash # Ao executar este script entre alguns parametros. Ex.: # [prompt]$ ./testargs.sh um dois tres quatro if [ ­z "$1" ]; then   echo "Uso: `basename $0` argumento1 argumento2 etc."   exit 1 fi echo echo "Listando argumentos com \"\$*\":" num=1 for arg in "$*"; do   echo "Arg #$num = $arg"   num=$[ $num + 1 ] done Adbeel Goes Filho

   Shell­Scripts                                                                           26

# Conclusão: $* mostra todos os argumentos como uma única string echo echo "Listando argumentos com \"\$@\":" num=1 for arg in "$@"; do   echo "Arg #$num = $arg"   num=$[ $num + 1 ] done # Conclusão: $@ mostra cada argumento em strings separadas echo shift O bash possui um comando embutido que lida com parâmetros, o shift. Quando você  usa o shift sai o primeiro parâmetro da lista e o segundo vai para $1 o terceiro vai para $2, e assim  por diante. Você pode ainda especificar quantas "casas" você quer que os parâmetros "andem" à esquerda através de "shift n" onde 'n' é o número de casas, mas se o número de casas que ele deve  andar for maior que o número de parâmetros o shift não é executado. Veja este exemplo: #!/bin/bash echo "$#: $*" echo ­e "executando \"shift\"" shift echo "$#: $*" echo ­e "executando \"shift 5\"" shift 5 echo "$#: $*" echo ­e "executando \"shift 7\"" shift 7 echo "$#: $*" $ ./shift­exemplo.sh 1 2 3 4 5 6 7 8 9 0 10: 1 2 3 4 5 6 7 8 9 0 executando "shift" 9: 2 3 4 5 6 7 8 9 0 executando "shift 5" 4: 7 8 9 0 executando "shift 7" 4: 7 8 9 0 Os valores que saem são perdidos. Use com atenção! Adbeel Goes Filho

   Shell­Scripts                                                                           27

Adbeel Goes Filho

   Shell­Scripts                                                                           28

set (para editar parâmetros) O que vou passar neste tópico não é sobre como usar "todo o poder do comando set", e  sim como usar  set  especificamente para editar parâmetros. Não tem nenhum segredo! Veja este  exemplo: set um dois tres Isso fará com que $1 seja 'um', $2 seja 'dois', $3 seja 'tres' e só! Não existirá $4, $5, etc. mesmo que eles tenham sido usados. Veja um exemplo de script: #!/bin/bash echo "Os $# parâmetros passados inicialmente foram: $@" echo echo "e agora eu vou alterá­los!" echo "como eu sou mau... (huahuahau risada diabólica huahuahuha)" echo set um dois tres echo "Os $# novos parâmetros agora são: $@" echo Não interessa quantos parâmetros você passar para este script, no final você só terá $1,  $2 e $3 valendo 'um', 'dois' e 'tres', respectivamente. Quoting  Os caracteres abaixo tem um modo especial de tratar o shell :  ;  &  (  )  |  ^    new­line  space  tab  #  ∙   caracter   deve   ser   cotado   pela   precedência   com   um   \.   O   par   \new­line   é   ignorado.   Todos   os  caracteres fechados entre o par de acentos (‘), exceto aspas simples são cotadas.  ∙ Um & no final do comando indica que este irá ser executado em  background.  O  shell  mostra o  número do processo gerado.  Para que você não perca este processo ao terminar seu shell, execute seu comando assim:  $ nohup comando argv1 argv2 ... argvn&  Exemplos: echo $PATH /usr/bin:/usr/local/bin Adbeel Goes Filho

   Shell­Scripts                                                                           29

arquivo=/home/morro.txt more $arquivo txt1=Casa txt2=Mae txt3=Joana echo ${txt1}da$txt2$txt3 Observe que no último exemplo foram usadas as chaves para circundar o nome da  variável, senão o Shell poderia interpretar a variável como txt1da, o que seria o nome da variável  diferente de txt1, caso as chaves não fossem usadas, gerando mensagem de erro de parâmetro não  definido, pois nesse caso a variável txt1da não existiria. Substituição de comando A  substituição de comando  é  usada para substituir  um  comando  por  seu resultado  dentro da mesma linha de comando. Isto será útil quando for necessário armazenar a saída de um  comando em uma variável ou passar essa mesma saída para outro comando. A sintaxe utilizada é: $(comando) ou `comando` A substituição de comando permite que você capture o resultado de um comando e  utilize­o como um argumento para outro comando ou armazene sua saída em uma variável. Exemplo: dir_atual=$(pwd) cp $(ls *.txt) /home/user1/backup Substituição do ~ (til) A substituição do til é executada de acordo com as seguintes regras: 1. Um til sozinho ou em frente a uma barra é substituido pelo conteúdo da variável  HOME. Exemplo: HOME=/home/user3 echo ~ 2. Um til seguido do sinal de + é substituído pelo valor da variável PWD.  3. Um til seguido de – será substituiído pelo valor da variável OLDPWD. Exemplo: echo ~ ls ­1F ~/file1 ls – logt ~+/poodle ls ~­ Adbeel Goes Filho

   Shell­Scripts                                                                           30

Prompting  Quando usado interativamente, o  prompt  do  shell  é o valor da variável PS1 antes da  leitura do comando. Se todo tempo uma linha deve ser digitada e uma nova linha teclada para  completar o comando, então um segundo prompt é mostrado. 

Input / Output  Antes   de   um   comando   ser   executado,   sua   entrada   e   saida   pode   ser   redirecionada  usando as notações interpretadas pelo shell.   word  ­ Usando word como saida padrão  >> word  ­ Idem ao >, so que neste caso se word já existe não sobrepõe, faz o append.  &digit. Note que digit precisa ser de um tamanho entre 0 a 9.  Exemplo:  ... 2>&1 

Arquivo associado ao descritor 2 com o arquivo corrente associado com o descritor do  arquivo 1. Note que o redirecionamento de I/O é necessário se você quer sincronia com stdout e  stderr   para   o   mesmo   arquivo.   Esta   opção   é   bastante   usado   para   se   configurar   impressoras   ou  dispositivos seriais.    Conceito de Sinais  Um sinal é u m flag transmitido para um processo quando certos eventos ocorrem. Os  sinais mais conhecidos em ambiente *IX são: NULL HUP INT QUIT KILL TERM

Saida do Shell ( ^D ou exit ) Hung­up – enviado para processos em retaguarda no logout Interrupção ( ^C ) Quit ( ^\ ) ­ gera arquivo core Morte certa ( Não pode ser capturado ou ignorado ) Terminação por software

O comando kill transmite um sinal explícito para um ou mais processos. Diite kill ­l para obter uma lista de sinais disponíveis no SO. O que é um TRAP ? Um trap é uma maneira de capturar  sinais transmitidos a um processo e de executar  alguma ação baseada no  tipo de sinal que foi recebido. A trap simplesmente espera por sinais enviados ao Shell, identifica­os e então, executa  Adbeel Goes Filho

   Shell­Scripts                                                                           31

a ação associada. Uma trap pode ser definida para a remoção de arquivos temporários no término de  um programa ou pode definir sinais que devam ser ignorados durante um segmento sensível   na  execução do programa. O comando trap O comando trap  pode ser usado em programas Shell para capturar um sinal antes que  ele possa abortar um processo e executar alguma ação adicional ou alternativa. Os comandos trap são normalmente colocados no início de um SS, mas eles podem  estar em qualquer parte do script. As traps são assinalidas pelo Shell quando este Lê  o comando  trap. As traps são acionadas quando um sinal relacionado é recebido. Sintaxe: trap 'comandos' sinal1 sinal2 ... sinal n Exemplo: trap 'echo bye; exit ' 2 3 15 while tru; do echo “Hello ...” done Ignorando sinais O comando trap pode ser usado para ignorar determinados sinais quando estes forem recebidos pelo  processo. Sintaxe: trap  '' sinal1 sinal2 ... sinal n Exemplo: Ignora o sinal INT que é equivalente ao ^C. trap '' 2 whilte true; do    echo “Hello ...”    sleep 2 done Exemplo: gerenciar remoção de arquivos temporários se o programa for abortado trap 'rm /tmp/templfile; exit' 2 3 15

Adbeel Goes Filho

   Shell­Scripts                                                                           32

Exemplo: comando para ignorar sinais antes de sessos críticas de código trap ''  3 5 Exemplo: restaurar o trap para ação default quando uma seção de código sensível for completada trap INT QUIT TERM  ou  trap 2  3 15  As interrupções e sinais de término invocados por um comando são ignorados se este  comando foi executado seguido do caracter &. Outros sinais tem valores herdados pelo  shell  de  shells­pai, com exceção do sinal 11. (seja comando trap). 

Adbeel Goes Filho

   Shell­Scripts                                                                           33

Comandos especiais  break [ n ]  continue [ n ]  cd [ arg ]  echo [ arg ... ]  eval [ arg ... ]  exit [ n ]  export [ name ... ]  hash [ ­r ][ name ... ]  newgrp [ arg ... ]  pwd  read [ name ... ]  return [ n ]  set [ ­­aefhkntuvx [ arg ... ] ]  shift [ n ]  test  times  trap [ arg ] [ n ]  type [ name ... ]  ulimit [ ­f [ n ] ]  umask [ nnn ]  unset [ name ... ]  wait [ n ] 

Chamada do sh  Opções podem ser especificadas com um simples ou múltiplos argumentos, mas em  todos os casos, cada opção deve iniciar com um ­.  ­c string  ­ Se a chave ­c está presente, então os comandos estão lendo de uma string.  ­s  ­ Se a chave ­s está presente, então os comandos estão lendo da entrada padrão, o shell  irá de cada parametro posicional.  ­i  ­ Se a entrada do shell estiver conectada a um terminal, então este shell é interativo,  Neste caso: TERMINATE é ignorado(então o sinal 0 não mata shell interativo).  ­r ­ Shell restrito.  sh pode retornar :  0 ­ Sucesso  Adbeel Goes Filho

   Shell­Scripts                                                                           34

1 ­ A execução do programa com erro (Veja Comandos especiais)  2 ­ Sintax Error (Erro de Sintaxe) 3 ­ Signal received that is not trapped 

6. Exercicios 1. Qual é a shell mais utilizada pelo AIX/6000 ? 2. Quais são os dispositivos default de entrada e saida utilizados pelo sistema ? 3. É possível alterar os dispositivos de entrada e saida padrões ? Como ? 4. Que tipo de informação é enviada para a saida padrão ? 5. Que outro dispositivo pode ser usado no lugar da entrada padrão ? 6. Utilizando redirecionamento, como você faria para escrever um pequeno texto no arquivo carta ? 7. Qual a diferença entre os sinais > e >> ? 8. Qual a finalidade do dispositivo nulo ? 9. O redirecionamento utilizado em um comando é válido para os próximos ? Explique 10.É possível redirecionar mais do que um   dispositivo padrão num só comando ? Caso afirmativo,  faça um exemplo redirecionando todos os dispositivos padrões. 11. A ordem  com que  são feitos os redirecionamentos é relevante para a ação tomada pelo  comando ? E usando associações ? Explique. 12.Explique os seguintes comandos : a) $ls 2> &1 > saida.do.ls b) $ls ­R / > erros 2> arvore c) $mailto claudia > carta e) $ls ­l /usr > arvore 2> &1 f) $ls > saida.do.ls 2> &2 13.Utilizando a substituição de comandos, atribua a data de hoje no formato dd/mm/yy à variável  TODAY. Consulte o manual on­line para verificar quais os formatos possíveis para a exibição de  datas e/ou horas. 14.Liste o conteúdo do diretório de outro usuário usando a substituição do til ?

Adbeel Goes Filho

   Shell­Scripts                                                                           35

15.Crie uma variável chamado MYNAME e armazene nela o seu primeiro nome. Como se mostra o  conteúdo da variável ? 16.Como fazer para que o Shell filho “enxergue” o conteúdo da variável MYNAME ? 17.Torne a variável TODAY somente­leitura. É possível excluir esta variável ? 18.Modifique seu prompt de comando, de modo que ele fique com a aparência a seguir: [user1]­10/10/2000 as 06:45­/home/user1 => 19.Utilizando a substituição de comando copie o conteúdo de /home/teste  para /tmp   20.Exiba o conteúdo do seu diretório home na saida padrão. 21.Copie a lista detalhada dos processos em execução para o arquivo lista.txt no seu diretório home. 22.Sabendo que a=1 b=2 c=3 Mostre na saida padrão começo­32321­meio­34567­fim utilizando os nomes das  variáveis. 23. Escreva um SS que emita uma mensagen na sua tela a cada 3 segundos com um bip. Torne este  SS imune aos sinais INT, HUP e TERM.  Como parar este programa ?  

Adbeel Goes Filho

   Shell­Scripts                                                                           36

Capitulo 2. Execução de Programas Falaremos agora sobre execução de programas em primeiro plano (fg ­ foreground) e  em segundo plano (bg ­ background), redirecionamento de saídas e também sobre os códigos de  escape dos programas.

7. Execução em foreground e background  Quando   executamos   um   programa,   o  shell  fica   esperando   o   mesmo   terminar   para  depois nos devolver a linha de comando. Por exemplo, quando executamos o comando  cp arquivo1 arquivo2  o  shell  executa esse comando, fica esperando ele terminar, para depois nos retornar a linha  de  comando. Isso chama­se execução em primeiro plano, ou foreground, em inglês.Agora digamos que  o arquivo a ser copiado seja muito grande, digamos, 50Mb. Enquanto o comando cp é executado,  vamos ficar com o shell preso a ele todo esse tempo, ou seja, cerca de 1 ou 2 minutos (Dependendo  da máquina). Somente após isso vamos ter a linha de comando de volta para podermos continuar  trabalhando. E se pudéssemos dizer ao shell para executar um programa e nos retornar a linha de  comando sem ficar esperando o tal programa terminar ? Seria muito melhor, não? Em alguns casos  seria. E podemos fazer isso. Uma maneira fácil é colocar o sinal de & depois de um comando.  No exemplo acima ficaria: virtvs@mucuripe:~$ cp arquivo1 arquivo2 &  [1] 206  virtvs@mucuripe:~$ Pronto, assim que teclarmos [enter], teremos a nossa linha de comando de volta e mais  duas informações: "[1] 206". A primeira informação ([1]) chama­se job. Ela identifica os programas que estão sendo  executados em bg (background). Por exemplo, se executarmos mais um programa em bg enquanto  este "cp" está sendo executado, o novo programa recebe o job de número 2 ([2]) e assim por diante. A segunda informação (206) é o pid do programa, ou seja, o número de processo que o  kernel dá a esse programa. Mas aí temos um pequeno problema. Digamos que você queira trazer o programa para  Adbeel Goes Filho

   Shell­Scripts                                                                           37

fg, por exemplo, se o programa executado em  bg  for um tocador de mp3 e você quiser mudar a  música. Como fazemos? Usamos o comando fg [job] (intuitivo, não ?) do bash. No exemplo acima,  digamos que eu execute o "cp" em  bg, mas depois queira trazê­lo para  fg  para cancelá­lo. Seria  simples: virtvs@mucuripe:~$ cp arquivo1 arquivo2 &  [1] 206  virtvs@mucuripe:~$ fg 1  cp arquivo1 arquivo2 Assim trazemos o "cp" para primeiro plano e a linha de comando só retorna quando ele terminar. Opcional Uma outra maneira de colocar um programa para rodar em bg é utilizando um truque  do bash. Digamos que você execute o comando "cp" e esqueça de colocar o sinal "&". E aí ? Tem  que ficar esperando acabar ou cancelar o comando? Não, podemos teclar: Ctrl + Z. Ao fazer isso,  paramos a execução do programa. Então é só dar o comando  bg [job]  (intuitivo também, né?): virtvs@mucuripe:~$ cp arquivo1 arquivo2 * aqui teclamos Ctrl + Z *  [1]+ Stopped cp ­i arquivo1 arquivo2  virtvs@mucuripe:~$ bg 1  [1]+ cp ­i arquivo1 arquivo2 &  virtvs@mucuripe:~$ Quando teclamos o Ctrl + Z, o bash nos diz que o job 1 foi parado ([1]+ Stopped) e  quando executamos "bg 1" ele nos diz que o comando voltou a ser executado, mas em bg (repare o  sinal de "&" no final da linha): [1]+ cp ­i arquivo1 arquivo2 &.

8. Redirecionamento Muitos   programas   que   executamos   geram   saídas   no   console,   ou   sejam,   emitem  mensagens para os usuários. Por exemplo, queremos achar quantos arquivos no nosso sistema tem  "netscape" no nome: virtvs@mucuripe:~$ find / ­name netscape  /usr/lib/netscape  /usr/lib/netscape/netscape  /usr/lib/netscape/nethelp/netscape  /usr/local/bin/netscape Adbeel Goes Filho

   Shell­Scripts                                                                           38

Agora se quisermos procurar quantos arquivos compactados com o gzip (extensão .gz)  tem   no   nosso   sistema   para   depois   analisá­los   e   possivelmente   apagar   os   repetidos   ou   inúteis,  teremos uma lista muito grande. Aqui no meu sistema deu mais de 1000 arquivos. Então, seria útil  podermos   enviar   as   mensagens   que   vão   para   o   console,   para   um   arquivo.   Assim,   poderíamos  analisá­lo depois de executar o comando. Isso é extremamente útil ao trabalharmos com shell script  ­ enviar as saídas dos comandos para arquivos para depois analisá­las. Exemplificando: virtvs@mucuripe:~$ find / ­name "*.gz" > lista.txt  find: /home/vera: Permissão negada  find: /home/pri: Permissão negada  find: /root: Permissão negada  virtvs@mucuripe:~$ Notamos que nem tudo foi para o arquivo lista.txt. As mensagens de erro foram para o  console. Isso porque existem dois tipos de saída: a saída padrão e a saída de erro. A saída padrão é a  saída normal dos programas, que no caso acima, seria os arquivos encontrados. E a saída de erro,  como o próprio nome diz, são os erro encontrados pelo programa durante sua execução, que devem  ser informados ao usuário, como os erros de "permissão negada". E   aí,   como   selecionar   uma   ou   outra   ?   É   simples,   apenas   devemos   indicar   o   "file  descriptor" (fd) delas. Não vamos entrar em detalhes sobre o que é "descritor de arquivos" por fugir  do nosso escopo e ser um pouco complicado, apenas temos que saber que o fd 1 corresponde a saída  padrão e o fd 2 a saída de erro. Assim, no exemplo acima, para enviar os erro para o arquivo  erros.txt e a saída padrão para o arquivo lista.txt, usaríamos: virtvs@mucuripe:~$ find / ­name "*.gz" 1> lista.txt 2> erros.txt Ou seja, é só por o número da saída desejada antes do sinal de ">". Agora digamos que queremos ver o conteúdo do arquivo lista.txt. Podemos abrí­lo com  um editor de textos ou usar o "cat". Optando pela última opção: virtvs@mucuripe:~$ cat lista.txt  /home/neo/gkrellm­0.10.5.tar.gz  /home/neo/linuxcall­interface­beta.tar.gz  ...   erros.txt | tee lista.txt O que fizemos ? Primeiro pegamos a saída de erro e enviamos para o arquivo erros.txt.  O restante, ou seja, a saída padrão, estamos enviando para a entrada do comando tee (usando o  pipe). O tee simplesmente pega o que ele recebe (através do pipe) e joga no arquivo lista.txt e na  tela.   Assim,   além   de   gravarmos   a   saída   num   arquivo,   podemos   mostrar   ao   usuário   o   que   está  acontecendo. Isso é muito útil quando escrevemos alguns scripts. Resumindo:   aprendemos   que   podemos   redirecionar   a   saída   padrão   ou   de   erro   de  programa para um arquivo usando respectivamente "1>" ou "2>" ou também enviar a saída para a  entrada de outro programa usando o pipe "|". echo Existem   alguns   momentos   que   você   não   quer   que   a   saída   do   echo   pule   de   linha  automaticamente. Para isso use o parâmetro "­n". Este parâmetro é útil quando você vai entrar com  algo após o echo. Veja este script: Exemplo: #!/bin/bash echo ­n "Entre com o nome do arquivo: " read FILE echo "Tipo do arquivo `file $FILE`" Muita atenção deve ser tomada ao usar o echo, pois as aspas que você pode vir a deixar de usar  podem fazer um diferença (em alguns casos isso pode ser muito útil). Exemplo: $ echo uma    boa   rede de irc     que conheco eh     irc.linux.org uma boa rede de irc que conheco eh irc.linux.org $ echo "uma    boa   rede de irc     que conheco eh     irc.linux.org" uma    boa   rede de irc     que conheco eh     irc.linux.org $ $ # agora um exemplo com variavel $ Adbeel Goes Filho

   Shell­Scripts                                                                           40

$ TESTE="primeira linha da variavel > segunda linha > terceira... > chega! :) > " $ echo $TESTE primeira linha da variavel segunda linha terceira... chega! :) $ echo "$TESTE" primeira linha da variavel segunda linha terceira... chega! :) A esta altura você já deve ter se perguntado "Como faço para imprimir caracteres nova  linha ou beep?!". Os mais malandrinhos devem ter tentado um contra­barra (backslash) '\', mas você  não pode simplesmente fazer isso. É necessário usar o parâmetro "­e" com o echo. Este parâmetro  permite que usemos sequências de escape contra­barra.     As sequências são iguais a da linguagem C, exemplo: \n para nova linha, \a para beep,  \b para backspace, etc... Exemplo: $ echo ­e "module caiu de cara tentando \"top soul\".\nQue paia\a"! module caiu de cara tentando "top soul". Que paia! O ­e é também usado para escrever colorido e outras coisas interessantes. Veremos isso no tópico  seguinte.

9. Metacaracteres e Wildcards Metacaracteres são caracteres que possuem algum significado especial para o shell. Wildcards são subconjuntos dos metacaracteres cuja característica é simplificar a linha  de comando.

Os metacaracteres e wildcards serão vistos neste trabalho de  uma maneira gradativa, a  medida em que sejam necessários.Alguns deles já foram vistos no redirecionamento (> > ). Veja mais alguuns metacaracteres:

Caracteres

Definição

\

Continuação de linha

;

Agrupamento de comandos Adbeel Goes Filho

   Shell­Scripts                                                                           41

Caracteres | 

Definição Processamento Sequenciado

O caracter \ (continuação de linha) permite continuar a escrever o comando na linha  subsequente, caso o mesmo seja extenso, ou seja, não caiba em uma só linha da tela. Ressaltamos  que não deverá haver espaço em branco após este caractere. Após pressionarmos a tecla [ENTER] o  shell  mostrará um novo prompt default (>) chamado de secundário, informando que a linha corrente  é a continuação da linha anterior. Exemplo: $cat /home/chico/public_html/index.html \ >     /home/maria/public_html/index.html O caracter de agrupamento de comando (;) permite agrupar os comandos em uma  mesma linha. Sintaxe: Exemplo:

$comando1 ; comando2 $ls ; pwd Isto é equivalente a digitar $ls $pwd

É importante observar que o segundo commando não depende da resposta do primeiro  comando, ou seja, não há relacionamento entre eles. Pipes Pipes  ou tubos ( | ) é uma outra forma de agrupar comandos em uma mesma linha,  porém, há relacionamento entre os comandos. Quand utilizamos o “|” (pipe), ele informa ao  shell  para conectar a saida padrão do  primeiro comando com a entrada   padrão do segundo comando. Por sua vez, a saida do segundo  comando é direcionada para a saida padrão. Para um melhor entendimento imagine que a linha de comando é um tubo por onde  deve passar a informação do primeiro comando para o segundo, do segundo para o terceiro e assim  sucessivamente, até que o último comando  direcione a saida   para a saida padrão. Agora vejamos o pipe. Sua sintaxe é:      $ programa1 | programa2 Adbeel Goes Filho

   Shell­Scripts                                                                           42

O pipe é usado para você fazer da saída de um programa a entrada de outro (como  usado no exemplo amarelinho.sh já mostrado anteriormente). Apesar de simples o pipe é muito útil  e poderoso. Veja este exemplo muito simples: $ who meleu    tty1     Nov 20 01:40 hack     tty2     Nov 20 01:45 root     tty3     Nov 20 02:44 $ who | cut ­c­9 meleu hack root Comandos Úteis com o Pipe xargs O xargs transforma stdin em argumentos da linha de comando. Vamos usar o exemplo  anterior de novo: Exemplo: $ who | cut ­c­9        # lembrando: pipe transforma stdout em stdin meleu hack root $ # "echo" nao le arquivo, ele usa argumentos. $ # A linha abaixo nao tem utilidade. $ who | cut ­c0­9 | echo $ # "xargs" transforma o conteudo de stdin em argumentos $ who | cut ­c0­9 | xargs echo meleu hack root   Como eu gosto do find não resisti e colocarei um comando interessante que usa pipe e xargs: $ find / ­perm ­2 ! ­type l ! ­type c | xargs ls ­ld > wordwritable.txt tee Outro   comando   bom   de   se   usar   com   pipe   é   o   "tee".   Ele   faz   com   que   a   saída   do  programa vá para a saída padrão, normalmente a tela e para um arquivo ao mesmo tempo. É como  se você fizesse "programa > arquivo" só que o saída do programa também seria escrita na saída  padrão. Experimente: Adbeel Goes Filho

   Shell­Scripts                                                                           43

$ ls ­la |tee conteudo.txt O  comando echo e os cracteres de saida \b \c \f \n \r \t \a \\ \0nnn

Backspace Suprime a terminação newline Alimentação de formulário Nova linha ( NewLine ) Carriage Return Tabulação Caractere de alerta Barra invertida Caractere de código ASCII em octal

Adbeel Goes Filho

   Shell­Scripts                                                                           44

10.Sequências de Escape ANSI Para usar cores a sequência de escape é "\e[m" (os sinais '' não entram!).  Veja um exemplo (mais a frente você verá tabelas com os significados destas sequências): Examplo: #!/bin/bash # imprime amarelinho no centro da linha # A variável $COLUMNS contém o número de colunas que o terminal está # usando, e antes de executar este script você precisa exportá­la: # [prompt]$ export COLUMNS [ $COLUMNS ] || {         echo Você precisa exportar a variável \"COLUMNS\":         echo "Tente \"export COLUMNS\" e tente executar novamente"         exit 1 } POSICAO=$[ ( $COLUMNS ­ `expr length "$*"` ) / 2 ] # `expr length "$*"` retorna o número de caracteres digitados # como parâmetros. echo ­e "\e[${POSICAO}C\e[33;1m$*\e[0m" Agora uma explicação ligeira: o \e diz ao echo que o que vem depois é uma sequência  de escape. Se você der a sequência '[C', onde num é um número qualquer, o cursor vai andar  "num" caraceteres para a direita. Acima eu uso a variável POSICAO para mover o cursor para o  centro da linha (veja o cálculo no código).     O comando '[m' muda para a cor "num". Cada cor tem um código próprio. No  exemplo acima o 33 faz ficar marrom, porém combinando com o 1 fica amarelo (isso no modo  texto, pois no xterm, por exemplo, o 1 faz o marrom ficar em negrito. veja OBSERVAÇÕES mais  adiante). Veja também uma tabela com os códigos de movimentação de cursor que eu conheço (os  caracteres '' devem ser ignorados):

Adbeel Goes Filho

   Shell­Scripts                                                                           45

Código

O que faz

 \e[A 

Move o cursor N linhas acima.

 \e[B 

Move o cursor N linhas abaixo.

 \e[C 

Move o cursor N colunas à direita.     

\e[D 

Move o cursor N colunas à esquerda. 

\e[E 

Move o cursor N linhas para baixo na coluna 1.

 \e[F 

Move o cursor N linhas para cima na coluna 1.

 \e[G   

Coloca o cursor na linha N.     

 \e[;H

Coloca o cursor na linha L e na coluna C.

 \e[I

Move o cursor N tabulações à direita.    

 \e[J 

N=0  Apaga do cursor até o fim da tela;  N=1  Apaga do cursor até o início da tela;  N=2  Apaga a tela toda.      

 \e[K 

N=0  Apaga do cursor até fim da linha;  N=1  Apaga do cursor até o início da linha; N=2  Apaga a linha toda.      

 \e[L

Adiciona N linhas em branco abaixo da atual. 

 \e[M    

Apaga N linhas abaixo da atual.   

 \e[P    

 Apaga N caracteres a direita.

 \e[S 

Move a tela N linhas para cima.     

 \e[T 

Move a tela N linhas para baixo.  

 \e[X 

Limpa N caracteres à direita (com espaços).

 \e[@ 

Adiciona N espaços em branco.    

 \e[s     

Salva a posição do cursor. 

 \e[u 

Restaura a posição do cursor que foi salva. 

Adbeel Goes Filho

   Shell­Scripts                                                                           46

Agora   uma   tabelinha   dos   atributos   e   seus   números   (N   deve   estar   no   formato  "\e[m"):

Atributo

N

Cor

X

Desligar todos atributos 

0

Preto

0

Negrito

1

Vermelho

1

Cor X para o primeiro plano

3X

Verde

2

Cor X para o segundo plano

4X

Marrom

3

Sublinhado

4

Azul

4

Piscando (blink)

5

Roxo

5

Video reverso

7

Ciano

6

­x­

­­

Branco

7

OBSERVAÇÕES: – –



Negrito,   Sublinhado   e   Piscando   possuem   comportamentos   diferentes   no   console   e   nos  emuladores de terminal. Principalmente quando temos negrito sendo usado com cores. Por exemplo, o código "\e[33m"  irá ativar  o marrom mas se for usado (no console!) com o  atributo de negrito ficará amarelo, e o código será assim: "\e[1;33m". Por isso faça os testes que  você descobrirá as cores Estas   tabelas   eu   fiz   graças   a   uma   matéria   que   o   aurélio   escreveu   sobre   isso.   Veja   em  http://verde666.org/coluna/  2.

read

Como você viu no script anterior para entrar com um dado usa­se "read". O read tem  alguns "macetinhos". Pra começar: você não precisa colocar um echo toda hora que for usar o read  para escrever um prompt. Basta fazer "read ­p prompt variavel" Veja esta seção de exemplos: Examplo: #!/bin/bash read ­p "Entre com uma string: " string echo $string $ ./read1.sh Adbeel Goes Filho

   Shell­Scripts                                                                           47

Entre com uma string: klogd eh um tremendo cachacero! klogd eh um tremendo cachacero! Examplo: #!/bin/bash read ­p "Entre com 3 strings: " s1 s2 s3 echo "s1 = $s1     s2 = $s2     s3 = $s3" Examplo: $ ./read­2.sh Entre com 3 strings: j00nix eh cabecudo s1 = j00nix     s2 = eh     s3 = cabecudo # o mesmo script com mais de 3 strings # $ ./read­2.sh Entre com 3 strings: eSc2 adora ficar de copy'n'paste no IRC. s1 = eSc2     s2 = adora     s3 = ficar de copy'n'paste no IRC. Quando o "read" vai ler apenas uma variável, toda a string vai ser atribuída a esta  variável. Quando vai ler mais de uma variável ele atribui cada string a sua respectiva variável; e  quando o número de strings excede o número de variáveis a última fica com o excedente. O parâmetro "­s" serve para não ecoar o que for digitado. É útil para digitar uma senha  por exemplo. Tente "read ­s PASS" e veja. Você   também   pode   determinar   o   número   de   caracteres   que   serão   lidos   com   o  parâmetro "­n". Tente fazer "read ­n 10 VAR". Mas cuidado: ao usar a opção ­n você não poderá  usar o backspace para fazer correções. A opção "­r" serve para que a contra­barra (backslash) não aja como um caracter de  escape.   3.

Redirecionamento

Quem já sabe programar deve saber que existem três "file descriptors" abertos por  padrão (pelo menos nos sistemas operacionais que conheço): stdin (standard input), stdout (standard output) e stderr (standard error). Para fins práticos, estes são  considerados arquivos e você pode direcionar destes "arquivos" para outros e vice­versa.

Adbeel Goes Filho

   Shell­Scripts                                                                           48

Veja como direcionar de: arquivo para stdin

$ programa  arquivo

stderr para arquivo

$ programa 2> arquivo

stdout para stderr

$ programa 1>&2

stderr para stdout

$ programa 2>&1

stdout e stderr para arquivo $ programa &> arquivo   Se você usar por exemplo "find / ­perm ­2 > worldwritable.txt" e no diretório não tiver  um arquivo chamado "worldwritable.txt" este será criado, a saída do comando será gravada nele e a  saída de erro padrão será impressa na tela. Para não ver as mensagens de "Permission Denied" faça  isso:      $ find / ­perm ­2 > worldwritable.txt 2> /dev/null Ainda   temos   um   probleminha:   este   comando   irá   mostrar   também   todos   os   links  simbólicos e vários arquivos de dispositivo. Para eliminar os links simbólicos faça o seguinte:      $ find / ­perm ­2 ! ­type l > worldwritable.txt 2> /dev/null Se   o   arquivo   já   existir   seu   conteúdo   será   sobregravado.   Mas   você   pode   apenas  concatenar o conteúdo no final do arquivo usando ">>". Exemplo:      $ echo " F I M  D O  A R Q U I V O " >> worldwritable.txt Veja este script a seguir a execute ele usando redirecionamento na linha de comando  pra ver os resultados #!/bin/bash echo "Isto vai para a saída padrão." echo "Isto vai para a saída de erro padrão." 1>&2 echo "Isto vai criar um arquivo e colocar esta linha nele." > ARQUIVO echo "Esta linha vai para o final do arquivo." >> ARQUIVO    Tem um outro tipo de redirecionamento que é bastante útil. É assim:     $ programa  2 )) Veja este script abaixo apenas para entender a utilidade do let: Exemplo: #!/bin/bash if (( $# != 2 )) ; then    # poderia ser: if let "$# != 2"         echo "Uso: `basename $0` N1 N2" 1>&2         exit 1 fi if (( $1 > $2 )) ; then    # poderia ser: if let "$1 > $2"         echo "$1 é maior que $2" elif (( $1 == $2 )) ; then    # poderia ser: elif let "$1 == $2"         echo "$1 é igual a $2" Adbeel Goes Filho

   Shell­Scripts                                                                           59

else         echo "$1 é menor que $2" fi  4.

Tomadas de decisão com && e ||

Esta   maneira   de   tomar   decisões   é   bem   compacta,   mas   não   aceita   "else".   Eu,  particularmente, prefiro usar esta estrutura quando vou fazer uma tomada de decisão e não preciso  de "else". A maneira de usar é:    comando1 && comando2    comando1 || comando2 O   &&   executa   o   primeiro   comando   e   somente   se   este   retornar   0   (não   ocorrer  problemas) o segundo será executado. O || executa o primeiro comando e somente se este retornar  não­zero (ocorrer problemas) o segundo será executado. Veja um exemplo bem simples: $ [ ­d ~/tempdir ] || mkdir ~/tempdir Como você deve estar lembrado, "[ ­d ~/tempdir ]" é o mesmo que "test ­d ~/tempdir" e  retornará 0 se existir o diretório ~/tempdir. Caso não exista ele retornará 1, e neste caso o "mkdir  ~/tempdir" será executado. Vejamos um parecido usando o &&: $ [ ­d ~/tempdir ] && ls ­ld ~/tempdir Listas As listas de comandos servem para agrupar comandos. Podem ser representadas por  (parenteses) ou {chaves}. A diferença é que os (parenteses) executam os comandos num  shell  a  parte e as {chaves} executam no shell atual. Execute comando a seguir e tente entendê­lo (está certo... são vários comandos, mas  inicialmente é encarado com um comando só). Exemplo: [ ­d /usr/doc ] && { echo "O diretorio existe" echo "veja o seu conteudo" cd /usr/doc ls } E observe que ao final da execução você estará no diretório /usr/doc, o que comprova  que com as {chaves} os comandos são executados no  shell  atual, se você trocar as {chaves} por  Adbeel Goes Filho

   Shell­Scripts                                                                           60

(parênteses) observará que o seu diretório não se alterará. FYI: para saber o diretório atual o comando a ser usado é o "pwd". Expressões Aritméticas Expressões   aritméticas   consistem   com   comparar   dois   números,   verificando   se   são  iguais, ou se o primeiro é maior que o segundo etc. Infelizmente não podemos apenas utilizar os símbolos conhecidos para igual (=), maior  que   (>),   menor   que   ( Amigos do $REGIAO:\e[m"         for amigo in $NOMES ; do                 echo "$amigo"         done         echo done Mas a coisa não é tão simples assim... Se dentro do loop você quisesse usar o comando  read para ler do teclado, seria necessário pegar a entrada de "/dev/tty". Sabendo que o /dev/tty é o  terminal que você está usando. Se você tiver muitos amigos no arquivo "amigos.regiao" não vai conseguir ver todos, pois a lista não caberá numa tela só. Neste caso, o script a seguir será melhor  que o "listamigos.sh". #!/bin/bash egrep ­v "^#|^ *$" amigos.regiao | while read REGIAO NOMES ; do         echo ­e "\n\e[32;1m­­> Amigos do $REGIAO:\e[m"         for amigo in $NOMES ; do                 echo ­e "\e[1m$amigo\e[m"         done         echo ­ne "\nEntre  para continuar ou 'sair' para sair: "         read QUIT cat file      O gato preto foi caçado por um cachorro marrom.      >sed ­e 's/preto/branco/g' file      O gato branco foi caçado por um cachorromarrom. Exemplo 2:      >cat file     O gato preto foi caçado por um cachorro marrom. Adbeel Goes Filho

   Shell­Scripts                                                                           111

    O gato preto não foi caçado por um cachorro marrom.     >sed ­e '/não/s/preto/branco/g' file     O gato preto foi caçado por um cachorro marrom.     O gato branco não caçado por um cachorro marrom.  Neste caso, a substituição é aplicada somente a linhas que casam com a expressão regular "/não/".  Portanto, ela não é aplicada a primeira linha, pois esta não contem a palavra "não". Exemplo 3:      >cat file     linha 1 (um)     linha 2 (dois)     linha 3 (três) Exemplo 3a:      >sed ­e '1,2d' file     linha 3 (três) Exemplo 3b:      >sed ­e '3d' file      linha 1 (um)     linha 2 (dois) Exemplo 3c:      >sed ­e '1,2s/linha/LINHA/' file     LINHA 1 (um)     LINHA 2 (dois)     linha 3 (três) Exemplo 3d:      >sed ­e '/^linha.*um/s/linha/LINHA/' ­e  '/linha/d' file     LINHA 1 (um) 3a : Este foi bem simples: Nós apenas deletamos as linhas de 1 até 2 3b : Isto também foi simples: Nós deletamos a linha 3. 3c : Neste exemplo, nós fizemos uma substituição nas linhas 1 até 2. 3d : Agora este é mais interessante e merece  algumas explicações.   O primeiro comando vai procurar "^linha.*um" e substituir "linha" por "LINHA", ou  seja, somente a primeira linha casa com essa expressão regular. O segundo comando diz para o sed  deletar   linhas   que   contenham   a   palavra   "linha".   Assim,   somente   as   duas   últimas   linhas   serão  Adbeel Goes Filho

   Shell­Scripts                                                                           112

deletadas, já que a primeira teve palavra "linha" substituída por "LINHA". Exemplo 4:      >cat file     olá     Este texto será cortado     olá (também será retirado)     ReTiRaDo Também!!!     tchau     (1) Este texto não foi apagado     (2) nem este ... ( tchau )     (3) nem este     olá     mas este será     e este também     e a menos que nós encontremos outro tch*u     cada linha até o final do texto será  apagada     >sed ­e '/olá/,/tchau/d' file     (1) Este texto não foi apagado     (2) nem este ... ( tchau )     (3) nem este Isto mostra como o endereçamento funciona quando dois endereços são especificados.  O sed encontra o primeiro casamento da expressão "olá" e deleta todas as linhas lidas na área de  edição   até   ele   encontrar   a   primeira   linha   que   contém   a   expressão   "tchau"   (está   também   será  apagada). Ele não aplica mais o comando de deleção para nenhuma linha até encontrar novamente a  expressão "olá". Desde que a expressão "tchau" não ocorre mais em nenhuma linha subseqüente, o  comando de deleção é aplicado até o final do texto. Resumindo, é simples: Quando ele encontra o  primeiro   endereço  ("olá")   ele  passa  a   executar  os   comandos   até  encontrar  o  segundo  endereço  ("tchau") ou o fim do texto. E isso se repete até acabar o texto. Exemplo 5:      >cat file     http://www.kernel.org/     >sed ­e 's@http://www.kernel.org@http://www.metalab.un c.edu@' file     http://www.metalab.unc.edu/  Note que nós usamos um delimitador diferente, @ para o comando de substituição. O  sed permite  diversos delimitadores para o comando de substituição, incluindo @ % , ; : Esses  delimitadores alternativos são bons para substituições que incluem string como nome de arquivos e  outras que contém barra normal /, o que torna o código do sed muito mais legível. Adbeel Goes Filho

   Shell­Scripts                                                                           113

Mais alguns comandos Aqui veremos mais alguns comandos sobre o sed, a maioria  deles   mais   complexos.   Dependendo   da   aplicação   em   que   vocês   forem   usar   o   sed,   dificilmente  usarão   esses   recursos,   a   menos   que   precisem   de   um   processamento   de   texto   mais   refinado   e  complexo. Veja que eles são muito usado nos scripts do sed (não confunda com shell­script). Backreference no Sed  Uma das coisas legais sobre backreference no sed é que você pode usar não apenas em  procura de textos mas também na substituição de textos. O comando Quit  O comando quit ou "q" é muito simples. Ele simplesmente termina o processamento.  Nenhuma outra linha é lida para a área de edição ou impressa na saída padrão. Sub­rotinas  Nós agora introduzimos o conceito de sub­rotinas no sed: No   sed,   as   chaves   {   }   são   usadas   para   agrupar   comandos.   Elas   são   usadas   dessa 

maneira: endereço1[,endereço2]{comandos}

Exemplo: Encontrar uma palavra de uma lista num arquivo  Este exemplo faz um bom uso dos conceitos descritos acima. Para isto, nos usamos um  shell­script, desde que os comandos são muito longos e precisaríamos escrever a longa string X  várias vezes. Note que usamos aspas duplas, já que a variável $X precisa ser expandida pelo shell. A  sintaxe para rodar esse script é: "script arquivo",onde "script" é o nome dado ao script e "arquivo" é  o nome do arquivo a procurar uma palavra da lista. #!/bin/sh X='word1\|word2\|word3|\word4|\word5' sed ­e " /$X/!d /$X/{        s/\($X\).*/\1/        s/.*\($X\)/\1/        q        }" $1 Uma nota importante: é tentador pensar que:     s/\($X\).*/\1/     s/.*\($X\)/\1/ é redundante e tentar encurtá­la para: Adbeel Goes Filho

   Shell­Scripts                                                                           114

    s/.*\($X\).*/\1/  Mas isto não funciona. Por que? Suponha que temos a linha:     word1 word2 word3 Nós não temos como saber se $X vai casar com word1, word2 ou word3, então quando  nós citamos ele (\1), nós não sabemos quais dos termos está sendo citado. O que está sendo usado  para certificar­se que não há problemas na correta implementação, é isto: "O operador * é guloso. Ou seja, quando há ambigüidade sobre qual (expressão)* pode casar, ele  tentar casar o máximo possível."  Então neste exemplo, s/\($X\).*/\1/ , .* tenta engolir o máximo da linha possível, em  particular, se a linha contém isso:       "word1 word2 word3" Então nós podemos ter certeza que .* casa com " word2 word3" e portanto $X seria  word1. Não se preocupem se não entenderam muito bem este tópico. Ele é complicado mesmo e  pouco   usado.   O   importante   é   entender   como   ele   funciona,   o   uso   de   regexp   e   do   comando   de  substituição e deleção. Para maiores informações sobre o sed, dê uma olhada na sua man page:  "man sed" . Espero que vocês tenham gostado desse pequeno tutorial sobre sed.  Linguagens Complementares

AWK Exemplo: exibir a terceira, quarta e nona colunas do saida de  um comando ls ­l /home/satis | awk ' {print $3, $r, $9}'

PHP

Adbeel Goes Filho

   Shell­Scripts                                                                           115

Capitulo 6. Bibliografia

ADBEEL

Goes, Adbeel. Programação Shell­Script. VIRTVS Engenharia e Informática  Ltda. Fortaleza, Outubro de 2001.

ALEX

Borro, Alex. Tutorial de Shell Script

RRM2000

Raimundo,   Rodivaldo   Marcelo.  Curso   Básico   de   Programação   em   Posix   Shell­Script. Book Express. Rio de Janeiro, 2000.

JULIO 

    Neves, Júlio Cezar. Programação Shell Linux, 3ª Edição, Editora Brasport,  ISBN 85­7452­118­3

SAADE

    Saade, Joel. BASH ­ Guia de Consulta Rápida, Editora Novatec, ISBN 85­ 7522­006­3

       

Adbeel Goes Filho

   Shell­Scripts                                                                           116

Capitulo 7. Apêndice A – Endereços Internet 1

Guia focalinux

http://www.focalinux.org 

2

Adv­Bash­Scr­HOWTO

http://www.linuxdoc.org   

3

Programação de Shell Scripts

http://unsekurity.virtualave.net/txts/shscript.txt 

4

UNIX Bourne Shell Programmin http://www.torget.se/users/d/Devlin/    shell     

5

Bash FAQ 

ftp://ftp.cwru.edu/pub/bash/FAQ 

6

Bash Reference Manual

http://www.gnu.org/manual/bash­2.02/bashref.html 

7

Bourne­Again SHell Home Page

http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html 

8

Underlinux 

http://sh.underlinux.com.br 

9

Expressões Regulare

http://guia­er.sourceforge.net 

10

sed­HOWTO

http://verde666/sed 

11

Programação em Shell Script

  http://www.jonathas.com.br/manual­  shell    .txt     

12

UNIX Power Tools

http://docs.online.bg/OS/unix_power_tools/index.htm 

13

Linux: Programação Shell

http://www.brasport.com.br 

14

Verdade Absoluta

http://www.absoluta.org

15

Wargames 

www.pulltheplug.com www.hackerslab.org 

16

Lista de discussão nacional sobre  http://br.groups.yahoo.com/group/shell­script  Shell Script

17

Dicas

http://www.semlimites.com.br/informatica/informatica_ software_sistemasoperacionais_unix_linux.shtm  

18

IBM­AIX

http://www.ibm.com 

19

Unix – Perguntas e respostas

http://www.klingon.com.br/unix/unix.html 

20

Introdução ao Unix

http://www.nicke.fenixnet.ccom.br/unix.html 

21

Criando   programas   usando   o  htttp://www.icmsc.sc.usp.br/manuais/UNIX    Shell

  

Adbeel Goes Filho

   Shell­Scripts                                                                           117

Capitulo 8. Anexos

Adbeel Goes Filho

   Shell­Scripts                                                                           118

1. Exemplos

 7.

Matemática

Soma de n números naturais #!/bin/sh clear echo "Qual o número ?" read n soma=0 for w_i in $(seq 1 $n ) ;      do        soma=$( expr $soma + $w_i)     done echo "A soma dos $n primeiros números naturais é $soma" exit 0 Fatorial #!/bin/sh clear read ­p "Qual o número para o cálculo do fatorial ?" n if [ $n ­le 0 ];    then       echo "Não existe fatorial de número negativo"       exit 1 fi; fatorial=1 for  w_i in $( seq 1 $n ) ;       do         fatorial=$[ $fatorial * $w_i ]      done echo "O fatorial de $n é $fatorial" exit 0

Adbeel Goes Filho

   Shell­Scripts                                                                           119

 8.

Acesso

Como ter apenas um login por usuário  #!/bin/sh # vi /usr/bin/login_unico  VAR=`who | cut ­c1­8 | tr ­d "\040" | grep ­n "^\'echo $LOGNAME\`$" |wc ­l`  if [ $VAR ­gt 1 ] && [ $LOGNAME = "root" ]      then      echo MENSAGEM DE LOGIN INVALIDO      sleep 10       exit  fi  # chmod 755 login_unico  # vi /etc/profile  ...  Como repetir os últimos comandos no Unix Arquivo de controle : $HOME/.sh_history  Total de cmds .........: 171 (em media)  Ativacao .................: set ­o vi  Shell responsável .....: ksh  Inclua o comando de ativação no arquivo $HOME/.profile.  Incluir no arquivo /etc/passwd:  ... ... usuario:senha:nr_usuario:grupo:comentario:dir_trabalho:/bin/ksh  Para mostrar e executar os últimos comandos tecle ESCape "k"  Transferência de arquivos em redes TCP/IP (Script Shell)  ­ Crie no /usr/bin um arquivo chamado envia e outro recebe com os seguintes conteúdos:  Arquivo envia:  #!/bin/sh  a=$1  shift  ftp ­i $a > $HOME/ftp.log /dev/null` [ `echo $FILE | wc ­w` ­gt 1 ] && {    PS3="Entre com o número: "    select opc in $FILE Sair ; do         [ "$opc" = "Sair" ] && exit         for HOWTO in $FILE ; do             [ "$opc" = "$HOWTO" ] && Ler $HOWTO         done     done Adbeel Goes Filho

   Shell­Scripts                                                                           124

} [ ­e "$FILE" ] && Ler $FILE # Isto só será executado se não for encontrado o HOWTO echo ­e "${RED}* * * HOWTO não encontrado * * *$NCOLOR" echo "Tente '`basename $0` [­p | ­m]' para ver a lista" exit 1  12.

todo.sh

  #!/bin/bash PROG=`basename $0` EDITOR=`which vi` FILE="$HOME/.ToDo" USAGE="Uso: $PROG [­h|­e]" case $1 in         ­h) echo " $USAGE ­e      edita a lista de \"Para Fazer\" (To Do) ­h      imprime esta mensagem e sai Sem parâmetros $PROG irá mostrar a lista de \"To­Do\". "             exit ;;         ­e) $EDITOR $FILE             exit ;;         '') cat $FILE 2> /dev/null || {                 echo "Você precisa criar o arquivo $HOME/.ToDo !"                 echo "Entre \"$PROG ­e\" para editar seu ~/.ToDo"                 echo "Para ajuda tente \"$PROG ­h\""                 exit 1             } ;;         *) echo "Parâmetro \"$1\" desconhecido!"            echo "$USAGE"            echo "Entre com \"$PROG ­h\" para ajuda."            exit ;;

Adbeel Goes Filho

   Shell­Scripts                                                                           125

esac    13.

inseretxt.sh

  #!/bin/bash # # Muitas vezes durante a escrita do texto # "Programação em Bourne­Again Shell" eu precisava # inserir um código de um script numa determinada # posição do arquivo e esta posição ficava entre muito texto antes e depois  # dessa linha. # Para fazer isso de uma maneira mais cômoda, eu escrevi este script. # Para informações sobre o uso tente o parâmetro '­h' ou # '­­help'. # Se você passar como o parâmetro "linha" um número maior # que o de linhas total do "ArqOriginal" os "arquivosN" # serão inseridos no final do "ArqOriginal". # Ah! Lembre­se de uma coisa: "linha" precisa ser um # inteiro positivo. E lembre­se de mais uma coisa: 0 # não é um número positivo. ;­) # meleu. # B="\e[1m" N="\e[m" USO="Uso: `basename $0` linha ArqOriginal arquivo1 [arquivoN ...]" AJUDA="Tente \"`basename $0` ­­help\" para ajuda" [ "$1" = '­h' ­o "$1" = '­­help' ] && {     echo ­e " ${B}Insere o conteúdo de arquivo(s) dentro de um outro.$N $USO Onde: \"linha\"       é a linha onde o texto será inserido \"ArqOriginal\" é o arquivo que receberá os textos  \"arquivoN\"    são os arquivos que serão inseridos em ArqOriginal "     exit } [ $# ­lt 3 ] && { Adbeel Goes Filho

   Shell­Scripts                                                                           126

    echo ­e ${B}Erro: erro na passagem de parâmetros$N     echo $USO     echo $AJUDA     exit ­1 } Linha=$1 # verificando se $Linha é um número inteiro positivo [ `expr $Linha ­ 1 2>/dev/null` ­ge 0 ] 2>/dev/null || {     echo ­e ${B}Erro: O primeiro parâmetro precisa ser inteiro positivo$N     echo $AJUDA     exit 1 } ArqOriginal=$2 [ ­f $ArqOriginal ] || {     echo ­e ${B}Erro: \"$ArqOriginal\" não existe ou não é um arquivo regular$N     echo $AJUDA     exit 2 } function ApagarSair {     rm "$1"     exit $2 } shift 2 Temp=/tmp/`basename $ArqOriginal`­$$.tmp # ­­> início do arquivo original: head ­$[$Linha­1] $ArqOriginal > $Temp # ­­> arquivos que serão inseridos: ContaAcerto=0 for Arq in "$@"; do     [ ­f "$Arq" ] || {         echo ­e ${B}OBS.: \"$Arq\" não existe ou não é um arquivo regular$N         continue     }     cat $Arq >> $Temp     (( ContaAcerto++ )) done [ $ContaAcerto ­eq 0 ] && {     echo ­e ${B}Nenhum arquivo foi inserido em \"$ArqOriginal\"$N     ApagarSair $Temp 3 Adbeel Goes Filho

   Shell­Scripts                                                                           127

} echo # ­­> pra terminar, final do arquivo original: sed ­n "$Linha,\$p" $ArqOriginal >> $Temp ArqFinal="$ArqOriginal.new" [ ­e $ArqFinal ] && {     echo ­e ${B}Já existe um arquivo chamado \"$ArqFinal\".$N     read ­n 1 ­p "Deseja sobregravá­lo? (s/N) " SN     echo     [ "$SN" != 'S' ­a "$SN" != 's' ] && {         echo ­e "$B\nOperação cancelada!$N"         ApagarSair $Temp 3     } } cat $Temp > $ArqFinal echo ­e " ${B}Operação concluída com sucesso.$N Confira em \"$ArqFinal\" " ApagarSair $Temp    14.

Mextract.sh

#!/bin/sh # # **************************** # * Meleu Extraction Utility * # **************************** # http://meleu.da.ru # Este script é baseado no Phrack Extraction Utility, (mais informações # ). Fiz ele, primeiro para praticar, segundo para # servir como mais um exemplo no texto "Programação em Bourne­Again Shell",  # e último para extração dos códigos do texto. =P # ############# Se já existirem arquivos com o nome dos que serão extraídos # !CUIDADO! # eles serão sobregravados! Portanto, se você extrair uma vez, ############# alterar o(s) código(s) extraído(s) e extrair novamente, perderá as alterações feitas! # # Adbeel Goes Filho

   Shell­Scripts                                                                           128

#   A seguir eu vou comentar sobre o código fazendo referência aos tópicos # do texto "Programação em Bourne­Again Shell". # # #    + A função do IFS é explicada no tópico "2.2. Variáveis do Shell", neste script eu usei o IFS  com valor nulo (vazio) para que os comandos considerem espaços que vêm antes de qualquer  caractere como parte do dado. Se você fizer por exemplo "read var" e antes de entrar qualquer # coisa colocar espaços e/ou TAB, você verá que eles serão desconsiderados se o IFS tiver seu valor  default (espaço, TAB, newline); # #    + A opção ­r no read (explicada em 3.2. read) serve para ignorar o # poder que a contra­barra (backslash) tem de "escapar" os caracteres. Em # outras palavras: a opção ­r garante que quando o read receber uma # contra­barra ela será passada para a variável sem nenhum valor especial; # #    + O cat enviando os dados para o read do while é explicado em # "5.5. Redirecionando loops" sob o título de "pipeando para o while"; # #    + o set é usado para fazer com que cada palavra (palavra aqui tem um # sentido de conjunto de caracteres separados por aqueles definidos no # IFS) vire um parâmetro posicional, conforme explicado em # "2.4.2. set (para editar parâmetros posicionais)". A opção ­­ quer dizer # "acabaram as opções, o que vier a partir daqui são os valores dos # parâmetros de posição", esta opção serve para prevenir que alguma # informação que comece com o caractere ­ seja considerado uma opção # sendo passada para o set; # #    + No tópico "2.5. Substituição de Variáveis" você verá a explicação # de se usar "FILE=${FILE:­.}/$1"; # #    + Bom... acho que é isso. Leia o código, execute­o, faça testes, # mude o código, execute­o novamente, veja o que mudou nos resultados, # leia as manpages em caso de dúvidas... Enfim, use o método hacker de # aprender a programar! ;­) # Espero que curta! # meleu  # # P.S.: Quer um "dever de casa"? Altere o código para que ele verifique #       se já existe arquivos com o mesmo nome dos que estão prestes a #       serem extraídos. Se existir, alertar o usuário sobre isso. Tente #       também fazer meios de detecção dos possíveis erros que possam #       ocorrer... #       Ah, sei lá! Brinque com o código um pouco! =) # B="\e[1m" Adbeel Goes Filho

   Shell­Scripts                                                                           129

N="\e[m" [ $# ­lt 1 ] && {     echo ­e "${B}Erro: falta parâmetros$N"     echo "Uso: `basename $0` arquivo1 [arquivoN]"     exit 1 } [ ­w . ] || {     echo ­e "${B}Erro: você não tem permissão de escrita neste diretório$N"     exit 1 } OldIFS="$IFS" IFS= cat $@ | while read ­r LINHA ; do         IFS="$OldIFS"         set ­­ $LINHA         case "$1" in         '')                 TempIFS="$IFS"                 IFS=/                 set ­­ $2                 IFS="$TempIFS"                 while [ $# ­gt 1 ]; do                     FILE=${FILE:­.}/$1                     [ ­d $FILE ] || mkdir $FILE                     shift                 done                 FILE="${FILE:­.}/$1"                 if echo ­n 2>/dev/null > $FILE ; then                     echo "* Extraindo $FILE"                 else                     echo ­e "$B­­> houve um erro ao tentar extrair '$FILE'"                     echo ­e "    este arquivo será ignorado.$N"                     unset FILE                 fi                         ;;         '')                 unset FILE         ;;         *)                 [ "$FILE" ] && {                     IFS=                     echo "$LINHA" >> $FILE Adbeel Goes Filho

   Shell­Scripts                                                                           130

                }         ;;         esac done echo "­­> Fim 
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF