Declarando funções
Existem duas formas de declarar funções no Bash. Ambas são equivalentes:
# Forma 1: com a palavra-chave function
function saudar {
echo "Olá, $1!"
}
# Forma 2: com parênteses (mais portável, compatível com POSIX sh)
saudar() {
echo "Olá, $1!"
}
saudar "admin"
Olá, admin!
Parâmetros posicionais
Dentro de uma função, $1, $2, etc. referem-se aos argumentos passados para a função (não para o script).
criar_usuario() {
local NOME="$1"
local GRUPO="$2"
local SHELL="${3:-/bin/bash}" # padrão: /bin/bash
echo "Criando usuário: $NOME"
echo " Grupo: $GRUPO"
echo " Shell: $SHELL"
echo " Total de argumentos: $#"
}
criar_usuario "joao" "devops" "/bin/zsh"
criar_usuario "maria" "sre"
Criando usuário: joao
Grupo: devops
Shell: /bin/zsh
Total de argumentos: 3
Criando usuário: maria
Grupo: sre
Shell: /bin/bash
Total de argumentos: 2
return
O return define o código de saída da função (0-255). Não é para retornar dados — para isso, use echo e capture com $().
usuario_existe() {
id "$1" &> /dev/null
return $? # propaga o código de saída do id
}
if usuario_existe "root"; then
echo "Usuário root existe"
fi
Usuário root existe
Para retornar valores, use echo:
obter_ip() {
local IFACE="$1"
ip -4 addr show "$IFACE" | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
}
MEU_IP=$(obter_ip "eth0")
echo "IP da eth0: $MEU_IP"
IP da eth0: 192.168.1.50
local e escopo de variáveis
Sem local, variáveis dentro de funções são globais. Isso causa bugs sutis.
MSG="global"
sem_local() {
MSG="modificada dentro da função"
}
com_local() {
local MSG="só existe aqui"
echo "Dentro: $MSG"
}
sem_local
echo "Após sem_local: $MSG"
com_local
echo "Após com_local: $MSG"
Dentro: só existe aqui
Após sem_local: modificada dentro da função
Após com_local: modificada dentro da função
Dica: Sempre use
local para variáveis dentro de funções. Isso evita colisões com variáveis globais e torna o código mais previsível.Funções como comandos
Funções se comportam como comandos comuns. Você pode usá-las em pipes, redirecionar saída e combiná-las com outros comandos.
listar_servicos_ativos() {
systemctl list-units --type=service --state=running --no-legend \
| awk '{print $1}'
}
# Usando em pipe
listar_servicos_ativos | grep ssh
# Redirecionando saída
listar_servicos_ativos > /tmp/servicos_ativos.txt
# Contando resultados
echo "Serviços ativos: $(listar_servicos_ativos | wc -l)"
Um padrão útil é criar uma biblioteca de funções em um arquivo separado e carregá-la com source:
# /usr/local/lib/utils.sh
log_info() { echo "[INFO] $(date +%H:%M:%S) $*"; }
log_warn() { echo "[WARN] $(date +%H:%M:%S) $*"; }
log_error() { echo "[ERROR] $(date +%H:%M:%S) $*" >&2; }
# No seu script:
source /usr/local/lib/utils.sh
log_info "Backup iniciado"
log_warn "Espaço em disco baixo"
log_error "Falha na conexão"
[INFO] 14:32:07 Backup iniciado
[WARN] 14:32:07 Espaço em disco baixo
[ERROR] 14:32:07 Falha na conexão
Dica: Use
declare -F para listar todas as funções definidas no shell atual. Útil para depuração e para verificar se uma função de biblioteca foi carregada corretamente.