#! /bin/bash # GRIXEC--minimalistic user-level batch middleware # Copyright (c) 2011 Alexandru Dan Corlan MD PhD (http://dan.corlan.net) # this program is covered by the GNU General Public Licence version 3 # WELCOME TO GRIXEC, a set of minimalistic tools to run unix # computational commands persistenly, that is to run commands that # read data files and produce result file with the preservation of the # command and the files. GRIXEC is meant as an experiment in order # to gather the specification of a simpler, unified user interface to # batch processing facilities, large and small, local or distributed # HOME PAGE (and USER MANUAL): # http://dan.corlan.net/software/grixec.html # # RELEASE HISTORY: # V0.1 -- June 27, 2011 -- basic functionality # V0.19 -- January 23, 2011 -- added danotation format for some data, older metadata format # -- still supported but declared obsolete # V0.2 -- January 24, 2011 -- meta-data moved to danotation format; depends on danotation # -- renamed grixall2 # # INSTALLING: # download this file, named grixall2, then # # chmod a+x ./grixall0.2 # sudo ./grixall0.2 install # # this will install this file and a few links to it (gxec, gxac, gxay) # in the /usr/local/bin directory; use the links as the user commands; # change the INSTALLDIR variable below to install in another directory INSTALLDIR=/usr/local/bin GRIXOME=grixome jcount () { printf J%03d `ls data | wc -w` } grixec () { USAGE="Usage: grixec -c file* [-m user@machine] -x cmd arg*" PROJDIR=`pwd` THECALL="$@" JOBID=`uuid` if [ $1 != -c ] then echo $USAGE exit 33 fi shift if [ $# -eq 0 ] then echo $USAGE exit 33 fi mkdir -p ~/$GRIXOME mkdir -p ~/$GRIXOME/$JOBID mkdir -p ./data JNAME=`jcount` echo $JNAME $JOBID ln -sf ~/$GRIXOME/$JOBID data/$JNAME MACHINE="local" # gxay dict jobnamed $JOBID $JNAME # gxay dict joblink $JNAME $JOBID # gxay $JNAME id $JNAME $JOBID # gxay $JNAME projdir $JNAME $PROJDIR # gxay $JNAME call $JNAME \"gxec $THECALL\" # gxay $JNAME created $JNAME \"`date`\" # gxay $JNAME by $JNAME $USER while [ $1 != -x ] ; do if [ $1 == -m ] ; then MACHINE=$2 shift; shift else cp $1 ~/$GRIXOME/$JOBID shift if [ $# -eq 0 ] then exit fi fi done # gxay $JNAME machine $JNAME $MACHINE # gxay $JNAME runfrom $JNAME `hostname` gxay $JNAME joblink $JNAME\ project_path \"$PROJDIR\" \ project \"`basename $PROJDIR`\" \ call \"gxec $THECALL\"\ machine \"$MACHINE\"\ runfrom \"`hostname`\"\ jobuuid \"$JOBID\" shift cd ~/$GRIXOME/$JOBID CMTUUID=`uuid | sed s/-/_/g` echo "#! /bin/bash # this script was automatically generated by grixec # caled at: " `date` " # with: grixec $THECALL # from project directory: $PROJDIR # project-specific name: $JNAME " $@ " echo userlog log_$CMTUUID date \\\"`date`\\\" status DONE _ >>dict.dan echo DONE >status " >grixrun chmod u+x grixrun # run # echo $MACHINE >machine #WARNING!! # the following gxays write in the dict.dan of the _current_ # directory, that now is the job directory if [ $MACHINE == "local" ] ; then exec /usr/bin/time -o timings `pwd`/grixrun >stdout.log 2>stderr.log & echo RUNNING >status gxay dict status RUNNING else ssh $MACHINE "mkdir -p $GRIXOME" gxay dict status RUNNING echo RUNNING >status scp -r `pwd` $MACHINE:$GRIXOME REMWD=`ssh $MACHINE "cd $GRIXOME/$JOBID; pwd"` ssh -n $MACHINE "cd $GRIXOME/$JOBID ; /usr/bin/time -o timings $REMWD/grixrun >stdout.log 2>stderr.log" ST="RUNNING" until [ $ST == "DONE" ] ; do sleep 2 ST=`ssh $MACHINE "cd $GRIXOME/$JOBID; cat status"` echo $ST done scp -r $MACHINE:$GRIXOME/$JOBID/* . echo DONE >status gxay dict status DONE fi } UUIDPAT=[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f]-[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f] grixacc.usage () { echo "Usage: grixacc a b c d e ..." echo "(where a, b, ... are increasingly specialised data locators)" echo "see the command source for details (more `which grixacc`)" } jobid () { ls -l data/$1 | sed "s/.*\($UUIDPAT\).*/\1/" # danotation jobuuid < data/$1/dict.dan | head -n 1 |sed s/\"//g } status () { cat data/$1/status # danotation status < data/$1/dict.dan | tail -n 1 } machine () { danotation machine < data/$1/dict.dan | head -n 1 } subfile () { DAF=$1 shift danotation $@ <$DAF } synoptic() { # echo $1 `jobid $1` `cat data/$1/status` `cat data/$1/machine` echo $1 `jobid $1` `status $1` `machine $1` } # Usage: grixacc a b c d e ... # # grixacc last jobdataspec... -- data for the latest started job from the current project # grixacc loclist -- list of the current project jobs and their status # grixacc job Jnnn jobdataspec... -- data for (local) job Jnnn # # jobdataspec... can be: # file -- will cat the file on stdout # path -- will produce the pathname to the respective file of the job # -- or the path to the respective job jobdataspec () { if [ $# -lt 2 ] ; then echo $1 return fi if [ $2 == "ls" ] ; then ls data/$1 return fi if [ $2 == "id" ] ; then jobid $1 return fi if [ $2 == "prjid" ] ; then echo $1 return fi if [ $2 == "syno" ] ; then synoptic $1 return fi if [ $2 == "format" ] ; then JID=$1 shift ; shift for j in $@ ; do grixacc $JID $j done return fi if [ $2 == "status" ] ; then status $1 return fi if [ -a data/$1/$2 ] ; then # echo --first-- DAFILE="data/$1/$2" if [ $# -eq 2 ] ; then cat $DAFILE else shift ; shift subfile $DAFILE $@ fi return else # ambigous if the file exists...but otherwise like danotation # echo --second-- $1 DAFILE=data/$1/dict.dan shift subfile $DAFILE $@ | sed /NA/d fi } grixacc () { if [ $# -lt 1 ] ; then grixacc.usage exit 1 fi if [ $1 == "last" ] ; then LASTJ=`ls -td data/J* | head -n 1` shift jobdataspec `basename $LASTJ` $@ elif [ $1 == "dict" ] ; then shift subfile data/dict $@ elif [ $1 == "all" ] ; then shift for i in `ls -td data/J*` ; do jobdataspec `basename $i` $@ done else jobdataspec $@ fi } logtodan() { DICTDAN=$1 CMTUUID=`uuid` echo "userlog " log_$CMTUUID >>$DICTDAN echo " date " \"`date`\" >>$DICTDAN echo " by " \"`whoami`\" >>$DICTDAN #shift shift echo $@ >>$DICTDAN echo "_" >>$DICTDAN } grixay () { if [ $1 == "project" ]; then shift logtodan dict.dan $@ exit fi if [ $1 == "dict" ]; then shift logtodan dict.dan $@ exit fi echo $1 | grep -q "J[0-9][0-9][0-9]" if [ $? -eq 0 ]; then JNM=`basename $1 .dan` shift logtodan data/$JNM/dict.dan $@ logtodan dict.dan projob $JNM $@ exit fi if [ $1 == "last" ] ; then LASTJ=`ls -t data | grep 'J[0-9][0-9][0-9]' | head -n 1` shift logtodan data/$LASTJ/dict.dan $@ logtodan dict.dan projob $LASTJ $@ exit fi } case `basename $0` in grixall0.2) if [ $1 == "install" ] ; then cp grixall0.2 $INSTALLDIR chmod a+x $INSTALLDIR/grixall0.2 ln -sf $INSTALLDIR/grixall0.2 $INSTALLDIR/gxec ln -sf $INSTALLDIR/grixall0.2 $INSTALLDIR/gxac ln -sf $INSTALLDIR/grixall0.2 $INSTALLDIR/gxay ln -sf $INSTALLDIR/grixall0.2 $INSTALLDIR/gxals fi ;; gxec) if [ $# -eq 0 ] ; then echo Usage: gxec gxac gxay gxals else grixec $@ fi ;; gxay) grixay $@ ;; gxac) grixacc $@ ;; gxals) grixacc last status ;; esac