64
Primeira parte, uma introdução Quem usa Linux conhece bem o prompt de comando sh, ou variações como o bash. O ue muita gente não sabe é que o sh ou o bash têm uma “poderosa” linguagem de script embutido nelas mesmas. Diversas pessoas utilizam-se desta linguagem para facilitar a realização de inúmeras tarefas administrativas no Linux, ou até mesmo criar seus próprios programinhas. Patrick Volkerding, criador da distribuição Slackware, utiliza esta linguagem para toda a instalação e configuração de sua distribuição. Você poderá criar scripts para automar as tarefas diárias de um servidor, para efetuar backup automático regularmente, procurar textos, criar formatações, e muito mais. Para você ver como esta linguagem pode ser útil, vamos ver alguns passos introdutórios sobre ela. Interpretadores de comandos são programas feitos para intermediar o usuário e seu sistema. Através destes interpretadores, o usuário manda um comando, e o interpretador o executa no sistema. Eles são a “Shell” do sistema Linux. Usaremos o interpretador de comandos bash, por ser mais “extenso” que o sh, e para que haja uma melhor compreensão das informações obtidas aqui, é bom ter uma base sobre o conceito de lógica de programação. Uma das vantagens destes shell scripts é que eles não precisam ser compilados, ou seja, basta apenas criar um arquivo texto qualquer, e inserir comandos à ele. Para dar à este arquivo a definição de “shell script”, teremos que incluir uma linha no começo do arquivo (#!/bin/bash) e torná-lo “executável”, utilizando o comando chmod. Vamos seguir com um pequeno exemplo de um shell script que mostre na tela: “Nossa! Estou vivo!”: #!/bin/bash echo 'Nossa! Estou vivo!' Fácil, hein? A primeira linha indica que todas as outras linhas abaixo deverão ser executadas pelo bash (que se localiza em /bin/bash), e a segunda linha imprimirá na tela a frase “Nossa! Estou vivo!”, utilizando o comando echo, que serve justamente para isto. Como você pôde ver, todos

Iniciação em Shell

Embed Size (px)

Citation preview

Page 1: Iniciação em Shell

Primeira parte, uma introdução

Quem usa Linux conhece bem o prompt de comando sh, ou variações como o bash. O ue muita gente não sabe é que o sh ou o bash têm uma “poderosa” linguagem de script embutido nelas mesmas. Diversas pessoas utilizam-se desta linguagem para facilitar a realização de inúmeras tarefas administrativas no Linux, ou até mesmo criar seus próprios programinhas. Patrick Volkerding, criador da distribuição Slackware, utiliza esta linguagem para toda a instalação e configuração de sua distribuição. Você poderá criar scripts para automar as tarefas diárias de um servidor, para efetuar backup automático regularmente, procurar textos, criar formatações, e muito mais. Para você ver como esta linguagem pode ser útil, vamos ver alguns passos introdutórios sobre ela.

Interpretadores de comandos são programas feitos para intermediar o usuário e seu sistema. Através destes interpretadores, o usuário manda um comando, e o interpretador o executa no sistema. Eles são a “Shell” do sistema Linux. Usaremos o interpretador de comandos bash, por ser mais “extenso” que o sh, e para que haja uma melhor compreensão das informações obtidas aqui, é bom ter uma base sobre o conceito de lógica de programação.

Uma das vantagens destes shell scripts é que eles não precisam ser compilados, ou seja, basta apenas criar um arquivo texto qualquer, e inserir comandos à ele. Para dar à este arquivo a definição de “shell script”, teremos que incluir uma linha no começo do arquivo (#!/bin/bash) e torná-lo “executável”, utilizando o comando chmod. Vamos seguir com um pequeno exemplo de um shell script que mostre na tela: “Nossa! Estou vivo!”:

#!/bin/bashecho 'Nossa! Estou vivo!'

Fácil, hein? A primeira linha indica que todas as outras linhas abaixo deverão ser executadas pelo bash (que se localiza em /bin/bash), e a segunda linha imprimirá na tela a frase “Nossa! Estou vivo!”, utilizando o comando echo, que serve justamente para isto. Como você pôde ver, todos os comandos que você digita diretamente na linha de comando, você poderá incluir no seu shell script, criando uma série de comandos, e é essa combinação de comandos que forma o chamado shell script. Tente também dar o comando ‘file arquivo’ e veja que a definição dele é de Bourne-Again Shell Script (Bash Script).

Contudo, para o arquivo poder se executável, você tem de atribuir o comando de executável para ele. E como citamos anteriormente, o comando chmod se encarrega disto:

$ chmod +x arquivo

Pronto, o arquivo poderá ser executado com um simples “./arquivo”.

Conceito de Variáveis em shell script

Variáveis são caracteres que armazenam dados, uma espécie de atalho. O bash reconhece uma variável quando ela começa com $, ou seja, a diferença entre ‘palavra’ e

Page 2: Iniciação em Shell

‘$palavra’ é que a primeira é uma palavra qualquer, e a outra uma variável. Para definir uma variável, utilizamos a seguinte sintaxe:

variavel="valor"

O ‘valor’ será atribuído a ‘variável ‘. Valor pode ser uma frase, números, e até outras variáveis e comandos. O valor pode ser expressado entre as aspas (“”), apóstrofos (”) ou crases (“). As aspas vão interpretar as variáveis que estiverem dentro do valor, os apóstrofos lerão o valor literalmente, sem interpretar nada, e as crases vão interpretar um comando e retornar a sua saída para a variável.

Vejamos exemplos:

$ variavel="Eu estou logado como usuário $user"$ echo $variavel Eu estou logado como usuário cla

$ variavel='Eu estou logado como usuário $user'$ echo $variavel Eu estou logado como usuário $user

$ variavel="Meu diretório atual é o `pwd`"$ echo $variavel Meu diretório atual é o /home/cla

Se você quiser criar um script em que o usuário deve interagir com ele, é possível que você queira que o próprio usuário defina uma variável, e para isso usamos o comando read, que dará uma pausa no script e ficarará esperando o usuário digitar algum valor e teclar enter. Exemplo:

echo "Entre com o valor para a variável: " ; read variavel(O usuário digita e tecla enter, vamos supor que ele digitou 'eu sou um frutinha')echo $variavel eu sou um frutinha

Controle de fluxo com o if

Controle de fluxo são comandos que vão testando algumas alternativas, e de acordo com essas alternativas, vão executando comandos. Um dos comandos de controle de fluxo mais usados é certamente o if, que é baseado na lógica “se acontecer isso, irei fazer isso, se não, irei fazer aquilo”.

Vamos dar um exemplo:

if [ -e $linux ]then echo 'A variável $linux existe.'else echo 'A variável $linux não existe.'fi

O que este pedaço de código faz? O if testa a seguinte expressão: Se a variável $linux existir, então (then) ele diz que que existe com o echo, se não (else), ele diz que não

Page 3: Iniciação em Shell

existe. O operador -e que usei é pré-definido, e você pode encontrar a listagem dos operadores na tabela:

-eq Igual

-ne Diferente

-gt Maior

-lt Menor

-o Ou

-d Se for um diretório

-e Se existir

-z Se estiver vazio

-f Se conter texto

-o Se o usuário for o dono

-r Se o arquivo pode ser lido

-w Se o arquivo pode ser alterado

-x Se o arquivo pode ser executado

Outras alternativas

Existem inúmeros comandos no Linux, e para explicar todos, teríamos de publicar um verdadeiro livro. Mas existem outras possibilidades de aprendizado desta língua, que também é usado em todas as programações. Primeiro de tudo você pode dar uma olhada na manpage do bash (comando man bash), que disponibilizará os comandos embutidos no interpretador de comandos. Uma das coisas essencias para o aprendizado é sair coletando exemplos de outros scripts e ir estudando-os minuciosamente. Procure sempre comandos e expressões novas em outros scripts e em manpages dos comandos. E por último, mas não o menos importante, praticar bastante!

Na tabela a seguir, você pode encontrar uma listagem de comandos para usar em sua shell script:

echo Imprime texto na tela

read Captura dados do usuário e coloca numa variável

exit Finaliza o script

sleep Dá uma pausa em segundos no script

clear Limpa a tela

stty Configura o terminal temporariamente

tput Altera o modo de exibição

if Controle de fluxo que testa uma ou mais expressões

case Controle de fluxo que testa várias expressões ao mesmo tempo

for Controle de fluxo que testa uma ou mais expressões

while Controle de fluxo que testa uma ou mais expressões

Page 4: Iniciação em Shell

E assim seja, crie seus próprios scripts e facilite de uma vez só parte de sua vida no Linux!

Segunda parte, se aprofundando mais!

Falamos sobre o conceito da programação em Shell Script, e demos o primeiro passo para construir nossos próprios scripts. Agora vamos nos aprofundar nos comandos mais complicados, aprendendo a fazer programas ainda mais úteis. Nestes comandos estão inclusos o case e os laços for, while e until. Além disso, vamos falar de funções e, por último, teremos um programa em shell script.

Case

O case é para controle de fluxo, tal como é o if. Mas enquanto o if testa expressões não exatas, o case vai agir de acordo com os resultados exatos. Vejamos um exemplo:

case $1 in parametro1) comando1 ; comando2 ;; parametro2) comando3 ; comando4 ;; *) echo "Você tem de entrar com um parâmetro válido" ;;esac

Aqui aconteceu o seguinte: o case leu a variável $1 (que é o primeiro parâmetro passado para o programa), e comparou com valores exatos. Se a variável $1 for igual à “parametro1″, então o programa executará o comando1 e o comando2; se for igual à “parametro2″, executará o comando3 e o comando4, e assim em diante. A última opção (*), é uma opção padrão do case, ou seja, se o parâmetro passado não for igual a nenhuma das outras opções anteriores, esse comando será executado automaticamente.

Você pode ver que, com o case fica muito mais fácil criar uma espécie de “menu” para o shell script do que com o if. Vamos demonstrar a mesma função anterior, mas agora usando o if:

if [ -z $1 ]; then echo "Você tem de entrar com um parâmetro válido" exitelif [ $1 = "parametro1" ]; then comando1 comando2elif [ $1 = "parametro2" ]; then comando3 comando4else echo "Você tem de entrar com um parâmetro válido"fi

Veja a diferença. É muito mais prático usar o case! A vantagem do if é que ele pode testar várias expressões que o case não pode. O case é mais prático, mas o if pode substituí-lo e ainda abrange mais funções. Note que, no exemplo com o if, citamos um “comando” não visto antes: o elif – que é uma combinação de else e if. Ao invés de fechar o if para criar outro, usamos o elif para testar uma expressão no mesmo comando if.

Page 5: Iniciação em Shell

For

O laço for vai substituindo uma variável por um valor, e vai executando os comandos pedidos. Veja o exemplo:

for i in *do cp $i $i.backup mv $i.backup /usr/backupdone

Primeiramente o laço for atribuiu o valor de retorno do comando “*” (que é equivalente a um ls sem nenhum parâmetro) para a variável $i, depois executou o bloco de comandos. Em seguida ele atribui outro valor do comando “*” para a variável $1 e reexecutou os comandos. Isso se repete até que não sobrem valores de retorno do comando “*”. Outro exemplo:

for original in *; do resultado=`echo $original | tr '[:upper:]' '[:lower:]'` if [ ! -e $resultado ]; then mv $original $resultado fidone

Aqui, o que ocorre é a transformação de letras maiúsculas para minúsculas. Para cada arquivo que o laço lê, uma variável chamada $resultado irá conter o arquivo em letras minúsculas. Para transformar em letras minúsculas, usei o comando tr. Caso não exista um arquivo igual e com letras minúsculas, o arquivo é renomeado para o valor da variável $resultado, de mesmo nome, mas com letras minúsculas.

Como os exemplos ilustram, o laço for pode ser bem útil no tratamento de múltiplos arquivos. Você pode deixá-los todos com letras minúsculas ou maiúsculas sem precisar renomear cada um manualmente, pode organizar dados, fazer backup, entre outras coisas.

While

O while testa continuamente uma expressão, até que ela se torne falsa. Exemplo:

variavel="valor"while [ $variavel = "valor" ]; do comando1 comando2done

O que acontece aqui é o seguinte: enquanto a “$variavel” for igual a “valor”, o while ficará executando os comandos 1 e 2, até que a “$variavel” não seja mais igual a “valor”. Se no bloco dos comandos a “$variavel” mudasse, o while iria parar de executar os comandos quando chegasse em done, pois agora a expressão $variavel = “valor” não seria mais verdadeira.

Until

Page 6: Iniciação em Shell

Tem as mesmas características do while, a única diferença é que ele faz o contrário. Veja o exemplo abaixo:

variavel="naovalor"until [ $variavel = "valor" ]; do comando1 comando2done

Ao invés de executar o bloco de comandos (comando1 e comando2) até que a expressão se torne falsa, o until testa a expressão e executa o bloco de comandos até que a expressão se torne verdadeira. No exemplo, o bloco de comandos será executado desde que a expressão $variavel = “valor” não seja verdadeira. Se no bloco de comandos a variável for definida como “valor”, o until pára de executar os comandos quando chega ao done.

Vejamos um exemplo para o until que, sintaticamente invertido, serve para o while também:

var=1count=0until [ $var = "0" ]; do comando1 comando2 if [ $count = 9 ]; then var=0 fi count=`expr $count + 1`done

Primeiro, atribuímos à variável “$var” o valor “1″. A variável “$count” será uma contagem para quantas vezes quisermos executar o bloco de comandos. O until executa os comandos 1 e 2, enquanto a variável “$var” for igual a “0″. Então usamos um if para atribuir o valor 0 para a variável “$var”, se a variável “$count” for igual a 9. Se a variável “$count” não for igual a 0, soma-se 1 a ela. Isso cria um laço que executa o comando 10 vezes, porque cada vez que o comando do bloco de comandos é executado, soma-se 1 à variável “$count”, e quando chega em 9, a variável “$var” é igualada a zero, quebrando assim o laço until.

Usando vários scripts em um só

Pode-se precisar criar vários scripts shell que fazem funções diferentes, mas, e se você precisar executar em um script shell um outro script externo para que este faça alguma função e não precisar reescrever todo o código? É simples, você só precisa incluir o seguinte comando no seu script shell:

. bashscript2

Isso executará o script shell “bashscript2″ durante a execução do seu script shell. Neste caso ele será executado na mesma script shell em que está sendo usado o comando. Para utilizar outra shell, você simplesmente substitui o “.” pelo executável da shell, assim:

sh script2

Page 7: Iniciação em Shell

tcsh script3

Nessas linhas o script2 será executado com a shell sh, e o script3 com a shell tcsh.

Variáveis especiais

$0 Nome do script que está sendo executado

$1-$9 Parâmetros passados à linha de comando

$# Número de parâmetros passados

$?Valor de retorno do último comando ou de todo o shell script. (o comando “exit 1″ retorna o valor 1)

$$ Número do PID (Process ID)

Você também encontra muitas variáveis, já predefinidas, na página de manual do bash (comando “man bash”, seção Shell Variables).

Funções

Funções são blocos de comandos que podem ser definidos para uso posterior em qualquer parte do código. Praticamente todas as linguagens usam funções que ajudam a organizar o código. Vejamos a sintaxe de uma função:

funcao() { comando1 comando2 ...}

Fácil de entender, não? A função funcionará como um simples comando próprio. Você executa a função em qualquer lugar do script shell, e os comandos 1, 2 e outros serão executados. A flexibilidade das funções permite facilitar a vida do programador, como no exemplo final.

Exemplo Final

Agora vamos dar um exemplo de um programa que utilize o que aprendemos com os artigos.

#!/bin/bash# Exemplo Final de Script ShellPrincipal() { echo "Exemplo Final sobre o uso de scripts shell" echo "------------------------------------------" echo "Opções:" echo echo "1. Trasformar nomes de arquivos" echo "2. Adicionar um usuário no sistema" echo "3. Deletar um usuário no sistema" echo "4. Fazer backup dos arquivos do /etc" echo "5. Sair do exemplo" echo echo -n "Qual a opção desejada? "

Page 8: Iniciação em Shell

read opcao case $opcao in 1) Transformar ;; 2) Adicionar ;; 3) Deletar ;; 4) Backup ;; 5) exit ;; *) "Opção desconhecida." ; echo ; Principal ;; esac}Transformar() { echo -n "Para Maiúsculo ou minúsculo? [M/m] " read var if [ $var = "M" ]; then echo -n "Que diretório? " read dir for x in `/bin/ls` $dir; do y=`echo $x | tr '[:lower:]' '[:upper:]'` if [ ! -e $y ]; then mv $x $y fi done elif [ $var = "m" ]; then echo -n "Que diretório? " read dir for x in `/bin/ls` $dir; do y=`echo $x | tr '[:upper:]' '[:lower:]'` if [ ! -e $y ]; then mv $x $y fi done fi}Adicionar() { clear echo -n "Qual o nome do usuário a se adicionar? " read nome adduser nome Principal}Deletar() { clear echo -n "Qual o nome do usuário a deletar? " read nome userdel nome Principal}Backup() { for x in `/bin/ls` /etc; do cp -R /etc/$x /etc/$x.bck mv /etc/$x.bck /usr/backup done}Principal

Terceira parte, janelas graficas

Nos dois topicos anteriores, vimos algumas coisas básicas e lógicas de programação em shell no Linux. Agora para completar, darei aqui dicas de como usar janelas gráficas em

Page 9: Iniciação em Shell

seus shell-scripts. Isso mesmo, janelas que rodam no ambiente gráfico, utilizadas facilmente em seu shell-script. Com esse recurso, vai ser possível deixar o seu programa bem amigável.

Não vai ser preciso saber muita coisa de programação em shell, pois é muito simples. Através do programa Xdialog, você poderá criar os mais variados tipos de janelas para o programa: caixas de texto, seleçÕes, radios, etc. O Xdialog é uma idéia que vem do dialog/cdialog, um programa para console que gera “janelas” no console (aquelas da instalação do Slackware) usando a biblioteca ncurses. O Xdialog ao invés de usar a biblioteca ncurses, usa a Xlib para criar as janelas no ambiente gráfico.

Primeiro de tudo será necessário você obter o Xdialog no seu sistema. Não é comum o Xdialog estar incluso nas distribuições, então você terá de pegar e compilar o programa. Obtenha o programa no CD da Revista ou visite o endereço oficial do Xdialog, que é http://xdialog.free.fr. Aqui eu peguei o arquivo Xdialog-1.4.5.tar.bz2, e agora vamos aos passos básicos para instalar ele. Primeiro descompacte-o com o comando bunzip2 Xdialog-1.4.5.tar.bz2, e logo em seguida tar xpvf Xdialog-1.4.5.tar. Um diretório chamado Xdialog-1.4.5 será criado, e entrando nele você estará pronto para compilá-lo e instalá-lo. Para fazer isso use os comandos ./configure, depois make e por último make install. No passo do make install, o binário do Xdialog será colocado em /usr/local/bin. Pronto, agora você já poderá utilizar o Xdialog através de qualquer shell-script.

E agora vamos à ação! Como aprendemos nos artigos anteriores, em shell-script é só colocar o comando dentro do arquivo que ele já vai ser executado quando o script for executado. Então só o que temos de aprender aqui é como usar o Xdialog. Vamos ver um primeiro exemplo:

#!/bin/bash

Xdialog --title "Exemplo número 1!" --center --stdout --yesno \"Isto é legal?" \0 0

echo $?

Como você pôde ver, o programa Xdialog gerou uma janela com título “Exemplo número 1!”, perguntando “Isto é legal?” e com opções de Sim e Não. Note que a \ (barra) serve para indicar à shell para continuar o comando da linha seguinte, então estas três linhas são que nem uma só. Como último comando do exemplo dado, temos o echo $?, que eu coloquei apenas para indicar qual foi o retorno da pergunta. Caso o usuário apertou em Sim, o retorno vai ser 0, e se apertou em Não, vai ser 1. Podemos usar este retorno para controlar o que o usuário escolher. Vejamos um exemplo:

Xdialog --title "Exemplo número 2!" --center --stdout --yesno \"Neste exemplo, vamos ver o que você quer fazer. Você deseja continuar com o programa?" \0 0

if [ $? = "0" ]; then echo "Que bom! Você continuou o programa! Parabéns!"elif [ $? = "1" ]; then echo "Você saiu do programa..."

Page 10: Iniciação em Shell

fi

Viu como funciona? Agora vamos ver outros recursos que o Xdialog pode oferecer. Eu vou dar vários exemplos aqui e sair comentando cada opção. Você precisará praticar bastante e conhecer as várias opções. Primeiro vamos gerar uma simples mensagem pro usuário ver:

Xdialog --title "Aviso" --center --stdout --msgbox \"Este programa é apenas um exemplo para você ver como o Xdialog \\nfunciona. Apropósito, se você praticar bastante pode criar \\nprogra mas incríveis e facilmente, que daria muito mais \\ntrabalho fazendo em outras linguagens." \0 0

O usuário aperta Ok e o shell-script continua normalmente. No primeiro exemplo eu usei a opção –yesno que gerava o sim e não. Agora usei o –msgbox. Mas e se você quiser que o usuário digite algo e isto seja gravado em um arquivo por exemplo? Vamos ver este exemplo:

Xdialog --title "Que Anime que você mais gosta?" --center --inputbox \"Se você sabe o que é Anime, e gosta, qual o seu preferido?\n \ Sua resposta será gravada no arquivo resposta." \0 0 2> resposta

Depois que o usuário preenche o campo e dá Ok, a resposta que este usuário digitou será gravada no arquvio resposta. Isto ocorreu pelo fato de eu ter colocado o direcionador 2> para o arquivo resposta. Se eu colocasse a opção –stdout na linha de comando do Xdialog, a resposta do usuário apareceria na tela. Tente você.

Vamos ver agora seleção de itens, que é uma das coisas mais importantes num programa. Desta vez usaremos a opção –menubox para gerar um menu com os itens a serem selecionados. Mais uma vez, vamos ao exemplo:

Xdialog --title "Exemplo de Menu" --center --stdout --menubox \"Qual sua distribuição Linux favorita?" \20 50 0 \1 "Slackware" \2 "Debian" \3 "Red Hat" \4 "Conectiva Linux" \5 "Eu tenho minha própria distribuição"

Viu como é fácil? O que o usuário escolher vai aparecer como resultado no console (por causa da opção –stdout). Se eu colocasse o redirecionador 2>, poderia ir para um arquivo como no exemplo anterior. Vamos esclarecer uma coisa aqui também… Depois do texto “Qual sua distribuição Linux favorita?”, há 2 números. Estes dois números correspondem à altura e comprimento da janela. Nos exemplos anteriores eu coloquei “0 0″ pois aí o Xdialog dimensiona automaticamente o tamanho da janela. Então já sabe, se quiser mudar o tamanho da janela, é só mudar estes dois números.

Agora como último exemplo, vamos criar uma janela em que o usuário poderá escolher uma ou mais opções. Isto é chamado de checklist, e pode ser visto no exemplo a seguir:

Xdialog --title "Último exemplo - checklist" --center --checklist \

Page 11: Iniciação em Shell

"Como se pronuncia Linux?" \0 0 0 \"Opção 1" "Láinucs" off \"Opção 2" "Lenocs" off \"Opção 3" "Linúcs" off \"Opçào 4" "Línucs" on \"Opção 5" "GNUUU/Linux" off

Veja agora a diferença entre esta checklist e o menu do exemplo anterior. Verifique que depois de cada opção há o on e o off. O on indica que esta opção deverá já estar marcada, e o off que não deverá estar marcada. Se o usuário escolher 3 opções, as mesmas serão o resultado.

Bem fácil criar uma interface amigável para suas shell-scripts. Se você pensa que isto é tudo, ainda tem muito mais por trás do Xdialog. Para não ter que ficar comentando cada opção, vou dar uma lista de parâmetros e a descrição de suas funções. O que você deverá fazer é sair testando todas as opções e se impressionar :)

–yesno Uma janela com opções de “Sim” ou “Não”

–msgbox Apenas mostra um texto informativo

–infoboxMesmo que –msgbox, só que desaparece automaticamente em um determinado tempo

–inputbox O usuário preenche um campo

–rangebox Escolhe um número entre X e Y, com uma barra de rolagem

–textbox Mostra o conteúdo de um arquivo numa caixa de texto

–editbox Edita o conteúdo de um arquivo numa caixa de texto

–menubox Cria um Menu de opções, onde se seleciona um item

–checklist Mesmo que –menubox, só que pode-se selecionar vários itens

–radiolist Mesmo que –menubox, mas agora em outro estilo

–treeview Opções organizadas em forma de “árvore” (interessante)

–gauge Um indicador de processo

–tailbox Mostra o conteúdo de um arquivo

–fselect Abre uma janela de seleção de um arquivo

–dselect Abre uma janela de seleção de um diretório

–calendar Mostra um calendário para escolher uma data

–timebox Mostra uma janela para edição de horário

Você também pode encontrar alguns exemplos no diretório samples que vem junto com o código-fonte do programa. Se você fizer algum programa legal em shell-script, sinta-se a vontade para me mandar um e-mail. Outra coisa, como o Xdialog é uma idéia tirada do dialog/cdialog (existe também o whiptail que é parecido), você pode usar a mesma sintaxe para criar estas “janelas” no modo console. Espero que estas informações foram úteis a você e até a próxima :)

Utilizando o bash

Page 12: Iniciação em Shell

Após o login de um usuário no modo texto, o mesmo entra em uma shell. Uma shell é um interpretador de comandos: ela lê o que o usuário digita, interpreta e executa as aplicações de acordo com o que você executou.

Existem diversos tipos de shells, como o sh, bash, tcsh, ksh, tclsh, entre outras. Neste treinamento estaremos trabalhando com a shell GNU bash (GNU Bourne-Again SHell), pois ela é a mais utilizada por padrão em todas as distribuições Linux.

Características dos arquivos no Linux

Nos nomes dos arquivos, os caracteres MAIÚSCULOS e minúsculos fazem diferença. Isso quer dizer que por exemplo: os arquivos PROGRAMA.tar.gz e programa.tar.gz são dois arquivos completamente diferentes. Ou então: ls é um comando e LS é um erro.

No Linux, não existem extensões especiais para programas executáveis (como .exe, .com). Ao invés disso, os arquivos têm permissão de executável ou não-executável. Mais detalhes no

Além de arquivos comuns, no Linux existem os chamados links simbólicos, que são uma espécie de atalhos. Mais detalhes no comando ln.

Executando comandos

Como um interpretador de comandos, o que o bash sabe fazer de melhor é: executar comandos! Assim como os prompts de comando da maioria dos sistemas operacionais, para executar um comando, o bash lê o que o usuário digitou e procura em diretórios pré-definidos (PATH) se aquele comando existe. Caso o programa exista e o arquivo for executável, o bash irá executá-lo.

Por exemplo, para executar o comando que lista arquivos no diretório atual:

$ ls

Quando o usuário digitou ls, o bash procurou nos diretórios do PATH e achou um comando chamado ls no diretório /bin, então o executou. Agora se um programa executável estiver fora do PATH, só será possível executá-lo especificando seu caminho completo:

$ /opt/programa/nonpath

E se um arquivo executável estiver no diretório atual, executamos o comando:

$ ./programa

Para sair da shell (logout), aperte CTRL+D ou execute o comando exit.

Completação por Tab

A completação por Tab é um recurso que permite completar comandos ou nomes de arquivos mais rapidamente, sem precisar digitar todos os caracteres. Para utilizar, basta

Page 13: Iniciação em Shell

apenas digitar as primeiras letras do comando ou arquivo e apertar a tecla Tab. O bash irá completar o nome do comando ou arquivo para você automaticamente.

Caso haja mais de um arquivo começando com as letras que você digitou, apertando Tab mais uma vez fará com que o bash apresente todas as opções disponíveis. Por exemplo, se você quiser saber todos os comandos que começam com as letras mo, execute na shell:

$ momodule-assistant montage mount mozillamogrify more mountpoint mozilla-firefox

Imagine, se você simplesmente apertar Tab duas vezes sem ter digitado nada, o bash irá lhe apresentar todos os comandos disponíveis no sistema!

Configurando o PATH

Quando falamos em PATH, queremos dizer se um determinado diretório está acessivel sempre, de qualquer lugar, para executar comandos. Quando um comando está dentro de um diretório PATH, quer dizer que de qualquer lugar você poderá executá-lo.

Se for necessário mudar o PATH para adicionar um diretório de algum programa que você instalou, basta apenas manipular a variável do bash chamada de $PATH. Para ver os atuais diretórios que estão no PATH da sua sessão atual, digite o seguinte comando:

$ echo $PATH/home/coletivo/bin:/usr/local/bin:/usr/bin:/bin

Acima podemos ver que os diretórios no PATH são separados por dois pontos. Então para adicionar um novo diretório no PATH, basta reconfigurar a variável da seguinte forma:

$ PATH=$PATH:/novodiretorio

No comando acima, atribuímos à variável $PATH o valor dela mesma, adicionando :/novodiretorio. Agora o /novodiretorio também estará no PATH.

Procurando por comandos já digitados

Uma boa forma de salvar tempo é utilizar comandos já digitados ao invés de digitá-los novamente. Por padrão o bash implementa um histórico com uma lista de todos os comandos que você digitou. Este histórico fica no arquivo .bash_history, dentro do diretório HOME de cada usuário.

Para procurar por um comando digitado anteriormente, comece apertando a sequência de teclas CTRL+R. Quando feito isso, o prompt muda, indicando “(reverse-i-search)`’:”. Comece a digitar o comando e ele vai tentando achar para você. Se ele achou um comando e você quer procurar por outros comandos que têm a mesma palavra, continue apertando CTRL+R para visualizar o que ele achou a mais. Por final, quando encontrar o comando desejado, aperte ENTER para executá-lo, ou a seta para o lado para editá-lo antes de pressionar ENTER.

Page 14: Iniciação em Shell

Outro jeito de visualizar o histórico de comandos é executar:

$ history

E o bash lhe mostrará uma lista de comandos precedidos pelo número de sequência do comando, ou seja, a ordem com que ele foi executado. Escolha uma linha, grave o número dessa linha e então para re-executar o comando, digite:

$ !numero

Por padrão o bash guarda 500 comandos em seu histórico. Para aumentar ou diminuir este limite, basta apenas mudar o valor da variável $HISTFILESIZE para a quantidade de comandos desejada:

$ HISTFILESIZE=2000

No caso acima mudamos a quantidade de comandos guardados no histórico para 2000.

Apelidos de comandos

Os aliases, ou apelidos, são um jeito fácil de criar atalhos para os comandos mais usados. Por exemplo, se eu tenho um comando “comando_realmente_grande -lZdsW” mas não quero ficar digitando tudo isto, posso criar um alias chamado “comando” da seguinte forma:

$ alias comando=”comando_realmente_grande -lZdsW”

Então toda vez que eu digitar comando, vai ser a mesma coisa que digitar todo este comando e seus parâmetros. Para visualizar todos os apelidos configurados para a sua atual sessão de shell, execute:

$ alias

Gerenciamento de tarefas

O bash oferece um gerenciamento de tarefas simples, que permite os usuários, em uma mesma shell, executar vários programas ao mesmo tempo, aproveitando os recursos de multi-tarefa do sistema operacional.

Quando um usuário executa um comando, dizemos que ele está no “plano ativo” (foreground), ou seja, está aparecendo na tela e o usuário pode interagir com ele. Além do plano ativo, existe o plano de fundo (background), onde um programa fica funcionando, mas não mostra na tela e nem interage com o usuário.

Por exemplo, comece executando uma aplicação que ficará funcionando no plano ativo:

$ man bash

Você pode interagir pela página de manual normalmente. Agora vamos suspender este programa e deixá-lo sendo executado no plano de fundo. Para isso, comece apertando a

Page 15: Iniciação em Shell

combinação de teclas CTRL+Z (Suspender). O bash irá sair da tela da página de manual e voltar ao prompt, com a seguinte mensagem:

[1]+ Stopped man bash

Isto significa que o programa 1 desta shell foi suspendido. Para mandá-lo para o plano de fundo, utilize o comando bg:

$ bg 1

Quando suspendemos o programa, ele parou completamente de funcionar e esperou uma ação do usuário. O comando bg fez com que o programa voltasse a funcionar, mas em plano de fundo. Para trazer o programa de volta ao plano ativo, utilize o comando fg:

$ fg 1

Assim a tela da página de manual irá aparecer novamente, do jeito que você a deixou. Você pode também executar múltiplos processos dessa forma. Agora se quisermos executar um comando mandando-o diretamente para o plano de fundo, ao invés do plano ativo, basta acrescentar o sinal “&” no final do comando, assim:

$ man bash &

Para listar os programas que estão suspendidos ou em plano de fundo, digite:

$ jobs

Arquivos de configuração

Muitas das coisas que aprendemos sobre o bash servem apenas para a sessão atual do usuário. Em outras palavras, se você criou apelidos para comandos ou mudou o tamanho do histórico de comandos, quando você efetuar o logoff tudo se perderá. No próximo login, você terá que fazer tudo novamente…

…A não ser que você utilize os arquivos de configuração e inicialização do bash.

O conteúdo do arquivo /etc/profile contém todos os comandos padrões para todos os usuários do sistema, uma vez que iniciaram uma sessão de login na shell. Nele podemos ver o PATH e o visual do prompt sendo configurados, por exemplo.

Já o conteúdo do arquivo .bash_profile dentro do diretório HOME do usuário contém os comandos de login para o usuário dono do HOME correspondente.

Em outras palavras, se você quiser deixar suas modificações (como variáveis e apelidos) permanentes, basta colocar os comandos dentro destes arquivos e os comandos serão re-executados toda vez que você iniciar uma shell interativa.

Page 16: Iniciação em Shell

Shell: Entrada e Saída

Se voltarmos um pouco para os conhecimentos básicos da informática, podemos lembrar que existem dois tipos principais de interfaces entre o usuário e o computador: interface de entrada (teclado, mouse) e interface de saída (monitor). Para entender o funcionamento das entradas e saídas dos comandos, basta inicialmente utilizar essa mesma definição: o teclado é a entrada padrão (STDIN), a tela é a saída padrão (STDOUT e STDERR).

Por exemplo, quando eu digito o comando ls:

$ lsarquivo1 arquivo2 arquivo3

Ele me retornou como saída na tela a lista dos arquivos: arquivo1, arquivo2, arquivo3. O comando retornou na tela pois não especificamos nada. Podemos fazer a mesma coisa com o comando cat:

$ cat contato.txt ...Informações de Contato...

Neste caso, o comando cat recebeu um argumento (contato.txt), o qual podemos chamar de entrada. Como a entrada padrão é o teclado, tivemos que digitar o nome do arquivo contato.txt. Recebido o argumento, o cat mandou para a tela (saída padrão), o conteúdo do arquivo contato.txt.

Alterando a saída dos comandos

Para alterar a saída dos comandos utilizamos os sinais de “>” e “>>”. O sinal de “>” altera a saída padrão, sobrescrevendo o destino, enquanto o sinal de “>>” altera a saída padrão mas adiciona o conteúdo ao destino. Se considerarmos estes caracteres como “redirecionadores”, talvez possamos entender melhor.

Por exemplo, se eu quiser alterar a saída do comando ls anterior, para ao invés de aparecer na tela, ser gravada em um arquivo:

$ ls > lista_de_arquivos.txt

Neste caso, ao invés de mostrar na tela, a saída agora é o arquivo lista_de_arquivos.txt e por isso o comando ls vai escrever neste arquivo. Se olharmos o conteúdo, veremos a lista “arquivo1, arquivo2, arquivo3”.

Como utilizamos o “>”, se existisse o arquivo lista_de_comandos.txt, ele seria sobrescrito pelo comando, perdendo todo seu conteúdo anterior. Utilizando o “>>”, podemos gravar várias linhas consecutivas sem sobrescrever os conteúdos anteriores:

$ ls >> lista_de_arquivos.txt

Se executarmos este comando várias vezes, veremos que dentro do arquivo haverá várias linhas com a mesma listagem de arquivos do comando ls.

Page 17: Iniciação em Shell

Um uso muito comum disto é redirecionar a saída para o /dev/null, que é um dispositivo/arquivo especial que anula tudo que vai para ele. Ao fazer:

$ cat contato.txt > /dev/null

A informação que está dentro do arquivo contato.txt não vai para nenhum lugar: nem para a tela, nem para um arquivo.

Existem dois tipos de saída: STDOUT (Saída Padrão) que corresponde às mensagens normais de um comando, como por exemplo, a listagem dos arquivos do comando ls. O STDOUT pode ser representado como estávamos fazendo anteriormente, com um sinal de “>”, ou também por “1>”. Então os dois comandos a seguir fazem a mesma coisa:

$ cat contato.txt > /dev/null$ cat contato.txt 1> /dev/null

O STDERR (Saída de Erros Padrão) corresponde às mensagens de erro que o programa gera. Seguindo os mesmos exemplos anteriores, vemos o STDERR em ação quando tentamos listar um arquivo que não existe:

$ ls arquivonaoexistente > /dev/nullls: não foi possível acessar arquivonaoexistente: Arquivo ou diretório não encontrado

Apesar de redirecionarmos a saída para ser anulada (/dev/null), mesmo assim o ls retornou na tela a mensagem de que o arquivo não existe. Isto acontece porque esta é uma mensagem de erro e por isso não é contemplada pelo sinal de “>” ou “1>”. Para redirecionar o STDERR, utilizamos “2>”. Corrigindo o exemplo anterior:

$ ls arquivonaoexistente > /dev/null 2> /dev/null

Agora sim, tanto o STDOUT quanto o STDERR serão anulados, pois foram redirecionados para /dev/null.

Como redirecionamos as duas saídas para um lugar só, também podemos simplificar o comando anterior da seguinte forma:

$ ls arquivonaoexistente > /dev/null 2>&1

Vamos por partes: primeiro redirecionei a saída padrão para /dev/null (> /dev/null) e logo em seguida redirecionei a saída de erros para o mesmo lugar que a saída padrão (2>&1). O caracter especial “&” atuou como uma referência para a saída padrão. Se não houvesse o “&”, a saída de erros seria direcionada para um arquivo comum chamado “1”. Por fim, este comando também faz com que os dois tipos de saída sejam enviados para /dev/null e, por consequência, anulados.

Alterando a entrada dos comandos

Para alterar a entrada dos comandos, utilizamos o sinal de “<”. Geralmente é utilizado em comandos que necessitam de arquivos como argumentos. Por exemplo, o comando sort ordena as linhas de um arquivo alfabeticamente e sua sintaxe é sort arquivo.

Page 18: Iniciação em Shell

Podemos redirecionar o conteúdo do arquivo diretamente, sem passá-lo como argumento:

$ sort < arquivo

Cada linha de arquivo será passada para o comando sort, que ordenará e mostrará na tela. Vamos então redirecionar essa saída para outro arquivo:

$ sort < arquivo > arquivo_ordenado

Outro exemplo muito comum do uso da alteração do STDIN é quando um programa necessita de sub-comandos. Por exemplo, a shell bash, quando executada, fornece um prompt para o usuário digitar os comandos via teclado. Podemos automatizar essa digitação colocando todos os comandos em um arquivo. Chamaremos este arquivo de comandos.txt, com o conteúdo:

cd /rootlscd /usr/lscd /etccat /etc/passwdcd /usr/local/binpwd

Agora podemos executar uma shell, passando como entrada este arquivo:

$ bash < comandos.txt

Ao invés do bash fornecer um prompt para a digitação de comandos, ele irá ler e executar todo o conteúdo do arquivo comandos.txt, depois sair. Este é o conceito de shell-script, mas utilizado de uma forma mais crua. Apesar de ser útil, geralmente usamos uma forma diferente para criar shell-scripts.

Outro exemplo como o anterior, mas bastante usado, seria restaurar um arquivo do banco de dados MySQL de forma automática. Nesta situação, temos um arquivo chamado base.sql que contém vários comandos SQL de criação de tabelas e dados. Usa-se então o redirecionador de entrada para que ao invés do usuário digitar todos estes comandos, eles serem passados para o utilitário do MySQL:

$ mysql bancodedados < base.sql

Utilizando o Pipe

Além dos redirecionadores, temos também o pipe, representado pelo caracter “|”. O pipe é responsável por passar a saída de um comando como a entrada de outro. Em outras palavras, ao se executar um comando, ao invés da saída dele ir para a tela ou para um arquivo, ele se torna a entrada de outro comando, funcionando de forma parecida com a utilização tanto do “>” quanto do “<”.

Utilizando um exemplo parecido com os anteriores, vamos ordenar um arquivo texto:

Page 19: Iniciação em Shell

$ cat arquivo.txt | sort

O comando cat, ao invés de mostrar o conteúdo de arquivo.txt na tela, manda a saída para o comando sort, que ordena e joga na tela. O mesmo comando, mas agora redirecionando o resultado para um outro arquivo:

$ cat arquivo.txt | sort > arquivo_ordenado.txt

Ou então, se quisermos ver uma listagem detalhada de um diretório com bastante coisa, podemos facilitar a visualização combinando a listagem e o comando less:

$ ls -lha /usr/bin | less

Ao listar todos os arquivos do diretório /usr/bin, o ls manda o resultado para o less. Com isso, podemos utilizar os recursos de paginação do less. Vamos agora descobrir se um processo está sendo executado no sistema:

$ ps aux | grep bash

O comando ps listou todos os processos do sistema e enviou para o grep “filtrar” e só mostrar os que tem a palavra bash.

Podemos utilizar também vários pipes, como no exemplo:

$ cat /etc/passwd | cut -d “:” -f1 | sort | uniq

Utilizamos 4 comandos, cada um recebendo o resultado do outro. Vamos por passos:

1. cat /etc/passwd: Simplesmente mostra o conteúdo do arquivo /etc/passwd.2. cut -d “:” -f1: Recebe o conteúdo do arquivo /etc/passwd, enviado pelo cat, e

separa seus “campos”, mostrando apenas a primeira palavra de cada linha (usuário).

3. sort: Organiza esses usuários em ordem alfabética.4. uniq: Remove linhas duplicadas.

Por fim, o uniq manda para a tela o resultado final: a lista dos usuários do sistema, ordenados por ordem alfabética.

Page 20: Iniciação em Shell

Comandos para Manipulação de Arquivos

Uma das coisas essenciais ao usar um sistema operacional é saber como lidar os arquivos e diretórios dentro dele. Em sistemas operacionais como o Linux, mexer com arquivos é essencialmente tudo o que você vai fazer ao configurar o sistema e seus serviços.

pwd – Exibe o diretório atual

Sintaxe: $ pwd

Mostra de forma simples em qual diretório o usuário está localizado no momento.

cd – Navegando entre diretórios

Sintaxe: $ cd [nome_do_diretório]

Muda o diretório atual.

Exemplos:

$ pwd/usr/games$ cd ~$ pwd/home/eitch

No exemplo acima, estávamos no diretório /usr/games e com um simples cd para o diretório ~, fomos para o diretório HOME (/home/eitch). Neste caso utilizamos o ~ que é uma espécie de atalho para o diretório HOME do usuário. Alguns destes “atalhos”:

. (ponto) Diretório atual

.. (dois pontos) Diretório anterior (um nível acima)

~ (til) Diretório HOME do usuário

/ (barra) Raiz do sistema

- (hífen) Último diretório (Voltar)

Se você deseja ir para um diretório que está na raiz diretamente, usa-se a / antes, exemplo:

$ pwd/usr/local/bin$ cd /etc/rc.d$ pwd/etc/rc.d$ cd -$ pwd/usr/local/bin

Page 21: Iniciação em Shell

Ao utilizar uma barra antes do diretório, especificamos o caminho absoluto do diretório, ou seja, todo o seu caminho desde a raiz. Se não colocamos a barra para especificar a raíz, quer dizer que estamos especificando um caminho relativo, ou seja, de acordo com o diretório atual. Em outras palavras, se eu estou no diretório /home/eitch, os dois comandos a seguir farão a mesma coisa, só que um usando o caminho relativo e o outro o caminho absoluto:

$ cd ..$ cd /home

ls – Listar arquivos

Sintaxe: $ ls [opções] [arquivo/diretório]

Lista os arquivos e diretórios. Se executarmos apenas o comando ls sozinho, ele mostrará todos os arquivos existentes no diretório atual. Há também alguns parâmetros extras:

-l Lista os arquivos em formato detalhado.

-a Lista os arquivos ocultos (que começam com um .)

-h Exibe o tamanho num formato legível (combine com -l)

-R Lista também os subdiretórios encontrados

Exemplo de uma listagem detalhada:

$ ls -ltotal 9916drwxrwxr-x 5 hugo hugo 1302 Aug 16 10:15 diretorio-rw-r--r-- 1 hugo hugo 122631 Jul 12 08:20 Database.pdf-rw-r--r-- 1 hugo hugo 2172065 Jul 12 08:20 MySQL.pdf-rw-r--r-- 1 hugo hugo 2023315 Jul 12 08:20 PHP.pdf

No exemplo acima, os arquivos e diretórios são listados com outras informações antes de seus nomes. Estas informações são separadas por um ou mais espaços (para uma melhor formatação) e apresentam os seguintes dados: tipo de arquivo e permissões, número de hard links, usuário dono, grupo dono, tamanho, data de modificação e por último o nome do arquivo.

Podemos ver acima que a segunda linha (diretorio) inicia com a letra d, o que significa que ele é um diretório, ao contrário dos outros arquivos que não contém nenhuma letra (-) e por isso são arquivos comuns. É possível identificar o tipo de arquivo desta maneira e as letras podem ser: b para arquivo especial de bloco, c para arquivo especial de caracter, d para diretório, l para link simbólico, p para um FIFO, s para socket.

Podemos também usar no ls o que chamamos de wildcards (caracteres coringa), ou seja, caracteres que substituem outros.

Exemplo, listar todos os arquivos que têm a extensão .txt:

$ ls *.txt

Page 22: Iniciação em Shell

debian-install.txt manualito.txt named.txt plip.txt seguranca.txtipfw.txt mouse.txt placa_de_video.txt rede.txt sis.txt

O wildcard neste caso é o “*”, que representa “tudo”.txt. Existem outros wildcards, como por exemplo o ponto de interrogação “?”, que substitui apenas 1 caractere. Exemplo:

$ ls manual?.txtmanual1.txt manual2.txt manual3.txt manualx.txt manualP.txt

Ou ainda os colchetes, que substituem uma faixa de caracteres:

$ ls manual[3-7].txtmanual3.txt manual4.txt manual6.txt manual7.txt

mkdir – Cria um diretório

Sintaxe: $ mkdir <nome_do_diretório>

Cria um diretório. Exemplo, criar um diretório dentro do HOME do usuário:

$ mkdir ~/paginas

rmdir – Remove um diretório vazio

Sintaxe: $ rmdir <nome_do_diretorio>

Apaga um diretório que esteja vazio.

Exemplo, apagando o diretório /tmp/lixo apenas se ele estiver vazio:

$ rmdir /tmp/lixo

Para apagar um diretório com seu conteúdo, usa-se o comando rm.

cp – Cópia de arquivos e diretórios

Sintaxe: $ cp [opções] <arquivo_origem> <arquivo_destino>

Copia arquivos e diretórios. Como parâmetros, temos:

-i Modo interativo. Pergunta se você quer sobrescrever ou não (confirmações)

-v Mostra o que está sendo copiado.

-R Copia recursivamente (diretórios e subdiretórios)

Exemplo, copiando o arquivo brasil.txt para livro.txt, com a opção de modo interativo:

$ cp -i brasil.txt livro.txt

Page 23: Iniciação em Shell

cp: sobrescrever `livro.txt'?

Como o arquivo livro.txt já existia, o comando pergunta se quer sobrescrever, responda y (sim) ou n (não).

Copiar o diretório /home/ftp e todo seu conteúdo (incluindo seus subdiretórios) para /home/ftp2:

$ cp -R /home/ftp /home/ftp2

mv – Move arquivos e diretórios

Sintaxe: $mv <arquivo_origem> <arquivo_destino>

Move um arquivo para outro lugar. Ele também é usado para renomear um arquivo.

Exemplo, renomear o arquivo industria.txt para fabrica.txt:

$ mv industria.txt fabrica.txt

Mover o arquivo industria.txt para /home/usuario com o mesmo nome:

$ mv industria.txt /home/usuario

rm – Remove arquivos e diretórios

Sintaxe: $ rm [opções] <arquivo>

Este comando apaga definitivamente o arquivo ou diretório. Exemplo:

$ rm arquivo.bin

Para apagar um diretório com todo seu conteúdo, usa-se a opção -r:

$ rm -r /tmp/lixo

Cuidado! O comando “rm -rf” é muito perigoso, use-o com cuidado. Ele remove um diretório e todo seu conteúdo sem perguntar. Por exemplo, fazer isso na raiz não seria uma boa idéia.

find – Procura arquivos

Sintaxe: $ find <diretorio> [-name nomedoarquivo]

Procura por arquivos no diretório especificado. Em seu uso mais simples, ele procura pelos nomes dos arquivos, mas pode também procurar por tipos, permissões, última modificação, entre outros.

Exemplo, procurar o arquivo nota.txt dentro do diretório /home/eitch:

Page 24: Iniciação em Shell

$ find /home/eitch -name nota.txt -print

Procurar por todos os diretórios dentro do /etc:

$ find /etc -type d -print

Procurar por todos os arquivos que foram modificados nos últimos 2 dias:

$ find / -mtime 2 -print

Procurar por arquivos que podem ser escritos por todo mundo:

$ find / -perm -222

Os wildcards também podem ser usados, por exemplo, procurar por todos os arquivos que começam com o nome de documento e terminam com .odp:

$ find /home/eitch -name documento*.odp

O find também conta com uma opção muito útil, a opção -exec. Através desta opção você pode executar comandos para cada um dos arquivos encontrados. Combinando com as outras opções, se torna um poderoso utilitário! Por exemplo, para definir permissões “755″ para todos os diretórios:

$ find /home/eitch -type d -exec chmod 755 {} \;

Neste exemplo, para cada diretório encontrado (-type d) dentro do /home/eitch, foi executado o comando chmod 755 <arquivo encontrado>. O “{}” no comando é substituído por cada arquivo ou diretório encontrado. O \; é apenas o “terminador” para o comando do -exec. O mesmo exemplo, agora para definir permissões “644″ para arquivos:

$ find /home/eitch -type f -exec chmod 644 {} \;

Ou então, eu quero remover todos os arquivos que terminam com a extensão .exe:

$ find /home/eitch -type f -name *.exe -exec rm -f {} \;

Ou até remover os diretórios que tem .svn como nome:

$ find /home/eitch/projeto -type d -name .svn -exec rm -rf {} \;

ln – Cria links entre arquivos

Sintaxe: $ ln -s <arquivo_origem> [link simbólico]

Usado para gerar links simbólicos, ou seja, links que se comportam como um arquivo ou diretório, mas são apenas redirecionadores que mandam seu comando para outro arquivo ou diretório.

Exemplo: Criar um link em /tmp/apostila-linux, apontando para o diretório /apostila:

Page 25: Iniciação em Shell

$ ln -s /apostila /tmp/apostila-linux

Também é utilizado para criar links físicos (hard-links). Um link físico funciona não como um atalho, mas como um arquivo apontando para um mesmo lugar no disco e funciona apenas em arquivos. Por depender de uma posição física no disco, só pode ser utilizado em uma mesma partição. Exemplo:

$ ln arquivo linkdoarquivo

cat – Exibe o conteúdo de um arquivo

Sintaxe: $ cat <arquivo>

Mostra o conteúdo de um arquivo, ou faz uma cópia deste arquivo, ou uma junção.

Exemplo: Mostrar o conteúdo de /home/eitch/contato:

$ cat /home/eitch/contato

Hugo [email protected]

http://www.devin.com.br

O cat também pode servir como redirecionador para outro arquivo. Os caracteres especiais de redirecionadores são utilizados para este fim.

O “>” redireciona a saída de um comando para um arquivo. Como o comando cat mostra exatamente o conteúdo de um arquivo, isso seria equivalente a fazer uma cópia do arquivo:

$ cat contato1 > contato2

O “>>” acrescenta a saída de um comando à um arquivo, mantendo seu conteúdo anterior:

$ cat contato1 >> contato3

Um outro exemplo divertido é tocar sons com o cat. Redirecionando o conteúdo de um arquivo para o dispositivo de som reproduz o som pelos alto-falantes e vice-versa. Para testar este caso, primeiro gravamos com um microfone o som:

$ cat gravacao.au < /dev/audio

O comando acima direcionou o dispositivo de som “no caso, a captura por microfone” para o arquivo gravacao.au. Agora escute o som gravado com o comando:

$ cat gravacao.au > /dev/audio

Os redirecionadores podem ser utilizados em todos os outros comandos na shell.

Page 26: Iniciação em Shell

head, tail – Mostra o começo e fim do arquivo

Sintaxe: $ head [opções] <arquivo>Sintaxe: $ tail [opções] <arquivo>

Talvez pelo arquivo poder ser muito grande, as vezes é necessário apenas visualizar parte dele. Em arquivos de log por exemplo, visualizar o final para ver os últimos acontecimentos é uma prática comum.

O comando head, como o nome diz (cabeçalho), mostra o começo de um arquivo. O comando tail (calda) mostra o final de um arquivo. Por padrão, ambos comandos mostram as 10 linhas correspondentes.

Por exemplo, exibindo as 10 últimas linhas do arquivo /var/log/messages:

# tail /var/log/messages

Ou as 10 primeiras linhas do /etc/profile:

$ head /etc/profile

Quando utilizado o parâmetro -n, podemos especificar a quantidade de linhas, ao invés de 10. O comando a seguir mostrará as 50 últimas linhas do arquivo /var/log/messages:

# tail -n 50 /var/log/messages

Quanto utilizado com o parâmetro -f, o comando tail mostra as linhas mas não para, continua mostrando as linhas na medida que o arquivo é atualizado. Útil para visualizar logs em constante atualização. Exemplo:

# tail -f /var/log/httpd/access_log

more, less – Visualiza arquivos por páginas

Sintaxe: $ more <arquivo>Sintaxe: $ less <arquivo>

Parecidos com o cat, mas ao invés de jogarem todo o conteúdo na tela de uma vez só, criam uma espécie de paginação.

No comando more, a tecla ESPAÇO vai passando as páginas, até quando o fim do arquivo chega e o o comando finaliza.

No less, a paginação funciona como em uma página de manual (na verdade, a visualização das páginas de manual é feita com o less): é possível utilizar as setas para navegar no documento para cima e para baixo, utilizar as teclas PgUp e PgDown para paginar, o comando /pesquisa para pesquisar por uma palavra no documento e a tecla q para sair.

file – Indica o tipo de arquivo

Page 27: Iniciação em Shell

Sintaxe: $ file <arquivo>

Identifica o tipo de arquivo ou diretório indicado pelo usuário conforme os padrões do sistema operacional.

Há varios tipos de retorno, exemplos: ASCII text, C Program source, directory, ELF-Executable, data, Bourn-again shell-script, JPEG Image File, entre outros.

Exemplo:

$ file linux.txtASCII Text

touch – Muda timestamps

Sintaxe: $ touch [opções] <arquivo>

Quando um arquivo é criado, o sistema de arquivos reserva para ele algumas informações que chamamos de timestamps: hora do último acesso e hora da última modificação. O comando touch muda estes valores.

Sem argumentos, o touch muda os dois atributos para a hora atual. Quando não existe o arquivo, o comando cria um novo arquivo vazio. Este parece ser o método preferido de criação de arquivos vazios.

Page 28: Iniciação em Shell

Manipulação de Usuários

Como você já deve saber, o Linux é um sistema multi-usuário, então, é claro que não só pode existir um usuário usando o sistema. Uma primeira coisa que possamos dizer é que o Linux não pode de alguma maneira ser usada sem estar sendo um usuário. O usuário ‘root’ é o administrador do sistema, e é ele quem você vai usar primeiro para criar outros usuários depois (a não ser que você tenha criado um usuário comum durante a instalação do seu Linux).

Antes de mais nada, fique sabendo que o root é um usuário especial, ele pode fazer TUDO em seu sistema, não importa o que acontecer, ele faz. Ao contrário dos usuários comuns, que têm restrições. Se você já instalou algum Linux, você verá que a primeira coisa que você irá fazer antes de usar o sistema é se logar como root, ou seja, preencher aquele campo login: com o usuário root. Mas aí por alguma razão você quer mudar de usuário, ou criar outro, ou qualquer coisa do tipo, então você se pergunta: “Como?”

Há um comando específico para isto. Este comando é o “adduser” ou “useradd”. Dependendo da distribuição, o comando “adduser” vai ser apenas um comando igual ao “useradd”, ou então um script interativo que irá lhe fazendo perguntas, você irá preenchendo, e então o script criará um usuário no sistema para você.

No caso do “adduser” ser um comando mesmo, você poderá utilizar assim:

adduser hugopasswd hugo

Isso respectivamente irá criar um usuário padrão chamado hugo, e depois com o comando “passwd”, você definirá uma senha para este usuário. Você pode especificar outros parâmetros para o usuário, como no comando a seguir:

adduser hugo -d /var/usuarios/hugo -s /dev/null

Com estes parâmetros, especifiquei que o usuário hugo terá como diretório home o “/var/usuarios/hugo” e como shell o “/dev/null” (ou seja, não terá shell). Sem estes parâmetros, o diretório home seria “/home/hugo” e o shell seria “/bin/bash”.

Vamos entender agora como este comando funciona, que é uma coisa essencial que todos deveriam saber em relação ao sistema Linux. Cada um desses programas escrevem o usuário no arquivo de configuração do Linux referente aos usuários do sistema. Este arquivo é o “/etc/passwd”. Cada linha deste arquivo é um usuário cadastrado no sistema. Com as informações que vou lhe dar aqui, você pode muito bem criar uma conta sem usar estes programas/scripts citados acima.

O passwd é formado por linhas onde cada linha é um usuário, como falei acima, então vamos aprender a montar cada linha desta. Vou pegar um exemplo para vocês:

hugo:x:1001:100:Hugo Cisneiros:/home/hugo:/bin/bash

Page 29: Iniciação em Shell

Vamos dividir esta linha em “campos”, onde cada um é separado por : (dois pontos), olhe só:

Campo Significado

hugoLogin do Usuário, aqui você pode colocar o nome que quiser com até 8 caracteres.

xAqui diz que o password está no arquivo /etc/shadow. Se estivesse *, a conta estaria desabilitada, e se estivesse sem nada (::), a conta não teria password.

1001 UID (User IDentification), o número de identificação do usuário.

100GID (Group IDentification), o número de identificação do grupo do usuário.

Hugo Cisneiros

Comentários do usuário, como nome, telefone, etc

/home/hugo O diretório HOME do usuário.

/bin/bashShell do usuário, ou seja, o programa que irá enterpretar os comandos que o usuário executar.

Obs: O /etc/shadow é um arquivo que contém a senha do usuário criptografada, se alguém tiver posse dela, esta pessoa pode muito bem comparar as senhas com uma lista de palavras, e pode descobrir as senhas dos usuários. Felizmente este arquivo está muito bem protegido pelo sistema :)

Bem, legal, aprendi sobre adicionar um usuário, mas como faço para removê-lo? Simples, você pode apagar a linha referente a ele no /etc/passwd e os seus arquivos, ou simplesmente digitar userdel usuario. Combine com a opção -r para deletar junto o diretório HOME do usuário.

Ahhhhh? Você quer mais? O quê? Quer deixar um usuário como se fosse root? Então vamos lá que não temos nada a perder! O root possui o UID e o GID igual à 0 (zero), e um usuário comum não. Se nós forçássemos a mudança do UID e GID de um usuário para 0, ele ficaria como se fosse o root! Por exemplo, eu tenho a linha do usuário no /etc/passwd e mudo:

hugo:x:1001:100:Hugo Cisneiros:/home/hugo:/bin/bashhugo:x:0:0:Hugo Cisneiros:/home/hugo:/bin/bash ^ ^

Pronto, o usuário hugo vai ser também o root do sistema, o administrador do sistema, o deus do sistema, etc. Outra dica: Não é muito bom ficar usando o usuário root, este usuário é somente para a administração do sistema, então eu recomendo à você a usar sempre um usuário normal, ser da plebe :) E se for precisar usar o root, logar como ele ou utilizar o comando “su -” para se tornar o próprio root.

Outro arquivo que tem muito haver com os usuários no Linux é o /etc/group. Que contém as definições de cada grupo, como por exemplo seus nomes, GIDs, e usuários adicionais que pertencem à ele. Você adicionando uma linha neste arquivo estará criando um novo grupo. Vamos criar aqui um novo grupo no /etc/group:

Page 30: Iniciação em Shell

metal:x:666:hugo,jim,eitch

Adicionando esta linha acima no arquivo /etc/group, um novo grupo é criado: com o nome ‘metal’, o GID ‘666′ e como usuários adicionais pertencentes à ele, ‘hugo, jim, eitch’. Fácil não?

Bem é isso, combinando este conhecimento com algo sobre permissões dos arquivos, você pode controlar muito bem quem usa o seu sistema ou servidor, dizendo quem pertence à que grupo, quais seus diretórios, que arquivos podem acessar, entre outros. Bom proveito!

Page 31: Iniciação em Shell

Permissões

Permissões de Acesso

Todo arquivo ou diretório tem, além de seu nome e conteúdo, propriedades que restringem o seu uso. Como o Linux é um sistema operacional multi-usuário, arquivos e diretórios têm de pertencer à um certo usuário e grupo. O diretório /root por exemplo pertence ao usuário root e grupo root. Devido às permissões deste diretório, apenas o usuário dono (root) pode entrar e mexer nele.

Este tipo de funcionalidade é essencial em um sistema multi-usuário real. O comando ls -l mostra uma listagem detalhada dos arquivos do diretório atual e isso inclui suas permissões. Vejamos um exemplo:

$ ls -ldrwxr-xr-x 2 coletivo coletivo 4096 2008-08-29 13:35 apostila

Na parte do comando ls aprendemos que depois do primeiro caracter (tipo de arquivo), os próximos 9 caracteres são uma sequência de permissões. Podemos dizer que temos 3 variações de letras:

Letra r – leitura (read) Letra w – escrita (write) Letra x – execução (execute)

Estas três letras se encaixam em 3 campos:

{rwx}{rwx}{rwx}

Campo 1: Permissões do usuário dono Campo 2: Permissões do grupo dono Campo 3: Permissões para todos os outros

Sendo assim, o exemplo rwxrwxrwx significa literalmente: O usuário dono pode ler, escrever e executar o arquivo. O grupo dono pode ler, escrever e executar o arquivo. Todos os outros podem ler, escrever e executar o arquivo. Em outras palavras, todos podem fazer tudo no arquivo. O oposto disto seria a combinação “———”.

Vejamos agora o exemplo do diretório apostila:

drwxr-xr-x 2 coletivo coletivo 4096 2008-08-29 13:35 apostila

Neste caso, quando há um “-” no lugar da letra, significa que não há essa permissão. Então podemos ler a linha da seguinte forma: O usuário dono (coletivo) pode ler, escrever e executar. O grupo dono (coletivo) pode ler e executar, mas não pode escrever. Todos os outros podem ler e executar, mas não podem escrever.

Outro exemplo:

Page 32: Iniciação em Shell

$ ls -l /dev/dspcrw-rw---- 1 root audio 14, 3 2008-08-29 07:57 /dev/dsp

O arquivo /dev/dsp é do tipo “arquivo especial de caracter” (c). O usuário dono (root) pode ler e escrever neste arquivo, mas não pode executá-lo. O grupo dono (audio) pode ler e escrever no arquivo, mas não pode executá-lo. Os outros não podem ler, não podem escrever e nem executá-lo.

Um outro exemplo:

$ ls -l /dev/cdromlrwxrwxrwx 1 root root 3 2008-08-29 07:57 /dev/cdrom -> hda

A primeira letra indica que o arquivo /dev/cdrom é um link simbólico para /dev/hda. Isto quer dizer que as permissões estarão sempre rwxrwxrwx e o que vale na verdade são as permissões do arquivo hda:

$ ls -l /dev/hdabrw-rw---- 1 root cdrom 3, 0 2008-08-29 07:57 /dev/hda

Ou seja, tanto para o arquivo /dev/cdrom, quanto para o arquivo /dev/hda: O usuário dono (root) pode ler e escrever, mas não pode executar. O grupo dono (cdrom) pode ler e escrever, mas não pode executar. Todos os outros não podem ler, não podem escrever e nem executá-los.

Modificando os donos

Ao utilizar o ls -l, podemos ver o usuário dono e o grupo dono dos arquivos e diretórios. Se criarmos um arquivo com o usuário coletivo, o usuário dono e o grupo dono serão os do usuário coletivo. Podemos modificar quem é o dono do arquivo através dos comandos chown (change ownership – mudar o usuário dono) e chgrp (change group – mudar o grupo dono), lembrando que apenas o usuário root pode fazer isto.

Utilizando o comando chown para modificar usuário dono e grupo dono:

# ls -ldrwxr-xr-x 4 coletivo coletivo 4096 2008-08-29 13:35 coletivo# chown root coletivo# chgrp root coletivo# ls -ldrwxr-xr-x 4 root root 4096 2008-08-29 13:35 coletivo

Um jeito mais simples de fazer a mesma coisa, em um comando só, seria:

# chown root.root coletivo

O comando chown também modifica o grupo dono, especificado no comando através do grupo precedido por um ponto.

Modificando as permissões

Page 33: Iniciação em Shell

Existem duas maneiras de se modificar as permissões com o comando chmod: a forma extendida e a forma octal. A modificação de permissões pode ser feita contanto que o usuário seja o dono do arquivo. Apenas o usuário root pode modificar as permissões de outros usuários.

Na forma extendida, especificamos u para usuário, g para grupo e o para outros. Exemplo:

$ chmod u=rw,g=rw,o= arquivo$ ls -l arquivo-rw-rw---- 1 coletivo coletivo 0 2008-08-29 14:14 arquivo

Desta forma especificamos que o usuário dono (coletivo) pode ler e escrever (u=rw), o grupo dono pode ler e escrever (g=rw) e os outros não podem fazer nada (o=). Podemos também utilizar ao invés do sinal “=”, os sinais de “+” e “-”, para atribuir permissões relativamente. Exemplo:

$ chmod o+r arquivo$ ls -l arquivo-rw-rw-r-- 1 coletivo coletivo 0 2008-08-29 14:14 arquivo

Ao invés de especificarmos cada campo (usuário, grupo, outros), pedimos ao chmod que adicionasse apenas a permissão de leitura para os outros (o+r). Agora vamos remover apenas o bit de escrita do grupo dono (g-r):

$ chmod g-w arquivo$ ls -l arquivo-rw-r--r-- 1 coletivo coletivo 0 2008-08-29 14:14 arquivo

A forma octal de representação das permissões, apesar de ser mais rápida, requer um pouco mais de raciocínio. Nesta forma, cada tipo de permissão (leitura, escrita e execução) é representado por um número, na seguinte ordem:

Número 1 – Execução Número 2 – Escrita Número 4 – Leitura

Pensando em forma binária, a soma dos números nos dará a combinação de atributos desejada. Por exemplo, o número 3 significa permissão de escrita e execução (1 + 2 = 3). O número 5 significa permissão de leitura e execução (1 + 4 = 5).

Sabendo disto, utilizamos 3 números junto ao comando chmod, cada um especificando os campos de usuário dono, grupo dono e outros:

$ chmod 755 arquivo$ ls -l arquivo-rwxr-xr-x 1 coletivo coletivo 0 2008-08-29 14:14 arquivo

O usuário dono (coletivo) pode ler, escrever e executar (1 + 2 + 4 = 7). O grupo dono (coletivo) pode ler e executar (1 + 4 = 5). Os outros podem ler e executar (1 + 4 = 5). Outro exemplo:

Page 34: Iniciação em Shell

$ chmod 644 arquivo$ ls -l arquivo-rw-r--r-- 1 coletivo coletivo 0 2008-08-29 14:14 arquivo

O usuário dono (coletivo) pode ler e escrever (2 + 4 = 6). O grupo dono (coletivo) pode apenas ler (4). Os outros podem apenas ler (4). Outro exemplo:

$ chmod 600 arquivo$ ls -l arquivo-rw------- 1 coletivo coletivo 0 2008-08-29 14:14 arquivo

Apenas o usuário dono (coletivo) pode ler e escrever (2 + 4 = 6).

Bits especiais

Além das permissões de leitura, escrita e execução, temos também três outros bits especiais de permissões que podemos usar:

SUID

Quando utilizado em um arquivo, faz com que todo usuário que executar este arquivo se transforme no usuário dono do arquivo durante a execução. Isto quer dizer que se um programa estiver com permissão de root e com o SUID ativado, qualquer usuário ao executar este programa, terá privilégios de root.Este tipo de permissão deve ser sempre evitado. Use apenas quando realmente precisar, pois se um programa do root tiver alguma falha de segurança e estiver com o SUID habilitado, qualquer usuário poderia se tornar o root e conseguir poder total no sistema.

Um exemplo de aplicação que possui (e precisa) de SUID é o /usr/bin/passwd: o comando que muda a senha dos usuários. O arquivo de usuários e senhas do sistema tem permissões para que apenas o root possa ler, mas se um usuário normal quiser mudar a sua senha diretamente, sem a intervenção do usuário root, como ele poderia ler e modificar o arquivo de senhas se as permissões não deixam?

Quando o usuário executa o /usr/bin/passwd, o comando está com permissão de SUID, então é como se o usuário virasse o root temporariamente e por isso ele poderá ler o arquivo de senhas. Neste caso, o usuário estaria limitado a fazer apenas o que o programa /usr/bin/passwd permite: mudar senhas.

Vejamos as permissões do exemplo:

$ ls -l /usr/bin/passwd-rwsr-xr-x 1 root root 30968 2008-04-02 20:57 /usr/bin/passwd

Podemos ver que há uma letra incomum nas permissões: o s. Quando o s está no campo de permissões ao usuário dono, quer dizer que está com SUID. Quando o s está minúsculo, indica que além do SUID, o programa também tem permissão de executável (x). Quando em maiúsculo, indica que apenas o SUID está ativo.

Adicionando e removendo o SUID de um arquivo:

Page 35: Iniciação em Shell

$ ls -l arquivo-rwxr-xr-x 1 coletivo coletivo 0 2008-08-30 12:42 arquivo$ chmod u+s arquivo$ ls -l arquivo-rwsr-xr-x 1 coletivo coletivo 0 2008-08-30 12:42 arquivo$ chmod u-s arquivo$ ls -l arquivo-rwxr-xr-x 1 coletivo coletivo 0 2008-08-30 12:42 arquivo

O SUID funciona apenas em executáveis, não funcionando em scripts shell. Em um script shell, o executável na verdade é o interpretador de comandos (a shell) e não o script. O SUID precisaria ser colocado na shell (o que não é nem um pouco recomendável).

SGID

Para arquivos, funciona como o SUID: quando executado por qualquer usuário, a execução acontece como se o grupo dono fosse o mesmo do arquivo, independente do usuário que estiver executando. Quando utilizado em diretórios, o SGID faz com que todos os arquivos criados tenham como grupo dono o grupo do diretório com o SGID. Isto é bastante usado em diretórios compartilhados.

Quando um arquivo ou diretório está com SGID, o ls -l irá mostrar a letra s (em maiúsculo ou minúsculo, que nem o SUID) na posição do campo do grupo.

Exemplo:

$ ls -ld apostiladrwxr-xr-x 2 coletivo coletivo 4096 2008-08-29 13:35 apostila$ chmod g+s apostila$ ls -ld apostiladrwxr-sr-x 2 coletivo coletivo 4096 2008-08-29 13:35 apostila# cd apostila# touch teste# ls -l teste-rw-r--r-- 1 root coletivo 0 2008-08-30 12:50 teste

Ao configurar o SGID no diretório apostila, o usuário coletivo forçou que qualquer usuário que criasse um arquivo dentro deste diretório o criaria como grupo-dono coletivo. Quando o root criou um arquivo vazio chamado teste, podemos ver que realmente o grupo deste arquivo ficou como coletivo.O SGID, assim como o SUID, também não funciona diretamente em scripts, apenas em executáveis.

Sticky

Em tempos passados, quando aplicado em um arquivo, dizia ao sistema operacional que a execução deste arquivo não poderia utilizar a memória RAM do sistema, mas isto hoje em dia é completamente ignorado. Quando aplicado em um diretório, faz com que apenas o dono do arquivo e o dono do diretório possam remover o seu conteúdo. Isto é utilizado em diretórios temporários como o /tmp, onde qualquer pessoa pode criar arquivos, mas só podem remover seus próprios arquivos e não os dos outros usuários também.

Page 36: Iniciação em Shell

O Sticky é representado pela letra t no terceiro campo de permissões: outros, no lugar do x. Exemplo:

$ ls -ld /tmpdrwxrwxrwt 11 root root 4096 2008-08-30 07:35 /tmp

Todos os usuários do sistema podem listar o conteúdo, criar, apagar arquivos e entrar no diretório. Porém, como existe o Sticky bit, estes usuários só poderão apagar seus próprios arquivos.

Forma Octal dos Bits Especiais

Vimos as formas extendidas de se configurar os bits especiais. Mas também há a forma octal, que funciona da mesma maneira que os bits de leitura, escrita e execução: cada bit é representado por um número e a soma destes números permite uma combinação de permissões especiais:

Número 1 – Sticky Número 2 – SGID Número 4 – SUID

O resultado destes números precedem os outros três números no comando chmod. Exemplo:

$ chmod 4755 arquivo$ ls -l arquivo-rwsr-xr-x 1 coletivo coletivo 0 2008-08-30 13:05 arquivo

Além das permissões normais (755), o SUID foi adicionado neste arquivo através do número 4.

$ chmod 6755 arquivo$ ls -l arquivo-rwsr-sr-x 1 coletivo coletivo 0 2008-08-30 13:05 arquivo

Os bits de SUID e SGID foram adicionados neste arquivo (2 + 4 = 6).

$ chmod 3755 apostila$ ls -ld apostiladrwxr-sr-t 2 coletivo coletivo 4096 2008-08-30 13:05 apostila

Os bits de Sticky e SGID foram adicionados neste diretório (1 + 2 = 3).

Máscara padrão de permissões

Toda vez que criamos um arquivo, não precisamos configurar suas permissões. Esta característica é conhecida pela definição “umask”, a máscara de permissões. O umask é um comando e funciona especificando uma máscara de permissões tanto em uma forma extendida quanto na forma octal, parecido com o comportamento do comando chmod.

Page 37: Iniciação em Shell

Por ser um comando da shell, o umask é definido nos scripts de inicialização dessa shell. No caso do bash, sabemos que o umask é geralmente definido no arquivo /etc/profile. Para visualizar a atual configuração do umask, digite:

$ umask0022

Agora comece com os valores: 666 para arquivos e 777 para diretórios. O valor das permissões normais (leitura, escrita e execução) do umask subtrai destes valores. Então no caso da umask 0022, os arquivos terão permissão padrão 644 e os diretórios terão 755.

Outra forma mais fácil de entender é utilizando o parâmetro -S:

$ umask -Su=rwx,g=rx,o=rx

Que significa 755, ou no caso de um arquivo, todos os números -1: 644.

Page 38: Iniciação em Shell

Shell Script: tratamento de argumentos e opções

Na grande maioria das vezes, a linguagem shell-script é usada para criar uma sequência de comandos que automatizam uma tarefa. Nisso, ela é extremamente eficiente e rápida. Combinar comandos é uma grande vantagem que o jeito UNIX de ser nos trouxe: várias ferramentas que fazem tarefas básicas, especializadas, e que quando se juntam realizam grandes feitos trabalhando juntas. Mas isso nunca impediu que se criasse também programas completos em shell-script.

Uma característica para deixar um shell-script mais robusto e menos “sequencial/batch-mode” é o tratamento de argumentos. No meu clássico tutorial Programando em Shell-Script, o tópico Variáveis Especiais nos traz os primeiros itens que devemos aprender para o tratamento de argumentos. Existem variáveis especiais que tratam os argumentos passados para um programa ou uma função. Estes são:

$0 – Retorna o nome do script que foi executado $N – Onde N é um número, corresponde ao argumento passado (1 = primeiro

argumento, 2 = segundo argumento, 3 = terceiro argumento, etc) $* – Retorna todos os argumentos de uma vez. $# – Retorna a quantidade de argumentos passado para o script. (argc)

Vejamos agora um shell-script exempo que faz uso de todos esses argumentos:

?010203040506070809101112

#!/bin/bash

 if [ $# -lt 1 ]; then   echo "Faltou utilizar pelo menos um argumento!"   exit 1fi

 echo "Numero de argumentos: $#" COUNT=0for ARG in $*; do   COUNT=`expr $COUNT + 1`   echo "Argumento $COUNT: $ARG"done

Page 39: Iniciação em Shell

1314

As linhas 3 a 6 verificam se a quantidade de argumentos ($#) é menor (-lt – less than) que 1. Ou seja, se o usuário não chamou o programa com nenhum argumento, ele imprime um erro e sai do programa com status 1.

A linha 8 mostra quantos argumentos foram utilizados, usando novamente o $#.

O resto das linhas, 10 a 14, usam o $* com um laço for e um contador para mostrar quais foram os argumentos.

Executando agora este script sem argumentos:

$ ./tmp.shFaltou utilizar pelo menos um argumento!

Agora executando com dois argumentos:

$ ./tmp.sh naosei testandoNumero de argumentos: 2Argumento 1: naoseiArgumento 2: testando

E agora com 4 argumentos:

$ ./tmp.sh a b c dNumero de argumentos: 4Argumento 1: aArgumento 2: bArgumento 3: cArgumento 4: d

Bem simples né?

Argumentos como opções e seus valores

Algo comum que vemos nos programas são opções. Opções não deixam de ser argumentos para um programa, mas eles tem um significado especial. Do tipo: Se a opção -d existir, ativar durante o programa o modo de depuração. Se houver um -h, então mostre uma ajuda e não faça mais nada. Se houver um -v mostre a versão, e por aí vai.

Exemplo:

?0102

#!/bin/bash

 case $1 in   "-h") echo "Isto seria uma ajuda... Mas fiquei com preguiça de

Page 40: Iniciação em Shell

030405060708091011

escrevela."         ;;   "-v") echo "Versao 666."         ;;   *) echo "Opcao invalida!"      exit 1      ;;esac

Exemplos do uso do script:

$ ./tmp.sh -hIsto seria uma ajuda... Mas fiquei com preguiça de escrevela.

$ ./tmp.sh -vVersao 666.

$ ./tmp.sh -OOpcao invalida!

$ ./tmp.shOpcao invalida!

Com isso a gente resolve um problema e cria mais outros dois…

E se o usuário colocar as duas opções? Só uma funcionaria. E se uma das opções precisasse de um valor? Estilo “-f arquivo.log” gravaria um

arquivo de log com as operações.

Poderíamos escrever vários algoritmos que verificassem cada um de todos os argumentos, testasse se fosse um ou outro, utilizasse as opções… Mas felizmente não precisamos fazer nada disso! O bash conta com uma função interna que trata os argumentos: o famoso getopts.

Utilizando o getopts para tratar tratar argumentos e opções

Seguindo a mesma linha de raciocínio, vamos logo para um exemplo de programa. Supondo que queiramos um shell-script que faça isso:

Caso a opção -h seja usada, mostra a ajuda e sai do programa.

Page 41: Iniciação em Shell

Caso a opção -v seja usada, mostra a versão e sai do programa. Caso a opção -o <arquivo> seja usada, grava um arquivo de log com as

operações efetuadas e resultados. Caso a opção -u seja usada, mostra o resultado do comando “uname -a” Caso a opção -m seja usada, mostra o resultado do comando “free -m” Caso a opção -s seja usada, mostra o resultado do comando “swap -s”

Note que apenas as opções -h e -v saem do programa após a execução. Agora vamos ao código:

?010203040506070809101112131415161718192

#!/bin/bash

 function PrintUsage() {   echo "Uso: `basename $0` <-umsf> [-ohv]"   exit 1}

 while getopts "hvo:umsf" OPTIONdo   case $OPTION in      h) PrintUsage         ;;      v) echo "`basename $0` versao 666."         exit         ;;      o) ARQUIVO_LOG=$OPTARG         ;;      u) DO_UNAME=1         ;;      m) DO_FREE=1         ;;      s) DO_SWAPON=1         ;;      ?) PrintUsage         ;;   esacdoneshift $((OPTIND-1)) if [ -z "$DO_UNAME" ] && [ -z "$DO_FREE" ] && [ -z "$DO_SWAPON" ] && [ -z "$DO_FDISK" ]; then   PrintUsagefi

 if [ "$ARQUIVO_LOG" ]; then   echo "Execucao iniciada em `date`." >> $ARQUIVO_LOG

    if [ "$DO_UNAME" == 1 ]; then      uname -a >> $ARQUIVO_LOG   fi

    if [ "$DO_FREE" == 1 ]; then      free -m >> $ARQUIVO_LOG   fi

    if [ "$DO_SWAPON" == 1 ]; then

Page 42: Iniciação em Shell

02122232425262728293031323334353637383940414243444

      swapon -s >> $ARQUIVO_LOG   fielse   echo "Execucao iniciada em `date`."   if [ "$DO_UNAME" == 1 ]; then      uname -a   fi

    if [ "$DO_FREE" == 1 ]; then      free -m   fi

    if [ "$DO_SWAPON" == 1 ]; then      swapon -s   fifi

Page 43: Iniciação em Shell

5464748495051525354555657585960

O interessante para nós são as linhas 8 a 28. O laço while getopts começa a tratar todos os argumentos. A cada iteração do laço, ele coloca a letra da opção na variável $OPTION.

Note que para cada opção que precisamos, colocamos uma letra no primeiro argumento do getopts:

while getopts "hvo:umsf" OPTION

Note também que depois da letra o temos um dois pontos (:). Esse dois pontos significa que logo após a opção -o, o usuário precisa fornecer um valor. Este valor é automaticamente armazenado na variável $OPTARG.

Dessa maneira, podemos executar esse programa de diversas formas:

./tmp.sh -o arquivo.log -u(executa o "uname -a" e grava no arquivo arquivo.log)

./tmp.sh -um

Page 44: Iniciação em Shell

(executa os comandos "uname -a" e "free -m")

./tmp.sh -m -s -u(executa os comandos "free -m", "swapon -s" e "uname -a")

Ou seja, não importa a ordem, o getopts vai reconhecer e executar as ações de acordo com a opção especificada.

E se você colocar uma opção que não está contemplatada… O “?” do case irá ser executado, por exemplo:

$ ./tmp.sh -a./tmp.sh: illegal option -- aUso: tmp.sh <-umsf> [-ohv]

E dessa forma fica bem fácil de entender e usar o getopts :) Depois que o laço é todo feito e executado em todos os argumentos (no meu caso, preferi apenas configurar variáveis para cada opção e tratá-las depois), ele executa o comando que está na linha 28:

shift $((OPTIND-1))

Este comando faz com que os argumentos de opções sejam “comidos“, até que não sobre nenhuma opção. Em outras palavras, os argumentos representados pelas variáveis $N só serão aqueles que não pertençam a nenhuma opção. Exemplo:

./tmp.sh -u -o arquivo.log -m argumento1 argumento2

Nesse caso, o $1 seria o argumento1 e o $2 seria o argumento2, quando na verdade, sem o shift, eles seriam respectivamente o $5 e $6.

Como nem tudo é perfeito, a função getopts do bash não aceita opções longas (–nome-da-opcao), ou seja, voce só pode utilizar uma letra como opção. Represente bem suas opções com as letras! :)

Argumentos dentro de funções

Se dentro de um shell-script temos uma função, essa função é enxergada pela shell como se fosse um comando. Nesse sentido, dentro de uma função as variáveis $N definidas pelo programa não funcionarão. Exemplo:

?010203040506070809

#!/bin/bash

 function Dummy() {   echo "Numero de argumentos: $#"    COUNT=0   for ARG in $*; do      COUNT=`expr $COUNT + 1`      echo "Argumento $COUNT: $ARG"   done}

Page 45: Iniciação em Shell

10111213

 Dummy

Não importa o que você executar com o script acima, a saída será sempre a mesma: 0 números de argumentos, como mostrado a seguir.

$ ./tmp.shNumero de argumentos: 0

$ ./tmp.sh naosei temporarioNumero de argumentos: 0

$ ./tmp.sh a b c d e f gNumero de argumentos: 0

Para a função Dummy, as variáveis especiais dos argumentos funcionam apenas para a função e não para o programa inteiro. É como se as variáveis fossem locais, e não globais. Vamos então substituir a linha da chamada da função Dummy (linha 13) por:

Dummy a b c d

E tentar executar novamente:

$ ./tmp.shNumero de argumentos: 4Argumento 1: aArgumento 2: bArgumento 3: cArgumento 4: d

Sabendo disso, não se percam na hora de usar os argumentos dentro das funções e lembrem-se que isto pode ser útil na hora de implementar diversas funções dentro de um script. Um bom exemplo disso é implementar a função PrintUsage que usamos anteriormente para, além de mostrar uma mensagem de uso, mostrar também uma mensagem de erro personalizada:

?12345

function PrintUsage() {   [ "$1" ] && echo -ne "Erro: $1\n"   echo "Uso: $(basename $0)  <-umsf> [-ohv]"   exit 1}

Agora é so chamar a função como…

PrintUsage "Faltando parâmetros."PrintUsage "Opção inválida."PrintUsage "No donut for you."

Use a criatividade de um programador (afinal, programação é arte) e comece a aprimorar suas ferramentas bash! :)

Page 46: Iniciação em Shell

Shell-Script: Reconexão Automática

Este shell-script verifica se uma máquina está conectada na rede, e caso não esteja, reconecta-se de alguma forma. Para funcionar, além do script é necessário também o agendador de tarefas crontab.

O script, checkConn.sh:

#!/bin/bash#

Page 47: Iniciação em Shell

# IP de TesteTEST_IP="74.125.47.147"

# UDHCPCUDHCPC=/sbin/udhcpc

if ! `ping -c1 $TEST_IP > /dev/null 2>&1`; then $UDHCPC -i eth0 -qelse exit 0fi

O TEST_IP é um IP da Internet para que o ping seja feito. Neste exemplo, usei um dos IPs do Google. Também, neste caso utilizei o cliente DHCP UDHCPC.

Em resumo, este script pinga um IP e caso não haja resposta, executa o udhcp pedindo um novo IP. É uma solução simples e não é totalmente segura. Por exemplo, se o IP que tentamos pingar está fora, ao invés da própria máquina, ele vai executar mesmo assim.

Com pequenas alterações, podemos colocar o dhclient para ser usado, ao invés do udhcpc. Ou também podemos colocar depois do “if” quaisquer comandos (como por exemplo, um log) que acontecerão quando a conexão falhar.

Escolha um intervalo para ficar executando este script. Aqui colocarei o script para ser executado de 2 em 2 minutos. Para fazer o agendamento, usamos o crontab executando como root “crontab -e” ou (2a. opção) editando o arquivo “/etc/crontab”. A linha:

*/2 * * * * /usr/local/bin/checkConn.sh

…fará isso.

O comando nohup

Essa é uma dica simples e rápida, mas que me quebrou um galho (ou seria árvore?) um dia desses. Eu precisava deixar um comando rodando num servidor remoto, porém não continuaria conectado via ssh neste. Ao executar o comando passando o famoso "&" no final da linha o terminal ficava livre, mas ao deslogar do terminal o comando recebia um sinal de hangup e "morria". 

Page 48: Iniciação em Shell

Enfim, pra rodar um comando em background e fazer com que o mesmo fique imune a sinais de hangup, usa-se o comando nohup. 

Exemplo de uso: 

# nohup ./comando_que_vai_demorar & 

A saída do comando será gravada no arquivo nohup.out, que será criado no diretório corrente (onde o comando foi executado). Agora você pode desconectar do terminal remoto e ir pra casa tranquilo. Simples assim! 

Fonte: http://www.devin.com.br/shell_script/