#!/usr/bin/env bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)check-port 3.3.1 16.03.2026 (c)2026 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Checks if port can be reached over the internet (ingres). #@ #@Usage: check-port [options] port #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -o, --output : Output format: can be "line", "keys", "json", "etsv", "tsv" or "table" (default). #@ Port: Can be a specific port or a port range e.g. '22-25,80,443' e.g. 80 (for http) # # Exit codes: # 01: Unknown or wrong parameter. # 02: **curl** not found. This script needs **curl** to perform. # 03: No internet connection. # 99: User interrupt. # # Update history: # # V 3.0.0 02.05.2020 New version # V 3.0.1 03.06.2020 Using transfer instead of curl # V 3.0.2 11.06.2020 Using library # V 3.0.3 21.05.2023 Using HTTPS instead of HTTP # V 3.1.0 05.06.2023 New copyright # V 3.2.0 11.09.2024 New minor version # V 3.2.1 13.10.2024 Don't use convert-json and jq # V 3.3.0 19.01.2026 Revised with support of Claude Code # V 3.3.1 16.03.2026 Optimized: replaced backticks with $(); [ ] with [[ ]]; # echo|grep with [[ == -* ]]; removed UUOC # # Find executable bash library and source it lib=$(command -v lib.bash 2>/dev/null) if [[ -n "$lib" ]]; then source "$lib" else progdir=$(dirname "$0") if [[ -r "${progdir}/lib.bash" ]]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Set the Base URL url="https://ifconfig.co/port" # Preset param="" maxchecks=25 # Maximal number of port checks formatstr="" # Print result in table format # Check parameters: Loop until all parameters are used up while [[ $# -gt 0 ]]; do pname="${1}" case "$1" in -o | --output) shift if [[ -n "$1" ]]; then if [[ -z "$formatstr" ]]; then formatstr=$(ToLower "$1") case "$formatstr" in etsv|tsv|line|keys|table|json) ;; *) errstr="Unknown format '$formatstr' after parameter '$pname'. Please choose from 'table', 'line', 'keys', 'etsv', 'tsv' or 'json'." ;; esac else errstr="Option '$pname' used more then once." fi shift else errstr="Please specify a format ('tsv', 'line', 'table' or 'json') after parameter '$pname'." fi ;; -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; *) shift if [[ "$pname" == -* ]]; then errstr="Unknown option '$pname'." else if [[ -z "$errstr" ]]; then if [[ -z "$param" ]]; then param=$(ToLower "$pname") else errstr="Port was already specified '$param'. Unknown additional parameter: '$pname'." fi fi fi ;; esac done # Plausibility checks if [[ -z "$errstr" && -z "$param" ]]; then errstr="No port number given." else if [[ -z "$formatstr" ]]; then formatstr="table" fi fi # Display help or error message DisplayHelp # Check if we have curl in path curl=$(filecheck -x curl) if [[ -z "$curl" ]]; then exitcode=2 errormsg $exitcode "($progstr) No 'curl' in '$PATH'. Please install first e.g. 'sudo yum -y install curl'." exit $exitcode else myip=$(get-ip ip) if [[ -z "$myip" ]]; then exitcode=3 errormsg $exitcode "($progstr) No connection to the Internet. Can't check ports." exit $exitcode else # Convert port range convert-number "$param" --max 65535 --padding 5 > "$scratchfile" # Read ports - avoid UUOC with direct redirect ports=$(head -n $maxchecks "$scratchfile" | tr '\n' ' ') printf "%s\t%s\t%s\n" "ip" "port" "reachable" > "${scratchfile}.out" for port in $ports; do result="" while [[ -z "$result" ]]; do # Get result from server transfer --quiet "${url}/${port}" --export "$scratchfile" stat=$? if [[ $stat -eq 0 ]]; then result=$(head -n 1 "$scratchfile") if [[ "$result" == "{"* ]]; then port=$(grep '"port":' "$scratchfile" | cut -d':' -f2 | tr -d '" ,') reachable=$(grep '"reachable":' "$scratchfile" | cut -d':' -f2 | tr -d '" ,') printf "%s\t%s\t%s\n" "$myip" "/$port/" "/$reachable/" >> "${scratchfile}.out" fi fi done done result=$(filecheck -sl "${scratchfile}.out") if [[ "$result" == "${scratchfile}.out" ]]; then if [[ "$formatstr" == "json" ]]; then print-table --import "${scratchfile}.out" --output "$formatstr" \ | sed 's|\("contentItems":.*\)|\1,\n "creator": "'"$progstr"'"|' else print-table --import "${scratchfile}.out" --output "$formatstr" fi fi fi fi # Cleanup and exit Cleanup exit $exitcode