#!/bin/bash # -*- coding:utf-8 -*- # file KLEIDER/web/src/favourites/evallogs # 2017-06-08 Herbert Schiemann # 2017-09-14 --titles: Sprachen-Datei bei Bedarf erzeugen # 2018-01-01 --undo: Letzte Auswertung rückgängig machen # 2020-04-16 symlinks relativ: ln -s -r, ptniix, pooldir # 2020-04-17 --upload: quit zum Ende # 2020-05-11 xhtml_setlang.xslt entfernt # Zähler, Variable, Aktionen declare_vars () { # Zähler g_counters=" \ verbose \ overwrite "; # Variable g_variables=" \ datadir \ newlogdir \ evlogdir \ docroot \ favdir \ srcbase \ srcdir \ pooldir \ trlang \ srclang \ ptnstory \ ptniix \ ptnlang "; # Aktionen g_actions=" \ undo \ eval \ reduce \ xslt \ xhtml \ langs \ titles \ upload "; } # declare_vars # setzt Vorgabe-Werte set_defaults () { local b=$(realpath $0); b=${b%/web/src/favourites/evallogs}; [[ -n "$verbose" ]] || verbose=1 ; [[ -n "$overwrite" ]] || overwrite=1 ; [[ -n "$datadir" ]] || datadir=$b/web/visits ; [[ -n "$newlogdir" ]] || newlogdir=$datadir/newlogs ; [[ -n "$evlogdir" ]] || evlogdir=$datadir/evallogs ; [[ -n "$docroot" ]] || docroot=$b/web/docroot ; [[ -n "$favdir" ]] || favdir=$docroot/f ; [[ -n "$srcbase" ]] || srcbase=$b/web/src ; [[ -n "$srcdir" ]] || srcdir=$srcbase/favourites ; [[ -n "$pooldir" ]] || pooldir=$b/pool ; [[ -n "$trlang" ]] || set_default_trlang ; [[ -n "$srclang" ]] || srclang=de ; [[ -n "$ptnstory" ]] || ptnstory="$docroot/s\${storyid}/story.xml.\${lang}." [[ -n "$ptnlang" ]] || ptnlang="$datadir/langs/langs.xhtml.\${lang}" [[ -n "$ptniix" ]] || ptniix="$b/web/imgix/imgix_\${storyid}.xml" [[ -n "$no_undo" ]] || no_undo=1; [[ -n "$no_langs" ]] || no_langs=1; [[ -n "$no_xslt" ]] || no_xslt=1; [[ -n "$no_xhtml" ]] || no_xhtml=1; } # set_defaults # setzt die Default-Sprachen set_default_trlang () { trlng="" ; local f; local l; for f in $docroot/local/local.xml.*.; do l=${f#$docroot/local/local.xml.}; l=${l%%.*}; trlang="$trlang $l"; done; } # set_default_trlang # Zeigt eine kurze Hilfe an show_help () { local cmd=${0#*/} ; set_defaults ; cat << .HELP ; $cmd --version $cmd --help $cmd ([Aktion] | [Option])* Aktionen --undo letzte Auswertung rückgängig machen --eval wertet Log-Dateien aus --reduce Besuchsdaten für den Webserver bereitstellen --xslt XSLT-Dateien für den Webserver --xhtml XHTML-Vorlagen für den Webserver --langs Sprachbezeichnungen --titles Titel-Dateien --upload Dateien hochladen Optionen --[no_]verbose Erhöht den Umfang der Ausgabe des Scripts ($verbose) --[no_]overwrite Existierende Dateien überschreiben ($overwrite) --datadir DATADIR Datenverzeichnis ($datadir) --newlogdir NEWLOGDIR Verzeichnis der neuen Log-Dateien ($newlogdir) --evlogdir EVLOGDIR Verzeichnis der ausgewerteten Log-Dateien --docroot DOCROOT Document Root des lokalen HTTP-Servers ($docroot) --favdir FAVDIR Web-Unterverzeichnis für die Auswertung --srcdir SRCDIR Skript-Verzeichnis ($srcdir) --pooldir POOLDIR Verzeichnis gemeinsam genutzter XSLT-Dateien ($pooldir) --trlang TRLANG Komma-getrennte Liste der Sprachen ($trlang) --srclang SRCLANG Quell-Sprache ($srclang) --ptnstory PTNSTORY Dateipfad einer Bildergeschichte mit Platzhaltern ($ptnstory) --ptniix PTNIIX Dateipfad einer Bildbewertungsdatei mit Platzhaltern ($ptniix) --ptnlang PTNLANG Dateipfad einer Sprachendatein mit Platzhaltern ($ptnlang) .HELP } # show_help # Zeigt die Version an show_version () { cat << .VERSION ; KLEIDER/web/src/favourites/evallogs Logdateien auswerten 2017-06-08 Herbert Schiemann GPL Version 2 oder neuer .VERSION } # show_version # Variable und Zähler initialisieren init_vars () { local v; declare_vars ; for v in $g_counters $g_variables $g_actions; do eval "$v=" ; done; } # init_vars # Argumente verarbeiten read_args () { local wd ; local lastwd ; local var ; local ok ; has_actions=0 ; for wd in "$@"; do if [[ "$lastwd" = "--" ]]; then _argv="$_argv $wd"; elif [[ -n "$lastwd" ]]; then if [[ "$wd" =~ ^[\ a-zA-Z0-9./_#-]+$ ]]; then if [[ "$lastwd" == "rc" && -n "" ]]; then exit 10 ; else ok=0 ; for var in $g_variables; do if [[ "$var" == "$lastwd" ]]; then (( ++ok )) ; eval "$var=\"$wd\"" ; break ; fi ; done ; if (( ! ok )); then (( verbose )) && echo "Unbekannte Option --$lastwd $wd" ; exit 11 ; fi ; fi ; else (( verbose )) && echo "Ungültiger Optionswert --$lastwd $wd" ; exit 12; fi; lastwd= ; else case "$wd" in --version ) show_version ; exit 0 ; ;; --help ) show_version ; show_help ; exit 0 ; ;; -- ) if [[ -n "$_argv" ]]; then lastwd=--; continue; else (( verbose )) && echo "Ungültige Option $wd" ; exit 13 ; fi ; ;; --* ) if [[ "$wd" =~ ^--[a-z][a-z0-9_]*$ ]]; then lastwd=${wd#--} ; ok=0 ; for var in $g_counters ; do if [[ "$lastwd" == $var ]]; then eval "(( ++$lastwd ))" ; elif [[ "$lastwd" == "no_$var" ]]; then eval "${lastwd#no_}=0" ; else continue; fi; (( ++ok )) ; break ; done; if (( !ok )); then for var in $g_actions; do if [[ "$lastwd" == "$var" ]]; then eval "(( ++$var ))" ; (( ++ok )); has_actions=1; break; elif [[ "$lastwd" == "no_$var" ]]; then eval "(( ++no_$var ))" ; (( ++ok )); break; fi; done; fi; (( ok )) && lastwd=; else (( verbose )) && echo "Ungültige Option $wd" ; exit 14 ; fi ; ;; * ) if [[ -n $_argv ]]; then _argv="$_argv $wd"; else (( verbose )) && echo "Ungültige Option $wd" ; exit 15 ; fi; ;; esac ; fi ; done ; if [[ -n $lastwd && "$lastwd" != "--" ]]; then (( verbose )) && echo "Unverarbeitete Option --$lastwd"; exit 16 ; fi ; [[ "$_argv" =~ ^[[:space:]]+$ ]] && _argv="" ; } # read_args # Aktionen ausführen run_actions () { local act ; for act in $g_actions; do eval "(( ! has_actions && ! no_$act || $act )) && process_$act"; done; } # run_actions # show_variables VARNAME1 VARNAME2 # Werte der Variablen anzeigen show_variables () { local v ; for v in $g_counters $g_variables $g_actions $1; do eval "echo \"$v = \$$v\"" ; done; } # show_variables # Können die Eingabedateien gelesen werden? # check_infiles first/path/to/file path/to/second_file ; check_infiles () { local f ; for f in "$@"; do if [[ ! -f "$f" ]]; then (( verbose )) && echo "\"$f\" ist keine gewöhnliche Datei"; return 1; fi; if [[ ! -s "$f" ]]; then (( verbose )) && echo "\"$f\" ist leer"; return 1; fi; if [[ ! -r "$f" ]]; then (( verbose )) && echo "Kann Datei \"$f\" nicht lesen"; return 1; fi; done; return 0; } # check_infiles # Können die Ausgabedateien erstellt werden? # erstellt fehlende Verzeichnisse und löscht existierende Dateien # nach Maßgabe der Variablen overwrite # check_outfiles first/path/to/file path/to/second_file ; check_outfiles () { local fp; local dir; local verb; (( verbose )) && verb=--verbose ; for fp in "$@"; do if [[ ! -e $fp ]]; then dir=${fp%/*}; if [[ -n $dir && ! -e $dir ]]; then mkdir -p $verb $dir ; if [[ ! -d $dir ]]; then (( verbose )) && echo "$dir ist kein Verzeichnis"; return 1; fi; fi; elif [[ -d $fp ]]; then (( verbose )) && echo "$fp ist ein Verzeichnis"; return 1; elif (( overwrite )); then (( verbose )) && echo "lösche $fp"; rm $fp; else (( verbose )) && echo "$fp existiert"; return 1; fi; (( verbose )) && echo "$fp"; done; return 0; } # check_outfiles # Sind die Dateien ausführbar? # check_executeable first/path/to/script path/to/second_srcipt ; check_executeable () { local f ; for f in "$@"; do if [[ ! -f "$f" ]]; then (( verbose )) && echo "$f\" ist keine gewöhnliche Datei"; return 1; fi; if [[ ! -x "$f" ]]; then (( verbose )) && echo "$f\" ist keine ausführbare Datei"; return 1; fi; done; return 0; } # check_executeable # letzte Auswertung rückgängig machen process_undo () { (( verbose )) && echo "process_undo" ; local verb=; (( verbose )) && verb=--verbose; check_infiles $srcdir/visits_logs.xslt || return; if ! [[ -L $datadir/visits.xml ]]; then (( verbose )) && echo "$datadir/visits.xml ist kein Symlink"; exit 101; fi; local v=$(realpath $datadir/visits.xml); # letztes visits-File local ts=${v#$datadir/visits.xml.}; # letzter Zeitstempel (( verbose )) && echo "letzter Zeitstempel $ts"; local d=$datadir/detailed.xml.$ts # letztes detailed-File local e=$datadir/finished.xml.$ts # letztes finished-File check_infiles $d $e || return; local fs=$(xsltproc $srcdir/visits_logs.xslt $d); local f; for f in $fs; do check_infiles $evlogdir/$f || return; done; local ots; # alter Zeitstempel local ov=; # vorige visits-Datei for f in $datadir/visits.xml.*; do [[ "$f" == "$v" ]] && continue; [[ $f -nt $v ]] && continue; if [[ -z "$ov" ]]; then ov=$f; continue; fi; [[ $f -nt $ov ]] && ov=$f; done; local ots; [[ -n "$ov" ]] && ots=${ov#$datadir/visits.xml.}; echo "früherer Zeitstempel $ots"; check_infiles \ $datadir/visits.xml.$ots \ $datadir/finished.xml.$ots \ $datadir/detailed.xml.$ots \ || return; for f in $fs; do mv $verb $evlogdir/$f $newlogdir/$f; done; for f in visits open; do [[ -L $datadir/$f.xml ]] && rm $verb $datadir/$f.xml; [[ -f $datadir/$f.xml.$ts ]] && rm $verb $datadir/$f.xml.$ts ; [[ -f $datadir/$f.xml.$ots ]] && ln -s -r $datadir/$f.xml.$ots $datadir/$f.xml ; done; rm $verb $d ; rm $verb $e ; } # process_undo # Logdateien auswerten process_eval () { (( verbose )) && echo "process_eval" ; local ts=$(date +%Y%m%d%H%M%S%N) ; check_outfiles \ $datadir/open.xml.$ts \ $datadir/finished.xml.$ts \ $datadir/detailed.xml.$ts \ $datadir/visits.xml.$ts \ || return; check_executeable $srcdir/logs.pl $srcdir/sums.pl || return; check_infiles $srcdir/visits_logs.xslt $srcdir/visits_num.xslt || return ; $srcdir/logs.pl --timestamp $ts --srcdir $srcdir \ --datadir $datadir --newlogs $newlogdir ; local f; if [[ ! -f $datadir/finished.xml.$ts ]]; then [[ -f $datadir/detailed.xml.$ts ]] && rm $datadir/detailed.xml.$ts; (( verbose )) && echo "Keine neuen Besuche"; exit 0; fi; { xsltproc $srcdir/visits_num.xslt $datadir/finished.xml.$ts; [[ -r $datadir/visits.xml ]] \ && xsltproc $srcdir/visits_num.xslt $datadir/visits.xml; } | $srcdir/sums.pl > $datadir/visits.xml.$ts; [[ -f $datadir/visits.xml.$ts ]] || return; for f in $(xsltproc $srcdir/visits_logs.xslt $datadir/detailed.xml.$ts); do check_outfiles $evlogdir/$f || continue ; mv $newlogdir/$f $evlogdir/$f; done; for f in open visits; do [[ -L $datadir/$f.xml ]] && rm $datadir/$f.xml; [[ -f $datadir/$f.xml.$ts ]] || continue ; ln -s -r $datadir/$f.xml.$ts $datadir/$f.xml ; done; } # process_eval # gzip-komprimierte Datei(en) hinzufügen add_gzip () { local f; for f in "$@"; do [[ -f $f ]] || continue; [[ -f ${f}gz ]] && rm ${f}gz; [[ -e ${f}gz ]] && continue; (( verbose )) && echo "erstelle ${f}gz"; gzip --best --stdout $f > ${f}gz ; done ; } # add_gzip # Daten für die Website reduzieren process_reduce () { (( verbose )) && echo "process_reduce" ; local s=$datadir/visits.xml ; local t1=$srcdir/visits_reduce.xslt ; local t2=$srcdir/vis_add_details.xslt ; local t3=$pooldir/xml_minimize.xslt ; local o=$favdir/f.xml ; check_infiles $s $t1 $t2 $t3 || return; check_outfiles $o. || return; local p1=${ptnstory%\$\{lang\}*}; local p2=${ptnstory#*\$\{lang\}}; local p=${p1}de${p2}; xsltproc $t1 $s \ | xsltproc \ --stringparam p_ptn_storypath "$p" \ --stringparam p_ptn_iixpath "$ptniix" \ $t2 - \ | xsltproc $t3 - > $o. ; add_gzip $o. ; } # process_reduce # XSLT-Dateien für den Webserver process_xslt () { (( verbose )) && echo "process_xslt" ; local f; local s; local d; local t=/pool/xslt_minimize.xslt; check_infiles $t || continue; for f in v; do s=$srcdir/$f.xslt; d=$favdir/$f.xslt; check_infiles $s || continue; check_outfiles $d. || continue; xsltproc $t $s > $d. ; add_gzip $d. ; done; } # process_xslt # XHTML-Vorlagen für den Webserver process_xhtml () { (( verbose )) && echo "process_xhtml" ; local s; local d; local t=/pool/xhtml_minimize.xslt ; check_infiles $t || return ; for s in $srcdir/*.xhtml.de; do d=$favdir/${s#$srcdir/}.; check_outfiles $d; xsltproc $t $s > $d ; add_gzip $d; done; } # process_xhtml # erstellt die Dateien langs.xhml.$lang process_langs () { (( verbose )) && echo "process_langs" ; local s=$srcbase/kalender/langcodes.dbd ; local t=$srcdir/langcodes_xhtml.xslt ; check_outfiles \ $datadir/langs/langs.xhtml.de \ $docroot/langcodes.xhtml.de \ || return ; check_infiles $s $t || return ; xsltproc $t $s > $docroot/langcodes.xhtml.de. ; check_infiles $docroot/langcodes.xhtml.de. || return ; $srcbase/localization/localize --no_upload --no_zipfiles langcodes.xhtml ; for s in $docroot/langcodes.xhtml.*. ; do t=${s#$docroot/langcodes.} ; t=$datadir/langs/langs.${t%.} ; mv $s $t; done; } # process_langs # erstellt die Dateien t.xml.$lang process_titles () { (( verbose )) && echo "process_titles" ; local l ; # Sprache local o ; # Ausgabedatei local f=$favdir/f.xml. ; local t=$srcdir/vis_titles.xslt ; local s ; # Sprachen-Datei check_infiles $f $t || return ; for l in $trlang; do o=$favdir/t.xml.$l. ; check_outfiles $o || continue ; s=$datadir/langs/langs.xhtml.$l ; check_infiles $s || process_langs ; check_infiles $s || continue ; xsltproc \ --stringparam p_lang $l \ --stringparam p_srclang $srclang \ --stringparam p_ptn_storypath "$ptnstory" \ --stringparam p_ptn_langpath "$ptnlang" \ $t $f > $o ; add_gzip $o ; done; } # process_titles # Dateien hochladen process_upload () { (( verbose )) && echo "process_upload" ; local verb; (( verbose )) && verb=--verbose local f; # Kennung einer Bildergeschichte { for f in $favdir/f.xml.* $favdir/t.xml.*; do echo "putnewer ${f#$docroot/}"; done; echo "quit"; } | $srcbase/localization/ftp.pl $verb; } # process_upload # Sicherheit export PATH=/bin:/usr/bin ; IFS=$' \t\n' ; init_vars ; set -o noclobber ; # existierende Dateien werden nicht überschrieben shopt -s extglob nullglob ; read_args "$@" ; set_defaults ; (( verbose > 1 )) && show_variables ; run_actions ; exit 0; # end of file KLEIDER/web/src/favourites/evallogs