From: vados-dev Date: Fri, 13 Mar 2026 05:40:02 +0000 (+0300) Subject: Autocommit in repo: , generated by owner: mikro_bak, in 08:40:02 13.03.2026. X-Git-Url: https://git.vados.ru/gitweb.cgi?a=commitdiff_plain;h=b23f16cd1e6e4d7fb2b335ae3ee32a23de2494c2;p=Mikrotiks%2FMikrotiks.git Autocommit in repo: , generated by owner: mikro_bak, in 08:40:02 13.03.2026. --- diff --git a/bin/ros-deploy.sh b/bin/ros-deploy.sh new file mode 100755 index 0000000..1b203c8 --- /dev/null +++ b/bin/ros-deploy.sh @@ -0,0 +1,328 @@ +#!/bin/bash +# +# ros-deploy.sh - Bulk RouterOS Script Deployment Tool +# Version: 1.2.1 (2025-06-26) +# +# A powerful and flexible tool for deploying RouterOS scripts to multiple +# MikroTik devices simultaneously via SSH. It supports both single-host +# deployment and batch deployment from a hosts file. +# +# Features: +# - Deploy scripts to a single host or a list of hosts from a file +# - Securely uploads and executes scripts using SCP and SSH +# - Supports user, host, and port specification ([user@]host[:port]) +# - Automatic cleanup of temporary script files on the remote device +# - Configurable connection timeout +# - Detailed summary of successful and failed deployments +# - Supports SSH key-based authentication for passwordless execution +# +# Usage: ./ros-deploy.sh [OPTIONS] (-h HOST | -H HOSTS_FILE) -s SCRIPT_FILE [-i IDENTITY_FILE] +# +# Author: Nikita Tarikin +# GitHub: https://github.com/tarikin/ros-deploy +# License: MIT +# +# Copyright (c) 2025 Nikita Tarikin +# +set -euo pipefail + +# Default values +DEFAULT_CONNECT_TIMEOUT=5 # Default connection timeout in seconds +NO_COLOR=false # Default color output enabled + +# Color codes (only used when output is a terminal and NO_COLOR is false) +if [ -t 1 ] && ! $NO_COLOR; then + COLOR_RESET='\033[0m' + COLOR_BOLD='\033[1m' + COLOR_RED='\033[1;31m' + COLOR_GREEN='\033[1;32m' + COLOR_YELLOW='\033[1;33m' + COLOR_BLUE='\033[1;34m' + COLOR_CYAN='\033[1;36m' +else + COLOR_RESET='' COLOR_BOLD='' COLOR_RED='' COLOR_GREEN='' COLOR_YELLOW='' COLOR_BLUE='' COLOR_CYAN='' +fi + +# Helper functions for colored output +info() { + echo -e "${COLOR_BLUE}ℹ $*${COLOR_RESET}" +} + +success() { + echo -e "${COLOR_GREEN}✅ $*${COLOR_RESET}" +} + +error() { + echo -e "${COLOR_RED}❌ Error: $*${COLOR_RESET}" >&2 +} + +warning() { + echo -e "${COLOR_YELLOW}⚠ $*${COLOR_RESET}" >&2 +} + +section() { + echo -e "\n${COLOR_CYAN}=== $* ===${COLOR_RESET}" +} + +# Help message - uses plain echo to avoid color codes in output +show_help() { + cat << 'EOF' +Deploy RouterOS scripts to one or more devices + +Usage: ros-deploy [OPTIONS] (-h HOST | -H HOSTS_FILE) -s SCRIPT_FILE + +Options: + --help Show this help message and exit + -h, --host HOST Single RouterOS device to deploy to (format: [user@]hostname[:port]) + -H, --hosts FILE File containing list of RouterOS devices (one per line, format: [user@]hostname[:port]) + -s, --script FILE RouterOS script file to execute + -t, --timeout SECONDS Connection timeout in seconds (default: 5) + -i, --identity FILE SSH private key file to use for authentication + --no-color Disable colored output + +Examples: + ros-deploy -H routers.txt -s config.rsc -t 10 + ros-deploy -h admin@router.local -s config.rsc --no-color +EOF + exit 0 +} + +# Parse command line arguments +HOSTS_FILE="" +SINGLE_HOST="" +SCRIPT_FILE="" +CONNECT_TIMEOUT="$DEFAULT_CONNECT_TIMEOUT" +IDENTITY_FILE="" +NO_COLOR=false + +while [[ $# -gt 0 ]]; do + case $1 in + --help) + show_help + ;; + --no-color) + NO_COLOR=true + # Re-initialize colors if needed + if $NO_COLOR; then + COLOR_RESET='' COLOR_BOLD='' COLOR_RED='' COLOR_GREEN='' COLOR_YELLOW='' COLOR_BLUE='' COLOR_CYAN='' + fi + shift + ;; + -h|--host) + if [ -z "$2" ] || [[ "$2" == -* ]]; then + echo "Error: Missing host argument for $1" >&2 + show_help + exit 1 + fi + SINGLE_HOST="$2" + shift 2 + ;; + -H|--hosts) + if [ -z "$2" ] || [[ "$2" == -* ]]; then + echo "Error: Missing hosts file argument for $1" >&2 + show_help + exit 1 + fi + HOSTS_FILE="$2" + shift 2 + ;; + -s|--script) + if [ -z "$2" ] || [[ "$2" == -* ]]; then + echo "Error: Missing script file argument for $1" >&2 + show_help + exit 1 + fi + SCRIPT_FILE="$2" + shift 2 + ;; + -t|--timeout) + if [ -z "$2" ] || [[ "$2" == -* ]]; then + echo "Error: Missing timeout value for $1" >&2 + show_help + exit 1 + fi + # Validate timeout is a positive number + if ! [[ "$2" =~ ^[0-9]+$ ]] || [ "$2" -eq 0 ]; then + echo "Error: Timeout must be a positive integer" >&2 + exit 1 + fi + CONNECT_TIMEOUT="$2" + shift 2 + ;; + -i|--identity-file) + if [ -z "$2" ] || [[ "$2" == -* ]]; then + echo "Error: Missing identity file argument for $1" >&2 + show_help + exit 1 + fi + IDENTITY_FILE="$2" + shift 2 + ;; + *) + echo "Error: Unknown option or missing argument: $1" >&2 + show_help + exit 1 + ;; + esac +done + +# Validate required parameters +if { [ -z "$HOSTS_FILE" ] && [ -z "$SINGLE_HOST" ]; } || [ -z "$SCRIPT_FILE" ]; then + echo "Error: You must specify either --host or --hosts, and --script" >&2 + show_help + exit 1 +fi + +TEMP_SCRIPT_NAME="$(basename "$SCRIPT_FILE")" + +# Check if files exist +if [ -n "$HOSTS_FILE" ] && [ ! -f "$HOSTS_FILE" ]; then + error "Hosts file '$HOSTS_FILE' not found" + echo "Please create a file with a list of routers, one per line, in format: [user@]hostname[:port]" >&2 + exit 1 +fi + +if [ -n "$IDENTITY_FILE" ] && [ ! -f "$IDENTITY_FILE" ]; then + error "Identity file '$IDENTITY_FILE' not found" + exit 1 +fi + +if [ ! -f "$SCRIPT_FILE" ]; then + error "RouterOS script file '$SCRIPT_FILE' not found" + echo "Please specify a valid RouterOS script file to execute" >&2 + exit 1 +fi + +# Function to execute RouterOS script +execute_routeros_script() { + local host="$1" + local user="admin" # default user + local port="22" # default SSH/SCP port (RouterOS uses the same port for both) + local target + + # Extract user if specified + if [[ "$host" == *"@"* ]]; then + user="${host%%@*}" + host="${host#*@}" + fi + + # Extract port if specified + # Extract port if specified (format: hostname:port or user@hostname:port) + if [[ "$host" == *":"* ]]; then + port="${host##*:}" + host="${host%:*}" + fi + + target="$user@$host" + + section "[$(date +'%Y-%m-%d %H:%M:%S')] Processing $target (port $port)" + + # Build base SSH/SCP options + local ssh_opts=("-o BatchMode=yes" "-o ConnectTimeout=$CONNECT_TIMEOUT" "-o StrictHostKeyChecking=accept-new") + if [ -n "$IDENTITY_FILE" ]; then + ssh_opts+=("-i $IDENTITY_FILE") + fi + + # 1. First, copy the script to the router using SCP + info "Uploading script to router..." + # shellcheck disable=SC2086 + if scp ${ssh_opts[*]} -P "$port" "$SCRIPT_FILE" "$target:$TEMP_SCRIPT_NAME"; then + + info "Script uploaded successfully, executing..." + + # 2. Only execute SSH if SCP was successful + # shellcheck disable=SC2086 + if ssh ${ssh_opts[*]} -p "$port" "$target" "/import verbose=no $TEMP_SCRIPT_NAME; /file/remove $TEMP_SCRIPT_NAME"; then + success "Successfully executed script on $target" + return 0 + else + error "Failed to execute script on $target" + return 1 + fi + else + error "Failed to upload script to $target" + return 1 + fi +} + +# Initialize tracking variables +FAILED_HOSTS=() +TOTAL=0 +SUCCESS=0 + +# Process hosts +section "Starting RouterOS deployment" +if [ -n "$SINGLE_HOST" ]; then + info "Single host: $SINGLE_HOST" +fi +if [ -n "$HOSTS_FILE" ]; then + info "Hosts file: $HOSTS_FILE" +fi +info "Script file: $SCRIPT_FILE" +info "Connect timeout: $CONNECT_TIMEOUT seconds" +info "SSH Key: $(ssh-add -l 2>/dev/null || echo "No SSH key loaded in agent")" +echo -e "${COLOR_YELLOW}----------------------------------------${COLOR_RESET}" + +# Process single host if specified +if [ -n "$SINGLE_HOST" ]; then + ((TOTAL++)) + if execute_routeros_script "$SINGLE_HOST"; then + ((SUCCESS++)) + else + FAILED_HOSTS+=("$SINGLE_HOST") + fi +fi + +# Process hosts file if specified +if [ -n "$HOSTS_FILE" ]; then + # Read hosts file into an array, skipping comments and empty lines + HOSTS=() + while IFS= read -r line; do + # Remove comments and trim whitespace + line="${line%%#*}" # Remove comments + line="${line##*([[:space:]])}" # Remove leading whitespace + line="${line%%*([[:space:]])}" # Remove trailing whitespace + + # Skip empty lines + [ -n "$line" ] && HOSTS+=("$line") + done < "$HOSTS_FILE" + + if [ ${#HOSTS[@]} -eq 0 ]; then + error "${COLOR_RED}No valid hosts found in $HOSTS_FILE${COLOR_RESET}" + exit 1 + fi + + success "${COLOR_GREEN}Found ${#HOSTS[@]} host(s) in file${COLOR_RESET}" + + # Process each host from the file + for host in "${HOSTS[@]}"; do + ((TOTAL++)) + if execute_routeros_script "$host"; then + ((SUCCESS++)) + else + FAILED_HOSTS+=("$host") + fi + done +fi + +# Print summary +section "Deployment Summary" +info "Total hosts: $TOTAL" +if [ $SUCCESS -gt 0 ]; then + success "Successful: $SUCCESS" +else + info "Successful: $SUCCESS" +fi + +if [ ${#FAILED_HOSTS[@]} -gt 0 ]; then + error "Failed: ${#FAILED_HOSTS[@]}" + echo -e "\n${COLOR_RED}Failed hosts:${COLOR_RESET}" + printf ' - %s\n' "${FAILED_HOSTS[@]}" + exit 1 +else + success "Failed: ${#FAILED_HOSTS[@]}" +fi + +echo +success "All deployments completed successfully!" +exit 0 diff --git a/bin/ros-diff.sh b/bin/ros-diff.sh index f7075f9..8d183ec 100755 --- a/bin/ros-diff.sh +++ b/bin/ros-diff.sh @@ -92,22 +92,22 @@ if [ -t 1 ] && $DEBUG_OUT; then green=$(tput setaf 2) bg_green=$(tput setab 2) yellow=$(tput setaf 3) - blue=$(tput setaf 4) + blue='\033[1;34m' #$(tput setaf 4) magenta=$(tput setaf 5) cyan=$(tput setaf 6) white=$(tput setaf 7) toend=$(tput hpa $(tput cols))$(tput cub 6) else - reset='' bold='' red='' green='' yellow='' blue='' magenta='' cyan='' white='' toend='' + reset='' bold='' red='' green='' bg_green='' yellow='' blue='' magenta='' cyan='' white='' toend='' fi help() { - echo -e "\n${white}❓ $*${reset}" + echo -e "\n${white}❓ $*${reset}" } info() { - echo -e "\n${cyan}🌀 $*${reset}" + echo -e "\n${blue}i $*${reset}" } success() { - echo -e "\n${green}✅ $*${reset}" + echo -e "\n${green}✅ $*${reset}" } error() { echo -e "\n${red}❌ $*${reset}" >&2 @@ -137,11 +137,6 @@ spinstr() # echo -ne "\\r[✅]\\n" tput cnorm -- } -# Source - https://stackoverflow.com/a/34392382 -# Posted by fipsbox, modified by community. See post 'Timeline' for change history -# Retrieved 2026-03-12, License - CC BY-SA 4.0 - - #sleep 10 & #spinstr $! #exit 0