Odkazy:
Program je běžnou součástí Linuxových distribucí, například v Debianu je v balíčku util-linux. Jeho předností, oproti jiným způsobům analýzy příkazové řádky je snadná specifikace nejn krátkých přepínačů jako -a
ale i dlouhých přepínčů jako například --help
. Proto jej mám velmi v oblibě a používám velmi často.
Po nějaké době používání, a vylepšování jsem přišel s následujícím použitím.
#!/bin/bash # -*- coding:utf-8; -*- # $Id: ......$ # Jednořádkový popis programu/skriptu. # Copyright (c) 2009 Já První Největší # Specifikace práv jako: Všechna práva vyhrazena. Nebo dělejte si každý co chcete. declare -r COPYRIGHT="(c) 2009 Já První Největší declare -r PROGRAM_NAME=${0##*/} declare -r PROGRAM_VERSION="2.3" declare -r PROGRAM_REVISION=$(echo '$Revision: 1.52 $' | awk '{print $2}') declare -r DESCRIPTION=" Víceřádkový popis programu a jeho použití. Toto je taková malá dokumentace. Nepleťte si prosím s popisem argumentů příkazové řádky. Tento a podobné informace jsou poskytovány funkcí echo_usage. " # Základní kontrola jestli spouštíme program na správném počítači/serveru. # to ve většině případů opravdu nepotřebujete. Ale někdy se to velmi hodí. # Nahrání knihoven a základní nastavení prostředí. Například: source /usr/local/sad/lib/environment source /usr/local/sad/bin/load-vars declare -ir TRUE=0 FALSE=1 # Boolean variables PATH=/usr/local/sad/bin:$PATH echo_version() { echo "$PROGRAM_NAME $PROGRAM_VERSION rev $PROGRAM_REVISION $COPYRIGHT" } echo_usage() { echo_version echo "usage: $PROGRAM_NAME [-dvh] ..." echo -e " -d,--debug\tdisplay debug messages, increase debuging level" echo -e " -v,--verbose\tbe more verbose, increase verbosity level" echo -e " -h,--help\tdisplay this little usage help" ... } echo_description() { echo "$DESCRIPTION"|grep -v "^ *$" } # Argument parser declare rest_args= declare -i option_verbose=$FALSE verbosity_level=0 declare -i option_debug=$FALSE debug_level=0 declare -i option_.... function parse_arguments() { local option local -i fatal=$FALSE eval set -- "$arguments" while true; do option=$1; shift case "$option" in -d|--debug) option_debug=$TRUE; ((debug_level++));; -v|--verbose) option_verbose=$TRUE; ((verbosity_level++));; ... -V|--version) echo_version; exit 0;; -D|--description) echo_description; exit 0;; -h|--help) echo_usage; exit 0;; --) rest_args="$@"; break;; # Stop parsing on '--' mark. *) echo "$PROGRAM_NAME: Argument parsing error: ($option): $*" exit 1 ;; esac # Check if mandatory parameters were given ... if ((fatal)); then echo "$PROGRAM_NAME: There was an fatal error. Exitting!" exit 1 fi done } # parse_arguments() ### Startup code. ############################################## arguments=$(getopt -u -n $PROGRAM_NAME \ -o "dhqsvVD" \ -l "debug help silent verbose version description" \ -- "$@") parse_arguments if ((option_debug)); then echo_version set -x fi ######## M A I N ##########################################
Teď se podíváme jak to celé funguje. Na začátku programu jsou úvodní komentáře. Navykl jsem si na tento několikařádkový blok a dávám jej všude standardně. Ve zkratce nás informuje o tom že tento program je v bashi. To je první a jediný povinný řádek. Poté následuje řáde s informacemi o verzi a souboru ze systému správy zdorjového kódu jako je RCS/CVS/SVN/... Navykl jsem si vždy nějaký systém použít. Alespoň RCS pokud nepouiji jiný.
Pořád se učím nové věci, ještě nedávno jsem předával argumenty do funkce parse_arguments
jiným způsobem. A ten fungoval dlouho. Pak se ale vyskytl speciální případ a já zjistil že to tak nejde. Na třetím řádku je jednořádkový popis programu. Je to velmi dobré pro rychlou orientaci. Název programu, ačkoliv by měl být dostatečně popisný, takový v řadě případů nemusí být. Poté následují řádky o Copyrightu a za nimi krátká informace o licenci.
Další částí v programu je blok konstant obsahující informace o samotném programu. Tento blok rovněž používám ve všech programech psaných v bashi. Tyto konstanty, velmi popisné, jsou pak v následujících funkcích použity. Definuji zde konstantu COPYRIGHT
s informacemi o držiteli kopyrajtu. Dále PROGRAM_NAME
jenž obsahuje jméno programu. To získám z parametru $0
. Informaci o verzi programu PROGRAM_VERSION
, udržovanou ručně. Poslední je informace o revizi PROGRAM_REVISION
získanou z systému správy verzí pokud to umí. Určitě to umí RCS a CVS.
Poté definuji konstantu DESCRIPTION
která obsahuje víceřádkový popis programu. Zastávám názor že dokumentace programu umístněná přímo do programu je velmi dobrá věc. Vždy ji máte po ruce a nemusíte ji hledat. A vždy ji píšu. Zde je účel programu to k čemu je určen a souvislosti s ostatními programy a vztahy k dalším částem projektu jehož je program součástí.
Pak dávám do programu základní kontrolu. Některé programy, jako součásti větších projektů jsou určeny jen k běhu na určených serverech. Spouštění na jiných strojích nemá smysl, nebo může být i nebezpečené. Zejména pokud program běží s právy roota. Například v projektu určeném k běhu na desítkách až stovkách počítačů kdy většina je „satelitních“ a pak jsou servery „distribuční“ a servery „centrální“ některé programy smí být spouštěny jen na určitém typu serveru. Tato kontrola podle různých znaků, jako je přítomnost konfigurace satelitního serveru, nebo přítomnost konfigurace distribučního serveru, pokud zjistí že je spuštěna na nesprávném serveru vypíše krátkou informaci a ukončí program.
Poté následuje blok příkazů pro vytvoření základního prostředí. Zde nahrávám příkazem source knihovny funkcí a proměnné specifické pro projekt. Program například vůbec neví, kde se nachází adresář s proměnnými. Pokud nějakou chce použít prostě použíje konstantu $VARIABLES
již správně defunije nějaká knihova ze zde právě nahraných. V této části rovněž defunuji logické konstanty TRUE a FALSE. A podle potřeby opravím či pozměním proměnnou PATH
.
Dále následují tři funkce. echo_version
, echo_usage
a echo_description
. První a poslední jsou všude stejné a využívají informací definovaných na začátku programu v konstantách popisujících program. Funkce echo_usage
zobrazuje informace o paramerech v příkazové řádce. Obsah této funkce je specifický pro každý program.
Nyní následuje definice proměnných po jednotlivé volby v příkazovém řádku a samotná funkce parse_arguments
která je naplní podle toho co v příkazovém řádku zadáme.
Podrobněji popsat parse_arguments()
Náslduje startovací kód programu. Zde zavoláme externí program pro analýzu příkazové řádky getopt s parametry popisujícími možné přepínače a informace o těchto přepínačích. To jsou písmenka za přepínačem -o
a slova dlouhých parametru za přepínačem -l
. Poté zavolám samotnou funkci parse_arguments
která podle informací v proměnné arguments
, získané voláním getopt, nastaví proměnné option_...
a další. V programu se dále používají jen tyto proměnné.
Posledním standardním kódem který používam je přepnutí do ladicího režimu v závislosti na hodnotě proměnné option_debug
získané z přepínače -d
nebo --debug
. Zde končí šablona a dále následuje samotný program.
Pokud se vám tato šablona zdá dlouhá, nemusíte ji používat. Je v ní jen má osobní zkušenost. Budete li programovat projekt s větším počtem skriptů, jenž jsou navzájem závislé a propojené, tato nebo nějaká jiná šablona vám bude velmi k užitku.
FIXME:Odstranit zbytek sekce.
function parse_arguments() { while true; do option=$1; shift case "$option" in -h|--help|-?) usage; exit 0;; -i|--interactive) INTERACTIVE=1;; -c|--count) COUNT=$1; shift;; … --) break;; *) echo "Argument parsing error: ($option): $*"; exit 1;; esac done # Argument checking … } ⋮ parse_arguments $(getopt -n "${0##*/}" -o "abc:hi" -l "help interactive count:" -- "$@")