#!/usr/bin/env bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)get-platform 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. # #@ Get some infos about the platform (OS) and machine. #@ #@Usage: get-platform [options] [keys] #@ Options: #@ -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -o, --output : Output format: can be "plain" (default), "keys", "json", "etsv", "tsv", "line" or "table". #@ Keys: Optional - Select the keys you want to display. Use a colon (default) or tab or comma separated string for keys e.g.: #@ os: Displays the Operation System e.g. "Linux", "Darwin", "SunOS". #@ id: Displays the id e.g. "ol", "FreeBSD" #@ #@Examples: #@ pname=`get-platform pretty_name` #@ echo "$pname" # will display e.g. "Oracle Linux Server 7.4" # # Exit codes: # 01: Unknown or wrong parameter. # 02: Unsupported OS. # 03: Unknown key. # # Update history: # # V 3.0.0 24.04.2020 New version # V 3.0.1 11.06.2020 Using library # V 3.1.0 05.06.2023 New copyright # V 3.1.1 09.08.2024 Using print-table # V 3.2.0 11.08.2024 New minor version: New JSON output with 'content' # V 3.2.1 25.09.2024 Autonomous wasn't recognized # V 3.2.2 30.08.2025 OL10: uname -p returns "unknown" # 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 [[ == pattern ]] or [[ =~ ]]; replaced [ -a ] with && # # 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 # Do extra cleanup function ExtraCleanup() { filecheck -rm "${scratchfile}.out" } # Preset param="" formatstr="" # Check parameters: Loop until all parameters are used up while [[ $# -gt 0 ]]; do pname="${1}" case "$pname" in -o | --output) shift if [[ -n "$1" ]]; then if [[ -z "$formatstr" ]]; then formatstr=$(ToLower "$1") case "$formatstr" in plain|keys|json|etsv|tsv|line|table) ;; *) errstr="Unknown format '$formatstr' after parameter '$pname'. Please choose from 'plain', 'keys', 'json', 'etsv', 'tsv', 'line' or 'table'." ;; esac else errstr="Option '$pname' used more then once." fi shift else errstr="Please specify a format ('plain', 'keys', 'json', 'etsv', 'tsv', 'line' or 'table') 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 "$param" ]]; then param=$(ToLower "$pname") else errstr="Keys were already specified '$param'. Unknown additional parameter: '$pname'." fi fi ;; esac done # Check if we can reformat the output pt=$(filecheck -x print-table) # Display help or error message DisplayHelp # Set output to plain if not specified if [[ -z "$formatstr" ]]; then formatstr="plain" fi # https://en.wikipedia.org/wiki/Uname uname=$(filecheck -x uname) if [[ -n "$uname" ]]; then os=$($uname -s 2>/dev/null) # (system) e.g. Darwin, SunOS, Linux rel=$($uname -r 2>/dev/null) # (kernel release) mach=$($uname -m 2>/dev/null) # (machine) e.g. x86_64 vers=$($uname -v 2>/dev/null) # (kernel version) proc=$($uname -p 2>/dev/null) # (processor) e.g. i386 node=$($uname -n 2>/dev/null) # (nodename) osid=$($uname -o 2>/dev/null) # (operating system) e.g. GNU/Linux plat=$($uname -i 2>/dev/null) # (hardware platform) else os="" rel="" mach="" vers="" proc="" node="" osid="" plat="" fi # Network gateway="" iface="" lip="" lipv6="" lipdns="" # Check for ifconfig ifconfig=$(filecheck -x ifconfig) if [[ -n "$ifconfig" ]]; then if [[ "$os" == "Darwin" ]]; then iproute=$(filecheck -x route) result=$("$iproute" get 8.8.8.8 2>/dev/null) if [[ -n "$result" ]]; then gateway=$(printf '%s' "$result" | grep 'gateway:' | cut -d':' -f2 | sed 's|^ ||') iface=$(printf '%s' "$result" | grep 'interface:' | cut -d':' -f2 | sed 's|^ ||') fi else iproute=$(filecheck -x ip) result=$("$iproute" route show 2>/dev/null | grep '^default ' | head -n 1) if [[ -n "$result" ]]; then gateway=$(printf '%s' "$result" | cut -d' ' -f3) iface=$(printf '%s' "$result" | cut -d' ' -f5) fi fi "$ifconfig" "$iface" > "$scratchfile" 2>/dev/null lip=$(grep "inet " "$scratchfile" | head -n 1 | awk '{print $2}') lipv6=$(grep "inet6 " "$scratchfile" | head -n 1 | awk '{print $2}') up=$(grep "^${iface}: .* "$scratchfile" 2>/dev/null lipdns=$(grep "name = ${node}\." "$scratchfile" | cut -d'=' -f2 | sed 's|^ ||' | sed 's|\.$||') if [[ -z "$lipdns" ]]; then lipdns=$(grep "name = " "$scratchfile" | head -n 1 | cut -d'=' -f2 | sed 's|^ ||' | sed 's|\.$||') fi fi # Determine local hostname and ip hostname=$(filecheck -x hostname) if [[ -n "$hostname" ]]; then if [[ -z "$node" ]]; then node=$("$hostname" -s 2>/dev/null) fi if [[ -z "$lip" ]]; then lip=$("$hostname" -I 2>/dev/null | awk '{print $1}') fi if [[ -z "$lipdns" ]]; then lipdns=$("$hostname" -A 2>/dev/null | awk '{print $1}') fi fi # Get fqdn by dnsdomainname dnsdomainname=$(filecheck -x dnsdomainname) if [[ -z "$lipdns" && -n "$dnsdomainname" ]]; then lipdns=$("$dnsdomainname" 2>/dev/null) if [[ -n "$lipdns" ]]; then lipdns="${node}.${lipdns}" fi fi if [[ "$os" == "SunOS" ]]; then isainfo=$(filecheck -x isainfo) if [[ -n "$isainfo" ]]; then bits=$(isainfo -b) else getconf=$(filecheck -x getconf) if [[ -n "$getconf" ]]; then bits=$($getconf LONG_BIT 2>/dev/null) else bits="" fi fi else # More infos about processor: cat /proc/cpuinfo if [[ "$proc" == "unknown" ]]; then case "$mach" in x86_64 | x86_32) proc="i386" ;; aarch64 | aarch32) proc="arm" ;; esac else # Use bash pattern match instead of echo|grep subshell if [[ "$proc" == x86* ]]; then proc="i386" fi fi getconf=$(filecheck -x getconf) if [[ -n "$getconf" ]]; then bits=$($getconf LONG_BIT 2>/dev/null) else bits="" fi fi # Try to get OS Name case "$os" in Linux) if [[ -f /etc/os-release ]]; then name=$(grep "^NAME=" /etc/os-release | tr -d '"' | cut -d'=' -f2) version=$(grep "^VERSION_ID=" /etc/os-release | tr -d '"' | cut -d'=' -f2) mainvers="${version%%.*}" osstr=$(grep "^PRETTY_NAME=" /etc/os-release | tr -d '"' | cut -d'=' -f2) id=$(grep "^ID=" /etc/os-release | tr -d '"' | cut -d'=' -f2) idlike=$(grep "^ID_LIKE=" /etc/os-release | tr -d '"' | cut -d'=' -f2) cpename=$(grep "^CPE_NAME=" /etc/os-release | tr -d '"' | cut -d'=' -f2) else if [[ -f /etc/system-release ]]; then name=$(head -n 1 /etc/system-release | awk -F ' release ' '{print $NR}') version=$(head -n 1 /etc/system-release | awk -F ' release ' '{print $NF}' | cut -d' ' -f1) mainvers="${version%%.*}" else name="$os" version="$rel" fi fi # Try to determine codename if [[ "$id" == "ol" || "$id" == "centos" ]]; then idlike="fedora" if [[ -f /etc/system-release ]]; then grepres=$(head -n 1 /etc/system-release | grep "(") if [[ -n "$grepres" ]]; then codename=$(head -n 1 /etc/system-release | cut -d'(' -f2 | cut -d')' -f1) fi else codename="" fi elif [[ "$id" == "ubuntu" || "$id" == "debian" ]]; then idlike="debian" if [[ -f /etc/os-release ]]; then grepres=$(grep "^VERSION=" /etc/os-release | grep "(") if [[ -n "$grepres" ]]; then codename=$(grep "^VERSION=" /etc/os-release | cut -d'"' -f2 | cut -d'(' -f2 | cut -d')' -f1) fi fi elif [[ "$id" == "rhel" ]]; then idlike="fedora" if [[ -f /etc/redhat-release ]]; then grepres=$(head -n 1 /etc/redhat-release | grep "(") if [[ -n "$grepres" ]]; then codename=$(head -n 1 /etc/redhat-release | cut -d'"' -f2 | cut -d'(' -f2 | cut -d')' -f1) fi fi elif [[ "$id" == "opensuse" || "$id" == "sles" ]]; then idlike="suse" if [[ -f /etc/SuSE-release ]]; then grepres=$(head -n 1 /etc/SuSE-release | grep "(") if [[ -n "$grepres" ]]; then codename=$(head -n 1 /etc/SuSE-release | cut -d'"' -f2 | cut -d'(' -f2 | cut -d')' -f1) fi fi else codename="" fi # Convert aarch64 to arm if [[ "$proc" == "aarch64" ]]; then proc="arm" fi # Check if we are on autonomous linux if codename is not defined if [[ -z "$codename" && "$id" == "ol" ]]; then rpm=$(filecheck -x rpm) if [[ -n "$rpm" ]]; then $rpm -q alx-utils > /dev/null 2>&1 stat=$? if [[ $stat -eq 0 ]]; then codename="Oracle Autonomous Linux" else codename="Oracle Enterprise Linux" fi fi fi if [[ -n "$codename" ]]; then if [[ "$id" == "ubuntu" || "$id" == "sles" ]]; then osname="${osstr} (${codename})" else osname="${name} ${version} (${codename})" fi else osname="${name} ${version}" fi ;; SunOS) if [[ -f /etc/os-release ]]; then name=$(grep "^NAME=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2) version=$(grep "^VERSION_ID=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2) osstr=$(grep "^PRETTY_NAME=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2) id=$(grep "^ID=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2) idlike=$(grep "^ID_LIKE=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2) cpename=$(grep "^CPE_NAME=" /etc/os-release | cut -d'=' -f2 | cut -d'"' -f2) fi if [[ -f /etc/release ]]; then osstr=$(head -1 /etc/release | sed 's|^ *||') datestr=$(taillastline /etc/release | sed 's|^ *||') vers="${vers} ${datestr}" fi if [[ -z "$version" ]]; then name="Sun Solaris" mainvers="${rel#5.}" if [[ -z "$osstr" ]]; then version="$mainvers" else substr=$(printf '%s' "$osstr" | cut -d'_' -f2 | sed 's|^u||' | sed 's|wos$||') if [[ -z "$substr" ]]; then version="$mainvers" else version="${mainvers}.${substr}" fi fi else mainvers="${version%%.*}" fi [[ -z "$osid" ]] && name="Solaris" [[ -z "$name" ]] && name="Sun Solaris" [[ -z "$id" ]] && id="solaris" [[ -z "$idlike" ]] && idlike="posix" if [[ -n "$osstr" ]]; then osname="$osstr" else osname="${name} ${vers} ${proc}" fi ;; Darwin) if [[ -z "$osid" ]]; then osid="OSX"; fi if [[ -z "$plat" ]]; then plat=$(sysctl -n machdep.cpu.brand_string) fi sw_vers=$(filecheck -x sw_vers) if [[ -n "$sw_vers" ]]; then name=$($sw_vers -productName) id="FreeBSD" idlike="posix" version=$($sw_vers -productVersion) mainvers="${rel%%.*}" StringArray=("Titan" "Hera" "Unknown" "Kodiak" "Cheetah" "Puma" "Jaguar" "Panther" "Tiger" "Leopard" \ "Snow Leopard" "Lion" "Mountain Lion" "Mavericks" "Yosemite" "El Capitan" "Sierra" \ "High Sierra" "Mojave" "Catalina" "Big Sur" "Monterey" "Ventura" "Sonoma" "Sequoia") if (( mainvers < 0 || mainvers > 24 )); then codename=$(awk '/SOFTWARE LICENSE AGREEMENT FOR macOS/' \ '/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf' \ | awk -F 'macOS ' '{print $NF}') else codename="${StringArray[$mainvers]}" if (( mainvers > 15 )); then name="macOS" elif (( mainvers > 11 )); then name="OS X" fi fi if [[ -n "$codename" ]]; then osname="${name} ${version} (${codename})" else osname="${name} ${version}" fi else name="Mac OS X" osname="$vers" fi ;; *) exitcode=2 errormsg $exitcode "($progstr) Unsupported OS '$os'" exit $exitcode ;; esac # Don't display empty values in JSON (use // as sentinel) [[ -z "$codename" ]] && codename="//" [[ -z "$cpename" ]] && cpename="//" [[ -z "$gateway" ]] && gateway="//" [[ -z "$iface" ]] && iface="//" [[ -z "$lip" ]] && lip="//" [[ -z "$lipv6" ]] && lipv6="//" [[ -z "$lipdns" ]] && lipdns="//" # Create header with all parameter names and write as tsv printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \ "os" "os_id" "id" "id_like" "platform" "name" \ "codename" "cpe_name" "version_id" "version_main" "pretty_name" "machine" "processor" "bit" "release" "date" \ "gateway" "interface" "up" "ip_v4" "ip_v6" "fqdn" "nodename" > "$scratchfile" # Create body and append to tsv printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \ "$os" "$osid" "$id" "$idlike" "$plat" "$name" \ "$codename" "$cpename" "$version" "/${mainvers}/" "$osname" "$mach" "$proc" "/${bits}/" "$rel" "$vers" \ "$gateway" "$iface" "/$up/" "$lip" "$lipv6" "$lipdns" "$node" >> "$scratchfile" # Display everything if [[ -z "$pt" ]]; then # No print-table found - just display the tsv file cat "$scratchfile" else cat "$scratchfile" | $pt "$param" --output "$formatstr" --quiet > "${scratchfile}.out" stat=$? if [[ $stat -eq 3 ]]; then exitcode=3 errormsg $exitcode "($progstr) None of the specified keys '$param' were found." else if [[ "$ENVELOPE_TABLE" == false || "$formatstr" != "json" ]]; then cat "${scratchfile}.out" else cat "${scratchfile}.out" | sed 's|\("contentItems":.*\)|\1,\n "creator": "'"$progstr"'"|' fi fi fi # Cleanup and exit Cleanup exit $exitcode