Saltar para o conteúdo
102 · LPIC-1 (parte 2)

105.2 Editar e escrever scripts simples

TópicoT02ObjetivoEditar e escrever scripts simples de shellPeso4PáginasLPIC-1 (102) - Version 5.0

Resumo Conciso

Estrutura de um script bash

bash
#!/bin/bash# Comentárioecho "Hello world!"
  • Shebang (#!): define o interpretador na primeira linha
  • Linhas com # após o shebang são comentários
  • Linhas em branco são ignoradas

Execução de scripts

MétodoComandoExecuta em…
Interpretador explícitobash script.shSub-shell
Com bit de execuçãochmod +x script.sh; ./script.shSub-shell
PATHscript.sh (se em directório do PATH)Sub-shell
No shell atualsource script.sh ou . script.shShell atual
Substitui shell atualexec script.shShell atual (substitui)

Parâmetros especiais do script

ParâmetroSignificado
$0Nome do ficheiro de script
$1..$9, ${10}Parâmetros posicionais (argumentos)
$* / $@Todos os argumentos passados
$#Nº de argumentos
$?Código de status do último comando (0 = sucesso)
$$PID do shell atual
$!PID do último processo em background

Variáveis e arrays

bash
VAR="valor"           # Atribuição (sem espaços ao redor de =)echo $VAR             # Referênciaecho ${#VAR}          # Comprimento da stringdeclare -a ARR        # Declarar arrayARR=( elem1 elem2 )   # Array implícitoecho ${ARR[0]}        # Primeiro elementoecho ${#ARR[@]}       # Nº de elementos

Substituição de comandos

bash
VAR=$(comando)        # Forma modernaVAR=`comando`         # Forma antiga (backtick)

Expressões aritméticas

bash
SUM=$(( $VAL1 + $VAL2 ))RESULT=$(( 1024 ** 3 ))

Execução condicional

OperadorComportamento
A && BB executa só se A for bem-sucedido ($?=0)
A || BB executa só se A falhar ($?≠0)

Estrutura if

bash
if [ CONDIÇÃO ] ; then    COMANDOSelif [ CONDIÇÃO ] ; then    COMANDOSelse    COMANDOSfi

Estrutura case

bash
case "$VAR" in    padrao1|padrao2)        COMANDOS ;;    *)        COMANDOS ;;esac

Construções de loop

bash
# for — percorre uma listafor VAR in LISTA; do    COMANDOSdone# for estilo Cfor (( IDX=0; IDX<N; IDX++ )); do    COMANDOSdone# while — repete enquanto condição for verdadeirawhile [ CONDIÇÃO ]; do    COMANDOSdone# until — repete até condição ser verdadeirauntil [ CONDIÇÃO ]; do    COMANDOSdone

Testes de ficheiros (test / [ ])

OpçãoAvalia
-fFicheiro regular existe
-dÉ um directório
-eExiste no sistema de ficheiros
-rÉ legível
-wÉ gravável
-xÉ executável
-sExiste e não está vazio
-h / -LÉ um link simbólico
-ntMais recente que outro ficheiro
-otMais antigo que outro ficheiro

Testes numéricos

OpçãoAvalia
-eqIgual
-neDiferente
-ltMenor que
-gtMaior que
-leMenor ou igual
-geMaior ou igual

Saída do script

ComandoFunção
echo "texto"Exibe texto (nova linha automática)
echo -n "texto"Sem nova linha
echo -e "lin1\nlin2"Interpreta sequências de escape
printf "%s\n" "$VAR"Saída formatada (C-style)

Exercícios Exploratórios

Exercício Exploratório 1 — Erro "Permission denied" ao executar script

Enunciado: Após criar um script, o utilizador recebe bash: ./script.sh: Permission denied. Qual a causa provável?

O ficheiro não tem permissão de execução. Solução:

bash
chmod +x script.sh./script.sh

Enunciado: O script do.sh é executável e undo.sh é um link simbólico para ele. Como identificar dentro do script se foi chamado como do.sh ou undo.sh?

A variável especial $0 contém o nome do ficheiro usado para chamar o script:

bash
#!/bin/bashecho "Este script foi chamado como: $0"

Se chamado via undo.sh, $0 será undo.sh.

Exercício Exploratório 3 — Enviar email de erro com if

Enunciado: Escreva uma instrução if para enviar email ao root somente se o comando anterior falhar.

bash
if [ "$?" -ne 0 ]; then    mail -s "Maintenance Error" root <<<"Scheduled task error"fi

A variável $? armazena o código de status do último comando. -ne (not equal) verifica se é diferente de 0 (falha).

Exercício Exploratório 4 — Criar array com argumentos do script

Enunciado: Como usar todos os argumentos de linha de comando para inicializar um array Bash?

bash
PARAMS=( "$@" )# ouPARAMS=( $* )

"$@" preserva aspas individuais de cada argumento, sendo a forma recomendada.

Exercício Exploratório 5 — Script de sincronização com mapfile

Enunciado: Escreva um script que sincronize ficheiros de um directório de origem para um destino usando mapfile e um ficheiro de lista.

bash
#!/bin/bashset -efFILE=~/.sync.listFROM=$1TO=$2if [ ! -d "$FROM" -o ! -d "$TO" ]; then    echo "Usage: $0 <SOURCEDIR> <DESTDIR>"    exit 1fimapfile -t LIST < "$FILE"for (( IDX=0; IDX < ${#LIST[*]}; IDX++ )); do    echo -e "$FROM/${LIST[$IDX]} → $TO/${LIST[$IDX]}"    rsync -qa --delete "$FROM/${LIST[$IDX]}" "$TO"done

mapfile -t lê cada linha do ficheiro para um elemento do array, removendo o \n final.

Exercício Exploratório 6 — Formatação com printf

Enunciado: Reescreva o seguinte echo -e usando printf para exibir o SO e a RAM livre formatados.

bash
echo -e "Operating system:\t$OS"echo -e "Unallocated RAM:\t$(( $FREE / 1024**2 )) MB"
bash
printf "Operating system:\t%s\nUnallocated RAM:\t%d MB\n" "$OS" "$(( $FREE / 1024**2 ))"

printf não adiciona \n automaticamente — é necessário incluir no formato. %s para strings, %d para inteiros.