Shell script

Programa de computador projetado para ser executado pelo shell Unix / Linux
Bash - linha de comando

Shell script 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 ver scripts sendo utilizados para automatização de tarefas, como configurar o ambiente, executar um programa e fazer qualquer limpeza, registro, etc. Este tipo de tarefas executadas por scripts em Shells são conhecidas mais popularmente como Shell Wrappers.

HistóriaEditar

A primeira linguagem de script em Shell, que veio a ser criada e implementada na versão 7 do Unix Shell ficou conhecida como Bourne Shell (sh) e foi criada por Stephen R. Bourne, Após a implementação da linguagem Bourne Shell (sh), diversas outras linguagens de scripts baseadas no (sh) vieram, como Korn Shell, DMERT Shell, e em 1989 veio a ser lançada a linguagem que se tornou Shell de login padrão em diversas distribuições Linux, O GNU Bash ou simplesmente Bash.


Funcionalidades e CapacidadesEditar

Selecionar ShellEditar

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:

1 #!/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 ele estará em todas elas no mesmo diretório /bin/, então use a seguinte forma:

1 #!/usr/bin/env bash

ComentáriosEditar

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áveisEditar

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é-definidasEditar

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 GlobaisEditar

Variáveis globais ou variáveis de ambiente globais, são variáveis criadas/definidas com o comando export e podem ser utilizadas por multiplos 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

ArrayEditar

Bourne Shell (sh) não é compatível com variáveis tipo array, mas Bourne-Again Shell (Bash) sim, exemplo simples de implementação:

1 #!/usr/bin/env bash
2 meu_array=(1 2 3 4 5 6 7 8 9)
3 meu_Array=("abc" "def" "ghi")

Chamar variáveisEditar

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áveisEditar

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

IfEditar

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

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:

1 if [ $1 = $2 ]; then
2     echo "Parametro 1 ($1) é igual a 2 ($2)."
3 else
4     echo "Parametro 1 ($1) não é igual a 2 ($2)."
5 fi

Mas, existe uma abreviação que também é muito utilizada que é menor e muito boa para teste de linha única:

1 [ $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

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

CaseEditar

Scripts em Bash ou sh, permitem case, a sintaxe é a seguinte:

case "$var" in
    valor)
    ;;
esac

Expressões RegularesEditar

Scripts em Bash possui compatibilidade com Expressões Regulares, algo que scripts em Bourne Shell (sh) não reconhecem:

1 #!/usr/bin/env bash
2 [[ $1 =~ ^sh|SH$ ]] && { echo "$1 - Bourne Shell"; }

OperadoresEditar

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

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

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

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

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

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 ]

LoopEditar

ForEditar

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

WhileEditar

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çõesEditar

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ídaEditar

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:

1 [ ! -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 usoEditar

Criar Shell scriptEditar

Para criar um Shell script você precisa saber qual linguagem de script irá utilizar antes. Para criar um utilizando Bash por exemplo, basta criar um arquivo com extensão a .sh e colocar na primeira linha deste 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 ComandoEditar

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á analizar 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 antigosEditar

Apagar periodicamente arquivos mais velhos que 30 dias do diretório /tmp:

#!/usr/bin/env bash
cd /tmp
find . -type f -mtime +30 -delete

Veja tambémEditar

ReferênciasEditar


Ligações externasEditar

Outros projetos Wikimedia também contêm material sobre este tema:
  Livros e manuais no Wikilivros
  1. https://en.wikipedia.org/wiki/Stephen_R._Bourne