Shell script
![](http://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Bash_screenshot.png/220px-Bash_screenshot.png)
Shell script é o nome dado a um arquivo que será interpretado por algum programa tipo Shell. Atualmente existem vários programas tipo Shell. Além dos principais - sh e bash -, existem também, ksh, zsh, csh e tcsh. Um Shell script (ou script em Shell) necessita basicamente do interpretador Shell.
Algumas operações típicas executadas por linguagens de script em Shell incluem; manipulação de arquivos, execução de programas e impressão de texto. Sendo assim é muito comum que scripts sejam utilizados para automatização de tarefas - como configurar o ambiente, executar um programa e fazer qualquer limpeza, registro, etc. Essas tarefas executadas por scripts em Shell são conhecidas mais popularmente como Shell Wrappers.
História
[editar | editar código-fonte]A primeira linguagem de script em Shell, criada por Stephen R. Bourne, veio a ser implementada na versão 7 do Unix Shell e ficou conhecida como Bourne Shell (sh). Após a sua implementação, diversas outras linguagens de scripts baseadas no sh vieram, tais como Korn Shell, e DMERT Shell, sendo que, em 1989, foi lançada a linguagem que se tornou Shell de login padrão em diversas distribuições Linux, a GNU Bash ou simplesmente Bash.
Funcionalidades e Capacidades
[editar | editar código-fonte]Selecionar Shell
[editar | editar código-fonte]Para selecionar qual Shell será utilizado, use a combinação de hashtag (#) mais exclamação (!) e caminho do executável na primeira linha do arquivo script, isso vem a ser conhecido como Shebang.
- Para declarar que o script deve ser interpretado por Bourne Shell (sh) a primeira linha será escrita da seguinte forma:
#!/bin/sh
- Para declarar que o script deve ser interpretado por Bourne-Again shell (Bash) é recomendável a utilização do comando env, pelo fato que apesar de o Bash já vir instalado em muitas distribuições Linux, não sabemos se estará em todas elas no mesmo diretório /bin/, então use a seguinte forma:
#!/usr/bin/env bash
Comentários
[editar | editar código-fonte]Os comentários nas linguagens Bourne Shell (sh) e Bourne-Again Shell (bash) serão utilizados hashtag (#), Exemplo de comentários:
#Comentário
#- Segundo comentário
# // [ Terceiro comentário ] //
Variáveis
[editar | editar código-fonte]Como qualquer outra linguagem de programação conhecida, um script em Shell também possui suporte a variáveis. Em uma breve explicação uma variável é um nome/objeto simbólico ao qual podemos atribuir valores, ler ou manipular o conteúdo. Para mais informações, leia-me. Os scripts em Shell podem lidar com diferentes tipos de variáveis sem precisar definir o tipo:
MENSAGEM_DATA=1979
MENSAGEM_NOME="Bourne Shell"
mensagem_tipo1="Unix Shell"
mensagem_autor="Stephen Bourne"
MENSAGEM=ola
_MENSAGEM2=oi-2.020
Variáveis Pré-definidas
[editar | editar código-fonte]Os scripts em Shell possuem as seguintes variáveis pré-definidas:
$?
- Armazena o status de saída do último programa executado;$#
- Armazena a quantidade de parâmetros de linha de comandos;$$
- Armazena o valor PID (Process Identifier) do script em shell que estiver em execução;$@
- Armazena o valor de todos os parâmetros passados, similar a variável argv presente nas linguagens de programação C e C++;$!
- Armazena o PID do último processo em segundo plano. Isso é útil para acompanhar o processo à medida que o trabalho é realizado;$0, ..., $9
- Armazena os valores de todos os parâmetros de linha de comando separadamente;
Variáveis Globais
[editar | editar código-fonte]Variáveis globais ou variáveis de ambiente globais, são variáveis criadas/definidas com o comando export e podem ser utilizadas por múltiplos scripts em Shell. Um exemplo é a variável de ambiente LANG (Pré-definida em diversas distribuições Linux), Podendo ser acessada por diversos arquivos de script em Shell.
Outras variáveis pré definidas são:
- PATH: define diretórios de procura por programas executados no shell;
- USER: informa o nome do usuário do shell;
- HOME: informa o caminho do diretório home do usuário;
- LANG: Idioma/Linguagem, especificada como locale;
- PWD: diretório atual;
- TERM: Tipo de terminal atual em uso.
- UID: UID do usuário atual.
- RANDOM: Gera um número aleatório
A duas formas de criar uma variável global, exportar uma variável pré definida ou definir quando for exportar:
VARIAVEL1=Teste
export VARIAVEL1
# Define e exporta com export
export VARIAVEL2=Teste
Array
[editar | editar código-fonte]Bourne Shell (sh) não é compatível com variáveis tipo array, mas Bourne-Again Shell (Bash) sim, exemplo simples de implementação:
#!/usr/bin/env bash
meu_array=(1 2 3 4 5 6 7 8 9)
meu_Array=("abc" "def" "ghi")
Array Associativo
[editar | editar código-fonte]Podemos construir em Bash arrays associativos, também chamados de dicionários
#!/usr/bin/env bash
declare -A dicionario
dicionario["Brasil"]="Brasília"
dicionario["Goiás"]="Goiânia"
dicionário["São Paulo"]="São Paulo"
dicionario[Sergipe]=Aracajú
echo ${dicionario["Brasil"]}
Chamar variáveis
[editar | editar código-fonte]Para chamar variáveis utiliza-se o sinal de cifrão $var. O cifrão ($) também é bastante utilizado em script sh, para executar programas externos exemplo: var=$(expr 2 + 2)
irá armazenar a saída do programa expr. E o cifrão mais chave ${var} é comum ser utilizado das seguintes maneiras:
Para acessar posições em um array ${var[1]}. (obs.: não funciona para sh, apenas para Bash)
E também para substituir o valor de uma variável se a mesma não possuir um valor: ${var:-nome} - ${var:=nome} - ${var:-$(programa)} dessas maneiras irão substituir pelo que for passado depois de :- ou :=, exemplo em código:
read -p "Digite um nome: " myname
echo "${myname:=$(whoami)}"
O código acima irá pedir para o usuário digitar um nome, caso digite irá utilizar echo para imprimir o nome digitado na saída padrão, caso contrário irá substituir pela saída do comando whoami, ao invés de substituir pela saída de um comando, você pode substituir por outro valor exemplo: ${myname:=Bourne Shell}
.
Remover Variáveis
[editar | editar código-fonte]Para remover uma variável, utiliza-se o comando unset + nome da variável, você pode também remover múltiplas variáveis basta separá-las por espaços.
unset VAR
unset VAR1 VAR2 VAR3 VAR4
If
[editar | editar código-fonte]Declaração if para scripts em bash ou sh:
if [ $1 = $2 ]; then
echo "Parametro 1=$1 é igual a 2=$2."
fi
Existe também outra forma:
[ $1 = $2 ] && { echo "Parametro 1 ($1) é igual a 2 ($2)."; exit 0; }
If-else
[editar | editar código-fonte]Declaração if else para scripts em bash ou sh, há diversas formas diferentes, tenha cuidado para não esquecer os espaços entre os colchetes eles são muito importantes:
A declaração if else mais comum e mais utilizada é a seguinte:
if [ $1 = $2 ]; then
echo "Parametro 1 ($1) é igual a 2 ($2)."
else
echo "Parametro 1 ($1) não é igual a 2 ($2)."
fi
Mas, existe uma abreviação que também é muito utilizada que é menor e muito boa para teste de linha única:
[ $1 = $2 ] && { echo "Parametro 1 ($1) é igual a 2 ($2)."; exit 0; } || { echo "Parametro 1 ($1) é diferente de 2 ($2)."; exit 0; }
Else-if
[editar | editar código-fonte]Declaração else if para scripts em bash ou sh são diferentes de algumas linguagens de programação, exemplo:
if [ $3 ]; then
echo "$3"
elif [ $2 ]; then
echo "$2"
else
echo "$1"
fi
Case
[editar | editar código-fonte]Scripts em Bash ou sh, permitem case, a sintaxe é a seguinte:
case "$var" in
valor)
;;
esac
Expressões Regulares
[editar | editar código-fonte]Scripts em Bash possui compatibilidade com Expressões Regulares, algo que scripts em Bourne Shell (sh) não reconhecem:
#!/usr/bin/env bash
[[ $1 =~ ^sh|SH$ ]] && { echo "$1 - Bourne Shell"; }
Operadores
[editar | editar código-fonte]Existem diversos operadores para cada Shell script, mas aqui serão passadas informações especificamente sobre Bourne shell por ser mais comum e muitos outros shell são similares. Os seguintes operadores serão explicados aqui:
- Operadores Aritméticos
[editar | editar código-fonte]Operadores | Descrição | Exemplos |
---|---|---|
+ (Adição) | Utilizado para somar valores em ambos lados do operador | $(expr 10 + 20) será igual 30 |
- (Subtração) | Utilizado para subtrair valores do lado direito para o esquerdo | $(expr 20 - 30) será igual -10 |
*(Multiplicação) | Utilizado para multiplicar valores em ambos lados do operador | $(expr 2 \* 6) será igual a 12 |
/ (Divisão) | Utilizado para dividir o valor esquero pelo direito do operador | $(expr 12 / 6) será igual a 2 |
% (Módulo) | Utilizado para dividir o valor da esquerda pelo da direita e retornar o restante | $(expr 12 % 6) será igual a 0 |
= (Igual) | Utilizado para atribuir valores e para testar valores. | x=2 Atribui o valor 2 para variável x.
[ $x = 2 ] Se $x é igual a 2 |
!= (Não igual) | Utilizado para testas se um valor é diferente de outro. | [ $x != 3 ] Se $x é diferente de 3 |
- Operadores Booleanos
[editar | editar código-fonte]Operadores | Descrição | Exemplos |
---|---|---|
! (Diferente) | Conhecido como Operador Lógico de negação. Utilizado para inverter
uma condição de verdadeira para falsa e vice versa. |
[ ! $x = 22 ] Se o valor de x é diferente de 22. |
-o (ou) | Conhecido como Operador Lógico OR. Utilizado para testar duas ou
mais possibilidades. |
[ $x = 22 -o $x = 23 ] Se o valor de x
é igual a 22 ou 23 |
-a (e) | Conhecido como Operador Lógico AND. Utilizado para testar duas ou
mais possibilidades. |
[ $y = 22 -a $x = 22 ] Se o valor de x e y
são iguais a 22 |
- Operadores para Teste de Arquivos
[editar | editar código-fonte]Operadores | Descrição | Exemplos |
---|---|---|
-b arquivo | Verifica se o arquivo é um arquivo especial de bloco; se sim, então a
condição se torna verdadeira. |
[ -b /etc/resolv.conf ] |
-c arquivo | Verifica se o arquivo é um arquivo especial de caracteres; se sim, então a
condição se torna verdadeira. |
[ -c /etc/resolv.conf ] |
-d arquivo | Verifica se o arquivo é um diretório; se sim, então a condição se torna
verdadeira |
[ -d /etc/resolv.conf ] |
-f arquivo | Verifica se arquivo é um arquivo comum em oposição a um diretório ou
arquivo especial; se sim, então a condição se torna verdadeira. |
[ -f /etc/resolv.conf ] |
-g arquivo | Verifica se o arquivo possui o seu conjunto de bits de identificação de grupo
(SGID); se sim, então a condição se torna verdadeira. |
[ -g /etc/resolv.conf ] |
-k arquivo | Verifica se o arquivo tem seu bit fixo definido; se sim, então a condição
se torna verdadeira. |
[ -k /etc/resolv.conf ] |
-p arquivo | Verifica se o arquivo é um pipe nomeado; se sim, então a condição
se torna verdadeira. |
[ -p /etc/resolv.conf ] |
-t arquivo | Verifica se o descritor de arquivo está aberto e associado a um terminal;
se sim, então a condição se torna verdadeira. |
[ -t /etc/resolv.conf ] |
-u arquivo | Verifica se o arquivo tem seu bit Set ID do usuário (SUID) definido;
se sim, então a condição se torna verdadeira. |
[ -u /etc/resolv.conf ] |
-r arquivo | Verifica se o arquivo está legível; se sim, então a condição se torna
verdadeira. |
[ -r /etc/resolv.conf ] |
-w arquivo | Verifica se o arquivo é gravável; se sim, então a condição se torna
verdadeira. |
[ -w /etc/resolv.conf ] |
-x arquivo | Verifica se o arquivo é executável; se sim, então a condição se torna
verdadeira. |
[ -x /etc/resolv.conf ] |
-s arquivo | Verifica se o arquivo tem tamanho maior que 0; se sim, então a condição
se torna verdadeira. |
[ -s /etc/resolv.conf ] |
-e arquivo | Verifica se o arquivo existe; é verdadeiro mesmo se o arquivo for um
diretório, mas existe. |
[ -e /etc/resolv.conf ] |
- Operadores Relacionais
[editar | editar código-fonte]Operadores | Descrição | Exemplos |
---|---|---|
-eq | Verifica se o valor de dois operandos é igual ou não; se sim, então a condição
se torna verdadeira. |
[ $x -eq 2 ] |
-ne | Verifica se o valor de dois operandos é igual ou não; se os valores não forem
iguais, a condição se tornará verdadeira. |
[ $x -ne 2 ] |
-gt | Verifica se o valor do operando esquerdo é maior que o valor do operando
direito; se sim, então a condição se torna verdadeira. |
[ $x -gt 2 ] |
-lt | Verifica se o valor do operando esquerdo é menor que o valor do operando
direito; se sim, então a condição se torna verdadeira. |
[ $x -lt 2 ] |
-ge | Verifica se o valor do operando esquerdo é maior ou igual ao valor do operando
direito; se sim, então a condição se torna verdadeira. |
[ $x -ge 2 ] |
-le | Verifica se o valor do operando esquerdo é menor ou igual ao valor do
operando direito; se sim, então a condição se torna verdadeira. |
[ $x -le 2 ] |
- Operadores de String
[editar | editar código-fonte]Operadores | Descrição | Exemplos |
---|---|---|
-z | Verifica se o tamanho do operando da string fornecido é zero; se tiver comprimento
zero, retornará verdadeiro. |
[ -z $str ] |
-n | Verifica se o tamanho do operando da string especificado é diferente de zero;
se tiver um comprimento diferente de zero, retornará true. |
[ -n $str ] |
[ $uma_var ] | Verifica se Uma_var não é a string vazia; se estiver vazio, ele retornará false. | [ $str ] |
Loop
[editar | editar código-fonte]For
[editar | editar código-fonte]Esse tipo de loop funciona da mesma forma para ambos Bash e sh.
# Irá executar echo "Test" 3 vezes
for i in 1 2 3
do
echo "Test"
done
# Em apenas uma linha
for i in 1 2 3; do echo "Test"; done
While
[editar | editar código-fonte]Existem diversas formas de utilizar o loop while para scripts em Bash ou sh:
while [ -z $a_input ]; do
read -p "Enter para continuar ou digite qualquer coisa para sair: " a_input
done
while [ -z $b_input ]; do read -p "Enter para continuar ou digite qualquer coisa para sair: " b_input; done
while read -p "Digite um numero: " c_input
do
if [ $c_input -gt 25 ]; then
echo "Numero $c_input é maior que 25"
break
else
echo "Numero $c_input é menor que 25"
break
fi
done
Funções
[editar | editar código-fonte]O scripts em Shell também aceitam funções. Bash e sh aceitam um mesmo padrão de funções, mas o Bash também aceita um outro formato que o sh não reconhece. Ambos formatos são mostrados abaixo:
# Ambos aceitam esse formato
minha_função(){
echo
}
# Esse formato apenas Bash aceitará
function minha_função(){
echo
}
Para chamar uma função basta digitar o nome da função em uma linha após a declaração da função como se fosse um comando. Exemplo:
nova_função() {
echo "Olá, Mundo!"
}
nova_função
Status de saída
[editar | editar código-fonte]O status de saída de um comando executado são valores, retornados pela chamada do sistema waitpid ou função equivalente. Os valores para o status de saída ficam entre 0 e 255; Os status de saída dos Shell builtins e comandos compostos também são limitados a esse intervalo. Sob certas circunstâncias, o shell usará valores especiais para indicar modos de falha específicos.
Para os propósitos do Shell, um comando que sai com um status de saída igual a 0 (zero) significa que a execução do script foi bem-sucedida. Você pode ver os exemplos passados anteriormente onde a última linha do script o status de saída é 0 (zero). Já um status de saída diferente de zero indica falha. Esse esquema aparentemente contra-intuitivo é usado para que haja uma maneira bem definida de indicar sucesso e uma variedade de maneiras para indicar vários modos de falha.
Quando um comando termina em um sinal fatal cujo número é N, o Bash por exemplo usa o valor 128+N como status de saída. Se um comando não for encontrado, o processo filho criado para executá-lo retornará um status 127. Se um comando for encontrado, mas não for executável, o status de retorno será 126. Um exemplo de uma implementação simples de status de saída:
[ ! -e /bin/bash ] && { exit 2; }
O próximo exemplo irá checar se um comando não foi executado com sucesso:
ping -c1 wikipedia..org
[ $? -ne 0 ] && echo "O comando ping emitiu algum erro."
Os script passados acima são para exemplos de implementação..
Exemplos de uso
[editar | editar código-fonte]Criar Shell script
[editar | editar código-fonte]Para criar um Shell script você precisa saber, antes, qual linguagem de script irá utilizar . Se for utilizar Bash, por exemplo, basta criar um arquivo com a extensão .sh e colocar na primeira linha desse arquivo o shebang para bash.
Para distribuições com base Linux, abra o terminal e digite os seguintes comandos:
echo '#!/usr/bin/env bash' > novo_script.sh
E depois de criado você deve tornar o arquivo executável, utilizando o seguinte comando: chmod u+x novo_script
Verificar parâmetros de linha de comando
[editar | editar código-fonte]Para verificar parâmetros de linha de comando com Bourne shell, há apenas uma maneira recomendável: utilizar loop + case + shift. Já com Bash há mais de uma, pelo fato de o Bash suportar expressões regulares.
Testar parâmetros utilizando loop + case + shift:
while [ $# -gt 0 ]; do
case "$1" in
version | -v) echo "Release v0.1.0 - from Wikipedia.org";;
*) echo "$0: Este parâmetro '$1' não foi reconhecido, saindo...";exit 1;;
esac
shift
done
O loop while acima irá iniciar se e somente se houver um parâmetro. O case irá analisar os parâmetros e o shift irá mudar de parâmetros se houver mais de um e terminar o loop caso não haja mais nenhum. Caso você tenha muitas opções para o seu script deixe help e version sempre como as primeiras e utilize break para terminar o loop.
Apagar arquivos antigos
[editar | editar código-fonte]Apagar periodicamente arquivos mais velhos que 30 dias do diretório /tmp:
#!/usr/bin/env bash
cd /tmp
find . -type f -mtime +30 -delete
Ver também
[editar | editar código-fonte]Ligações externas
[editar | editar código-fonte]- «Bash scripting» (em inglês). Guia do Ubuntu