domingo, 4 de janeiro de 2026

Executar Scripts Remotamente

Introdução

Muitas vezes, em uma rede, laboratório ou em um cluster (ou até mesmo de um único computador para outro), é necessário rodar um script remotamente e temos de contornar a senha do SSH. Com o presente artigo e os scripts adiante, executaremos scripts remotamente.

Pode parecer uma falha de segurança, mas quando se trabalha com vários computadores em rede torna-se contraproducente ficar digitando a senha do SSH repetidas vezes, mas basta ter cuidado, pois trata-se de script para execução interna na rede/laboratório/cluster.

Além disso, temos dois scripts: um com senha SSH e outro somente com chave SSH (mais seguro). Utilize o que for mais conveniente para você. Use um ou outro, pois depende de como você configurou o SSH: com chave (mais seguro) ou com senha.

Não colocarei aqui como executar através do Linux um script/batch no Windows, pois não é o escopo do artigo.

A lógica é bem simples: coloque nos scripts executa-geral-senha.sh ou executa-geral-chave.sh o caminho e o nome do script que você quer executar remotamente.

Caso os dois scripts, o chamado e o chamador, façam conexões SSH dará erro e/ou pedirá senha em cima de senha; isso não é incontornável no Linux, mas para o que se pretende não vale a pena o trabalho.

Como bônus, deixo ao final o script copia-chave-distros.sh que deve ser executado diretamente no terminal com:

./copia-chave-distros.sh.

Tal script copia as chaves SSH, cria remotamente o arquivo /etc/sudoers.d/usuario e configura esse arquivo com ALL=(ALL) NOPASSWD: ALL e Defaults:usuario !requiretty.

Temos quatro seções no artigo:
1- Seção do script com senha;
2- Seção do script com chave;
3- Como utilizar os scripts e
4- Bônus.


Nível: Intermediário.

E, como sempre, respeitando a Velha Máxima casada com o Velho Ditado: tenha a decência de ler todo o artigo antes de sair executando comandos!


1 - Seção do Script com Senha (OPÇÃO COM SENHA SSH)

Crie o script:

$ sudo vim $HOME/caminho_diretorio/scripts/executa-geral-senha.sh

Usei o vim, use teu editor preferido e adapte o caminho para salvar o script de acordo com as tuas necessidades.

Coloque dentro (copie e cole o código):

#!/bin/bash

# ============================================
# Executa outros scripts por SSH com senha
# Compatível com Debian | Fedora | RHEL | Arch
# e derivados
# ============================================

# Caminho do script local a ser executado remotamente (modifique aqui)
SCRIPT_PATH="$HOME/caminho_diretorio/scripts/script.sh"

# Verifica se o script existe
if [ ! -f "$SCRIPT_PATH" ]; then
    echo "Script local não encontrado: $SCRIPT_PATH"
    exit 1 # Encerra o script caso o arquivo não exista
fi

# Extrai o nome do script do caminho
SCRIPT="$(basename "$SCRIPT_PATH")"
DESTINO="/opt/scripts/$SCRIPT"

# Senha sudo (texto plano - cuidado em ambientes sensíveis)
SENHA="senha"

# Lista de hosts/nós (modifique conforme necessário)
# Para vários hosts/nós: ("no01" "no02" "no03" "no04" ...)
NODES=("no01")

# Loop sobre cada host/nó
for NODE in "${NODES[@]}"; do
    echo ">>> Enviando $SCRIPT para $NODE..."

    # Copia o script para /tmp
    scp "$SCRIPT_PATH" "$NODE:/tmp/" || {
        echo -e "\033[1;31mFalha ao copiar para $NODE!\033[0m"
        continue
    }

    # Move para /opt com sudo, torna executável
    ssh "$NODE" "echo \"$SENHA\" | sudo -S mkdir -p /opt/scripts && sudo mv /tmp/$SCRIPT $DESTINO && sudo chmod +x $DESTINO; echo"

    # Executa o script remotamente com ou sem argumento adicional
    # Caso quiser colocar argumentos adicionais, se souber o que está fazendo
    # Senão deixe como está
	if [ "$SCRIPT" == "pvfs2-dist-keys.sh" ]; then
    		ssh "$NODE" "echo \"$SENHA\" | sudo -S bash $DESTINO /opt/orangefs; echo"
	elif [ "$SCRIPT" == "copia-chave-visudo.sh" ]; then
    		scp ~/.ssh/id_ed25519.pub "$NODE:/tmp/id_ed25519.pub"
    		ssh "$NODE" "echo \"$SENHA\" | sudo -S bash $DESTINO /tmp/id_ed25519.pub"
	else
    		ssh "$NODE" "echo \"$SENHA\" | sudo -S bash $DESTINO"
	fi

    if [ $? -eq 0 ]; then
    # Azul negrito: \033[1;34m
    # Azul forte: \033[38;5;39m
    echo
    echo -e "\033[1;34mSCRIPT EXECUTADO COM SUCESSO EM $NODE!!!\033[0m"
	else
    # Vermelho negrito: \033[1;31m
    echo
    echo -e "\033[1;31mERRO AO EXECUTAR SCRIPT EM $NODE!!!\033[0m"
    continue
fi
    echo
	# === LIMPEZA ===
	# Apaga o script da máquina remota (comente a linha abaixo, caso queira)
	sudo rm -rf /opt/scripts/$SCRIPT
done

Salve e saia.

Dê permissão de execução:

$ sudo chmod +x executa-geral-senha.sh

Para executar no servidor:

$ ./executa-geral-senha.sh

Ou, se for o caso:

$ sudo ./executa-geral-senha.sh


2 - Seção do Script com Chave ( OPÇÃO COM CHAVE SSH)

SCRIPT executa-geral-chave.sh

Agora temos o script executa-geral-chave.sh onde não tem a senha, pois configuramos o SSH para trabalhar com chave (é mais seguro).

Pré-requisitos (feito uma única vez)

Gera chave SSH (se ainda não existir):

$ ssh-keygen -t ed25519


Copia a chave para os hosts/nós:

$ ssh-copy-id usuario@no01


Ou:
$ ssh-copy-id usuario@192.168.1.100


Teste:

$ ssh usuario@no01

Ou:

$ ssh usuario@192.168.1.100

Não pedirá senha.


Configurar sudo sem senha no nó remoto:

$ sudo visudo -f /etc/sudoers.d/usuario


Coloque dentro do arquivo:

$ usuario ALL=(ALL) NOPASSWD: ALL


Crie o arquivo executa-geral-chave.sh (ou dê o nome que quiser) com seu editor de texto preferido e coloque dentro (copie e cole o código):

#!/bin/bash

# ============================================
# Executa outros scripts por SSH com chave
# Compatível com Debian | Fedora | RHEL | Arch
# e derivados
# ============================================

# Requisitos:
# Gere a chave SSH
# $ ssh-keygen -t ed25519
# Copie para os hosts/nós
# $ ssh-copy-id usuario@no01 e/ou ssh-copy-id usuario@192.160.1.100
# Teste:
# ssh usuario@no01 e/ou ssh usuario@192.168.1.100
# Não deve pedir senha
# Configure sudo sem senha no host/nó remoto, somente com chave
# $ sudo visudo -f /etc/sudoers.d/usuario
# Coloque dentro do arquivo
# usuario ALL=(ALL) NOPASSWD: ALL
# Defaults:usuario !requiretty

# Caminho do script local a ser executado remotamente (modifique aqui)
SCRIPT_PATH="$HOME/caminho_diretorio/scripts/script.sh"

# Verifica se o script existe
if [ ! -f "$SCRIPT_PATH" ]; then
    echo "Script local não encontrado: $SCRIPT_PATH"
    exit 1 # Encerra o script caso o arquivo não exista
fi

# Nome do script
SCRIPT="$(basename "$SCRIPT_PATH")"
DESTINO="/opt/scripts/$SCRIPT"

# Lista de hosts/nós (modifique conforme necessário)
# Para vários hosts/nós: ("no01" "no02" "no03" "no04" ...)
NODES=("no01")

# Loop sobre cada host/nó
for NODE in "${NODES[@]}"; do
    echo ">>> Enviando $SCRIPT para $NODE..."

    # Copia script para /tmp
    # scp = secure copy (copia arquivos via SSH)
    # -o BatchMode=yes = evita prompts de senha; falha se não houver autenticação por chave
    scp -o BatchMode=yes "$SCRIPT_PATH" "$NODE:/tmp/" || {
        echo "Falha ao copiar para $NODE"
        continue # Pula para o próximo host/nó em caso de erro
    }

    # Cria o diretório, move e dá permissão
    # ssh = conecta via SSH e executa comandos no host/nó remoto
    # -o BatchMode=yes = impede que ssh peça senha; útil para scripts automatizados
    ssh -t -o BatchMode=yes "$NODE" "
        set -e # encerra o ssh se algum comando falhar
        sudo mkdir -p /opt/scripts # cria diretório de destino se não existir
        sudo mv /tmp/$SCRIPT $DESTINO # move o script para o destino final
        sudo chmod +x $DESTINO # torna o script executável
		
	# Validação do bash, altere para tuas necessidades
    	   if [ ! -x /bin/bash ]; then
        	echo \"Erro: /bin/bash não encontrado ou não executável\"
        	exit 1
    	   fi

    # Executa o script remotamente com ou sem argumento adicional
    # Caso quiser colocar argumento adicional, se souber o que está fazendo
    # Senão deixe como está
    if [ \"$SCRIPT\" == \"pvfs2-dist-keys.sh\" ]; then
        sudo /bin/bash $DESTINO /opt/orangefs
    else
        sudo /bin/bash $DESTINO # executa o script remoto sem argumentos
    fi

    # === LIMPEZA ===
    # Apaga o script da máquina remota após a execução (comente a linha abaixo, caso queira)
    sudo rm -f $DESTINO

    " || {
	# Vermelho negrito: \033[31m
	echo
        echo -e "\033[1;31mERRO AO EXECUTAR NO HOST/NÓ $NODE!!!\033[0m"
        continue # pula para o próximo host/nó em caso de erro
    }
    # Azul negrito: \033[1;34m
    # Azul forte: \033[38;5;39m
    echo
    echo -e "\033[1;34mSCRIPT EXECUTADO COM SUCESSO EM $NODE!!!\033[0m"
    echo
done

Salve e saia.
Dê permissão de execução.


3 - Como Utilizar

Por exemplo, temos o script atualiza-remoto-distros.sh que atualiza o sistema em lote e queremos executá-lo automaticamente em várias máquinas.


SCRIPT atualiza-remoto-distros.sh

#!/bin/bash

# ============================================
# Script de atualização do sistema
# Compatível com Debian | Fedora | RHEL | Arch
# e derivados
# ============================================

# Este script é projetado para ser executado remotamente através do
# script principal executa-geral-senha.sh ou executa-geral-chave.sh (via SSH + sudo).

set -e

echo ">>> Iniciando atualização do sistema..."

# Detecta o gerenciador de pacotes
if command -v apt-get >/dev/null 2>&1; then
    # Verde negrito: \033[1;32m
    echo -e "\033[1;32m>>> Sistema baseado em Debian/Ubuntu detectado!\033[0m"
    export DEBIAN_FRONTEND=noninteractive
    apt-get update
    apt-get upgrade -y
    apt-get autoremove -y

elif command -v dnf >/dev/null 2>&1; then
    echo -e "\033[1;32m>>> Sistema baseado em Fedora/RHEL detectado!\033[0m"
    dnf upgrade -y
    dnf autoremove -y

elif command -v pacman >/dev/null 2>&1; then
    echo -e "\033[1;32m>>> Sistema baseado em Arch Linux detectado!\033[0m"
    pacman -Syu --noconfirm

else
    # Vermelho negrito: \033[1;31m
    echo -e "\033[1;31mGerenciador de pacotes não suportado!\033[0m"
    exit 1
fi

echo ">>> Atualização do sistema concluída com SUCESSO!"

Salve e saia.
Dê permissão de execução.


Basta colocar no script executa-geral-senha.sh ou executa-geral-chave.sh o caminho para o script desejado em:

# Caminho do script local a ser executado remotamente (modifique aqui)
SCRIPT_PATH="$HOME/caminho_diretorio/scripts/atualiza-remoto-distros.sh"

E executar um dos dois scripts chamadores.

A lógica é bem simples: coloque nos scripts executa-geral-senha.sh ou executa-geral-chave.sh o caminho e o nome do script que você quer executar remotamente.


4 - Bônus

SCRIPT copia-chave-distros.sh

#!/bin/bash

# ============================================
# Configura SSH e sudo NOPASSWD
# Compatível com Debian | Fedora | RHEL | Arch
# e derivados
# ============================================

# Antes de executar esse script, você deverá ter gerado a chave no servidor
# Exemplo:
# $ ssh-keygen -t ed25519

CHAVE_PUB="$HOME/.ssh/id_ed25519.pub"
# Configure com seu usuario e senha
USER_REMOTO="usuario"
SENHA="senha"  # senha sudo do usuário remoto

if [ ! -f "$CHAVE_PUB" ]; then
    echo "Chave pública ED25519 não encontrada em $CHAVE_PUB"
    exit 1
fi

echo ">>> Processando nós..."

# Altere para tua faixa de IPs
for i in {4..8}; do
    NODE="192.168.1.$i"
    echo -n "Verificando conectividade com $NODE... "

    if ping -c 1 -W 1 "$NODE" &> /dev/null; then
        echo "OK"
        echo "Copiando chave para $NODE"
        ssh-copy-id -i "$CHAVE_PUB" "$USER_REMOTO@$NODE"
    else
        echo -e "\033[1;31mFalhou conectividade com $NODE!\033[0m"
        continue
    fi

    echo ">>> Configurando sudo NOPASSWD e !requiretty em $NODE..."

    # Cria arquivo sudoers remoto com senha via sudo -S
    ssh "$USER_REMOTO@$NODE" "
        echo '$SENHA' | sudo -S bash -c '
            cat > /etc/sudoers.d/$USER_REMOTO <>> Nó $NODE configurado com sucesso!\033[0m"
    echo
done
# Verde negrito: \033[1;32m
echo -e "\033[1;32m>>> Todos os nós processados com sucesso!\033[0m"
echo

Salve e saia.
Dê permissão de execução.

Lembre que o script copia-chave-distros.sh deve ser executado diretamente no terminal (./copia-chave-distros.sh), pois se chamarmos ele por um dos outros scripts dará erro devido às senhas de sudo, caminhos de arquivos no servidor, etc. Um script remoto nunca pode copiar a chave do servidor por questões de segurança, então o servidor SEMPRE precisa enviar a chave, pois quem deve fazer a conexão SSH é o script chamador.

Caso os dois scripts, o chamado e o chamador, façam conexões SSH dará erro e/ou pedirá senha em cima de senha; isso não é incontornável no Linux, mas para o que se pretende não vale a pena o trabalho.

Nenhum comentário:

Postar um comentário