#!/bin/sh argHelp() { echo "The project management script of OpenSCADA mostly designed to call from OpenSCADA itself, but it also can be used independently. The script is mostly software platform specific and this one is related for Linux. openscada-proj list openscada-proj proc|create|remove|snapshot|crash|cores|update {ProjName} Commands: list - list of the accessible projects; proc - performing of the RO project copying to WR, creating desktop link, processing core dumps; create - creating new project or copying the RO project to WR, creating desktop link; remove - removing the project; snapshot|crash|cores - creating the hot crash snapshot to the running project, where the 'crash' variant to call from OpenSCADA, the 'cores' variant to call from 'proc' for processing the core-files; update - updating from 0.8.0 LTS. Arguments: ProjName - project name; Environment variables: dPrj - directory of projects OpenSCADA, can be RO; dPrjUser - directory of projects OpenSCADA of the user, WR; dSysCfg - directory of system configuration; dData - directory of system data. openscada-proj backup|backupRestore {ProjName} [{BackupName}] openscada-proj backupList {ProjName} Commands: backup - backup the project under the name , or with the current date at missing; backupRestore - restore the project from the backup name , or from the last one at missing; backupList - list of backups of the project . Arguments: ProjName - project name; BackupName - name of the backup archive. Environment variables: OSCD_TAR_ComprPrg - TAR compression program, by default gzip; OSCD_TAR_Args - TAR extra arguments, by default \"--exclude=lock --exclude=ARCHIVES\"; OSCD_BackLim - Backups limit, by default 10. "; } gdbCall() { gdb $@ --batch --quiet \ -ex "echo \n==== (gdb) info thread ====\n" -ex "info thread" \ -ex "echo \n==== (gdb) thread apply all bt full ====\n" -ex "thread apply all bt full" \ -ex "echo \n==== (gdb) info sharedlibrary ====\n" -ex "info sharedlibrary" } crashHandler() { if test -z "$(which gdb 2> /dev/null)"; then echo "No GDB program present!"; return 0; fi prjNm=$1 dPrjRez=$dPrj/$prjNm if test -n "$dPrjUser" -a -d $dPrjUser/$prjNm; then dPrjRez=$dPrjUser/$prjNm; fi cd $dPrjRez if test "$2" = cores; then for fit in `ls core* 2> /dev/null`; do resultFile="${prjNm}_${fit}_$(date +%F_%H.%M).crash" echo "Processing the core dump files for backtrace obtaining in the file $resultFile" gdbCall @bindir_full@/openscada --core ${fit} > $resultFile gzip $resultFile rm -f ${fit} done return 0 fi if test "$2" != snapshot -a "$2" != crash; then echo "Unknown command $2 to the crash handler!" elif test ! -f $dPrjRez/lock; then echo "The project is not running since missing the file $dPrjRez/lock!" else pid=`cat $dPrjRez/lock | sed -r 's/^0*([0-9]+).*/\1/'` if ! ps -A -o "pid cmd" | grep "^ *$pid.*openscada" > /dev/null; then echo "No 'openscada' process at pid $pid!" else cd $dPrjRez if test "$2" = crash; then resultFile="${prjNm}_$(date +%F_%H.%M).crash" echo "Processing the crashing project for backtrace obtaining in the file $resultFile" rm $dPrjRez/lock else resultFile="${prjNm}_$2_$(date +%F_%H.%M).crash" echo "Processing the crash snapshot for backtrace obtaining in the file $resultFile" fi gdbCall -p $pid > $resultFile gzip $resultFile fi fi } if test $# -lt 1; then argHelp; exit 0; fi dPrjUser=${dPrjUser:=~/.openscada} dPrj=${dPrj:=@oscd_datadir_full@} dSysCfg=${dSysCfg:=@sysconfdir_full@} dData=${dData:=@datadir_full@} case "$1" in list) if test -d $dPrjUser; then echo "=== User projects ===" for fit in `ls $dPrjUser`; do if test -d $dPrjUser/$fit && test -f $dPrjUser/$fit/oscada.xml; then echo "$fit"; fi done echo "=== Common projects ===" fi for fit in `ls $dPrj`; do if test -d $dPrj/$fit && test -f $dSysCfg/oscada_$fit.xml -o -f $dPrj/$fit/oscada.xml; then echo "$fit"; fi done ;; proc|create) if test $# -lt 2; then echo "Not enough arguments!"; exit 1; fi prjNm=$2 dPrjRez=$dPrj/$prjNm # Processing the system projects' directory if test ! -d $dPrjRez -a -w $dPrj -a -f $dSysCfg/oscada_$prjNm.xml; then mkdir -p $dPrjRez; fi # Processing the user projects' directory if test ! -d $dPrjRez -o ! -w $dPrjRez && test -n "$dPrjUser"; then if test ! -d $dPrjUser; then mkdir -p $dPrjUser; fi if test ! -d $dPrjUser/LibsDB/; then mkdir -p $dPrjUser/LibsDB/ ln -s $dPrj/LibsDB/* $dPrjUser/LibsDB/ || cp $dPrj/LibsDB/* $dPrjUser/LibsDB/ fi dPrjRez=$dPrjUser/$prjNm if test ! -d $dPrjRez; then mkdir -p $dPrjRez if test -d $dPrj/$prjNm; then cp -R $dPrj/$prjNm/* $dPrjRez if test ! -f $dPrjRez/oscada.xml; then cp $dSysCfg/oscada_$prjNm.xml $dPrjRez/oscada.xml; fi fi fi fi # Initiating common files and checking if test -d $dPrjRez -a -w $dPrjRez; then if test ! -f $dPrjRez/oscada.xml -a ! -w $dSysCfg/oscada_$prjNm.xml; then cp $dSysCfg/oscada_start.xml $dPrjRez/oscada.xml; fi if test ! -d $dPrjRez/LibsDB -a ! -L $dPrjRez/LibsDB; then ln -s ../LibsDB $dPrjRez/LibsDB; fi if test ! -d $dPrjRez/LibsDB -a ! -L $dPrjRez/LibsDB; then cp -R $dPrjRez/../LibsDB $dPrjRez/LibsDB; fi if test ! -d $dPrjRez/ARCHIVES/; then mkdir -p $dPrjRez/ARCHIVES/MESS $dPrjRez/ARCHIVES/VAL; fi if test $1 = create -a -n "$(which xdg-user-dir)" && test -n "$(xdg-user-dir DESKTOP)"; then DESKTOP_DIR="$(xdg-user-dir DESKTOP)" if test -n "$DESKTOP_DIR" -a ! -f "$DESKTOP_DIR/openscada_$prjNm.desktop"; then cp $dData/applications/openscada.desktop "$DESKTOP_DIR/openscada_$prjNm.desktop" sed -i "s/Exec=/Exec=env OSCADA_ProjName=$prjNm /" "$DESKTOP_DIR/openscada_$prjNm.desktop" sed -i "s/\(^\(Generic\|\)Name\(=\|\\[.*\\]=\).*\)/\1: $prjNm/" "$DESKTOP_DIR/openscada_$prjNm.desktop" fi fi # Checking for lost lock at it PID and openscada process in whole, and starting from the user directory if test -f $dPrjRez/lock; then pid=`cat $dPrjRez/lock | sed -r 's/^0*([0-9]+).*/\1/'` if ! ps -A -o "pid cmd" | grep "^ *$pid.*openscada" > /dev/null; then rm $dPrjRez/lock; fi fi # Processing the core dump files "core[.*]" in the work directory crashHandler $prjNm cores fi ;; remove) if test $# -lt 2; then echo "Not enough arguments!"; exit 1; fi prjNm=$2 prjDir= if test -n "$dPrjUser" -a -d $dPrjUser; then for fit in `ls $dPrjUser`; do if test -d $dPrjUser/$fit && test -f $dPrjUser/$fit/oscada.xml && test $fit = $prjNm; then prjDir=$dPrjUser/$fit break fi done else for fit in `ls $dPrj`; do if test -d $dPrj/$fit && test -f $dSysCfg/oscada_$fit.xml -o -f $dPrj/$fit/oscada.xml && test $fit = $prjNm; then prjDir=$dPrj/$fit break fi done fi if test "x$prjDir" != "x"; then # Removing the backups cd $prjDir/.. for iF in `ls -t ${prjNm}_*.backup 2> /dev/null`; do rm $iF; done # Removing the project folder rm -r $prjDir # Remove the desktop link if test -n "$(which xdg-user-dir)" && test -n "$(xdg-user-dir DESKTOP)"; then DESKTOP_DIR="$(xdg-user-dir DESKTOP)" if test -n "$DESKTOP_DIR" -a -f "$DESKTOP_DIR/openscada_$prjNm.desktop"; then rm $DESKTOP_DIR/openscada_$prjNm.desktop fi fi else exit 1; fi ;; snapshot|crash|cores) if test $# -lt 2; then echo "Not enough arguments!" else crashHandler $2 $1 fi ;; backup) if test $# -lt 2; then echo "Not enough arguments!"; exit 1; fi prjNm=$2 prjBackNm=${prjNm}_$(date +%F_%H.%M).backup if test $# -ge 3; then prjBackNm=${prjNm}_$3.backup; fi prjsDir=$dPrj if test -n "$dPrjUser" -a -d $dPrjUser/$prjNm; then prjsDir=$dPrjUser; fi cd $prjsDir if test -d $prjNm; then echo "Backuping the project \"$prjNm\" to $prjBackNm" OSCD_TAR_ComprPrg=${OSCD_TAR_ComprPrg:=gzip} OSCD_TAR_Args=${OSCD_TAR_Args:=--exclude=lock --exclude=ARCHIVES} tar -I$OSCD_TAR_ComprPrg $OSCD_TAR_Args -cvf $prjBackNm $prjNm > /dev/null ln -f -s $prjBackNm ${prjNm}_last.backup #Processing the backup limit iBack=0 OSCD_BackLim=${OSCD_BackLim:=10} for iF in `ls -t ${prjNm}_*.backup 2> /dev/null`; do if test -h $iF; then continue; fi if test $iBack -ge $OSCD_BackLim; then echo "Removing $iF by the limit $OSCD_BackLim" rm $iF fi iBack=$(($iBack + 1)) done else echo "No the project \"$prjNm\" found!"; fi ;; backupRestore) if test $# -lt 2; then echo "Not enough arguments!"; exit 1; fi backNm=last if test $# -ge 3; then backNm=$3; fi prjNm=$2 prjsDir=$dPrj if test -n "$dPrjUser" -a -d $dPrjUser/$prjNm; then prjsDir=$dPrjUser; fi cd $prjsDir prjBackNm=${prjNm}_$backNm.backup if test -d $prjNm -a -f $prjBackNm; then if test -f $prjNm/lock; then echo "Stop the project $prjNm before restoring from the backup $prjBackNm"; exit 1; fi echo "Restoring the project \"$prjNm\" from the backup $prjBackNm" rm -R $prjNm tar xvf $prjBackNm > /dev/null else echo "No the backup \"$prjBackNm\" found!"; fi ;; backupList) if test $# -lt 1; then echo "Not enough arguments!"; exit 1; fi prjNm=$2 prjsDir=$dPrj if test -n "$dPrjUser" -a -d $dPrjUser/$prjNm; then prjsDir=$dPrjUser; fi cd $prjsDir for iF in `ls -t ${prjNm}_*.backup 2> /dev/null`; do if test -h $iF; then continue; fi echo $iF | sed -n "/^${prjNm}_\(.*\)\.backup/s//\1/p" done ;; update) if test $# -lt 2; then echo "Not enough arguments!"; exit 1; fi prjNm=$2 # OpenSCADA user folder presence if test -z "$dPrjUser" -o ! -d $dPrjUser; then exit 1; fi # Source directory checking whether it or "DATA" if test -d $dPrjUser/$prjNm; then if test ! -f $dPrjUser/$prjNm/oscada.xml; then srcDir=$prjNm; fi elif test -d $dPrjUser/DATA -o -d $dPrjUser/.openscada_old/DATA; then srcDir=DATA; fi if test -z "$srcDir"; then exit 1; fi # Saving the old release data to ".openscada_old" if test ! -d $dPrjUser/.openscada_old; then mkdir $dPrjUser/.openscada_old mv $dPrjUser/LibsDB $dPrjUser/ARCHIVES $dPrjUser/DATA $dPrjUser/*.xml $dPrjUser/*.db $dPrjUser/icons $dPrjUser/.openscada_old/ cp -R $dPrj/LibsDB $dPrjUser/LibsDB fi # New project folder creating if test ! -d $dPrjUser/$prjNm; then mkdir $dPrjUser/$prjNm cp $dPrjUser/.openscada_old/DATA/* $dPrjUser/$prjNm fi # Other elements copying cp $dSysCfg/oscada_start.xml $dPrjUser/$prjNm/oscada.xml if test ! -f $dPrjUser/$prjNm/St.db -a -f $dPrjUser/$prjNm/MainSt.db; then mv $dPrjUser/$prjNm/MainSt.db $dPrjUser/$prjNm/St.db fi cp -R $dPrjUser/.openscada_old/ARCHIVES $dPrjUser/$prjNm ln -s ../LibsDB $dPrjUser/$prjNm/LibsDB ln -s ./ $dPrjUser/$prjNm/$prjNm ;; *) argHelp ;; esac exit 0