#!/usr/bin/env bash http_version=0.5.1 # this script version. set -o monitor # for job control. set -o errexit # exit if error occurs. # Defaults HOST=0.0.0.0 PORT=8000 DIR=$PWD # Check Python 3 if ! hash python3 2>/dev/null; then echo -e "$0: Python 3 executable not found." >&2 exit 1 fi http_print_help() { cat <<-EOF Run Python 3 builtin HTTP Server. Usage: http [-v|--version] [-h|--help] [-c|--cgi] [-f|--firefox] [[:]] [] [] Options: -c, --cgi run as CGI Server. -f, --firefox open URL in Firefox. -h, --help print this help message and exit. -v, --version print version and exit. Arguments: host to bind. Default: 0.0.0.0 port to bind. Default: 8000 directory to serve. Default: current directory. EOF exit 0 } while (( "$#" )); do case "$1" in -c|--cgi) CGI='--cgi';; -f|--firefox) FOX=1;; -h|--help) http_print_help;; -v|--version) echo "http v$http_version"; exit 0;; -*|--*) echo -e "$0: Bad option: $1" >&2 exit 1 ;; *) if [ -d "$1" ] then # If direcory exists set it as root DIR. DIR="$1" elif [[ "$1" =~ ^[0-9]+$ ]] then # If value is integer set it as PORT. PORT="$1" elif [[ "$1" =~ \ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] then # Value like IPv4 address. Not necessary. HOST="$1" elif [[ "$1" == 'localhost' ]] then # Nuff said. HOST="$1" elif [ "$(grep -o : <<<"$1")" ] then # If value like 'localhost:4000' HOST="$(echo "$1" | cut -d ":" -f 1)" PORT="$(echo "$1" | cut -d ":" -f 2)" else echo -e "$0: Bad option: $1$" >&2 exit 1 fi ;; esac shift done # Check available port and retry 3 times. retries=1 while [ "$(ss -tanp | grep -o "$PORT")" ]; do if [[ "$retries" == 4 ]] then echo -e "Max number of retries reached! Exiting." >&2 exit 1 else : fi # Increase port if is already in use. PORT_USED="$PORT" let PORT++ echo -e "Port $PORT_USED is already in use! Switching to: $PORT" | sed 's/^ *//g' >&2 let retries++ done # Run Python http.server. echo -e "Serve: $DIR\tPress ^C to stop serving." python3 -m http.server $CGI --bind $HOST $PORT --directory $DIR & [[ "$FOX" == 1 ]] && firefox http://$HOST:$PORT/ fg