#! /bin/csh -f # # sendhome.com v0.95 # # Send your x-ray frames to a remote machine (home) # continuously, AS they are collected! # # -James Holton 12-12-1901 :) # ################################################################################ echo "$0 - a safe, secure, and backgroundable way to send files home James Holton 12-12-1901" echo "" goto Setup # # Routine (at bottom) to read command-line args # Help: cat << EOF-help usage: $0 /data/${user}/frames/first_001.img ${user}@remotehost.college.edu:/bigdisk/${user}/frames/ [no compress] where: /data/${user}/frames/ - the local directory containing frames first_001.img - the first (oldest) frame to send home any frames newer than [first_001.img] will also be sent ${user}@remotehost.college.edu - your login at home /bigdisk/${user}/frames/ - the disk (at home) you want to put your frames on (remote directory will be created if it doesn't exist) Other options: no compress - (optional) do not compress the files during transfer (usually 3x slower) timeout 50 - set the connection time-out to 50 minutes no timeout - disable connection time-out (careful! might interfere with last file ) ----------- a log of files that were sent home will be kept in $sentlog NOTE: things will probably go a lot faster if: /bigdisk is pysically attached to remotehost.college.edu /data is pysically attached to the computer running sendhome EOF-help # exit is "Help" was not just displayed for fun... #if($?BAD) exit 9 Return_from_Setup: if("$rhost" == "") goto Help ############################################################################### # preamble ############################################################################### echo "logging sent files in $sentlog" echo "sending ${minsize}-byte files" echo -n "from ${framedir} " if("$firstfile" != "") echo -n "(starting with "\"$firstfile\"") " if("$lastfile" != "") echo -n "(finishing with "\"$lastfile\"") " echo "" echo "to $rdir on ${ruser}@${rhost}" if($?CLEAR) echo "local copy will be deleted once file has been sent." onintr User_Interrupt unset FINISHED touch $sentlog if($?BUNCHWISE) goto Bunchwise ############################################################################### # start sending frames home ############################################################################### echo "$framedir ext $minsize $timeout $lastfile $firstfile $sentlog" |\ nawk '{framedir=$1;minsize=$3;timeout=$4*60;lastfile=$5;firstfile=$6;\ if(firstfile == "") sending=1;\ cmd="ls -lLrt "framedir; while(1){new=0;\ # keep listing the directory every 10 seconds \ while(cmd | getline){\ # ignore entries before the first file \ if($NF == firstfile){sending=1};\ # pretend earlier entries were already sent \ if(! sending) sent[$NF]=1;\ if((sending)&&($5>=minsize)&&(! sent[$NF])){\ print $NF; fflush(); ++new; idle=0; \ # keep an internal record of files we have sent \ sent[$NF]=1;};\ # exit when we see a file called "exit" \ if($NF == lastfile){exit};\ };\ # idle timeout so last file send finishes \ close(cmd); if(! new){system(" sleep 10 "); idle+=10};\ if(idle > timeout) exit;}}' |\ (cd $framedir; tar c${B}${T}f - - ) | $compresser |\ ssh -x -k ${ruser}@${rhost} "if(! -e $rdir) mkdir -p $rdir; $decompress | (cd $rdir ; tar xv${B}f - )" |\ nawk -v clear=$?CLEAR -v framedir=$framedir -v sentlog=$sentlog '\ {filename=""; for(i=1;i<=NF;++i){ word=$i; \ if(! system("test -s " framedir "/" word)) filename=word; \ word=substr($i,1,length($i)-1);\ if(! system("test -s " framedir "/" word)) filename=word; \ } if(filename=="") {print; next}}\ clear!=0 && sentfile!=""{if(! system("rm -f " framedir "/" sentfile)) printf "deleted %s ", sentfile} \ {print ""} \ {printf "sending %s ", filename; print filename > sentlog} \ {sentfile=filename} \ END{if(clear !=0 && sentfile!="") if(! system("rm -f " framedir "/" sentfile)) printf "deleted %s ", sentfile; \ print ""}' # user will only have to enter their remote password once if(-e "${framedir}/$lastfile") then # the "exit" file was produced set FINISHED goto done endif # reaching here means the file-finder program timed out goto Timed_out Bunchwise: ############################################################################### # make a list of at least $bunch_size files before initiating a send # mainly for OSF1 users echo "unimplemented! sorry." exit 9 goto done # user will have to enter their remote password once per bunch Timed_out: ############################################################################### echo "timeout: $timeout minutes" set FINISHED User_Interrupt: ############################################################################### onintr done echo "connection lost...." # don't ask user questions if output is not a terminal test -t 1 if($status) set DONT_ASK echo "reconnect to ${rhost}? [Yes]" echo -n "->" if(! $?DONT_ASK) then set temp = "$<" else set temp = "No" echo "" endif if("$temp" =~ [Nn]*) then goto done endif # re-discover first filename set firstfile = "" goto reconnect ############################################################################### done: ############################################################################### onintr # don't ask user questions if output is not a terminal test -t 1 if($status) set DONT_ASK if(! $?FINISHED) then # extract last file sent from TAR log cat $sentlog |&\ nawk 'BEGIN{RS=" "} {print}' |\ nawk '/,$/{print substr($0,1,length($0)-1)} ! /,$/{print}' |\ nawk 'NF==1' |\ tail -1 >! ${tempfile}$$ set firstfile = `tail -1 ${tempfile}$$` rm -f ${tempfile}$$ >& /dev/null if(-e "${framedir}/$firstfile") then echo "" echo "WARNING! remote $firstfile is incomplete! " echo "" echo "send it now? [Yes]" echo -n "->" if(! $?DONT_ASK) then set temp = "$<" else echo "" endif if("$temp" =~ [Nn]*) then goto cleanup endif # do the standard send for one file echo "$firstfile" |\ (cd $framedir; tar c${B}${T}f - - ) | $compresser |\ ssh ${ruser}@${rhost} "$decompress | (cd $rdir ; tar xv${B}f - )" |&\ nawk -v clear=$?CLEAR -v framedir=$framedir -v sentlog=$sentlog '\ NF==1{filename= $1} NF>1{filename = substr($2,1,length($2)-1)} \ {printf "sending %s", filename; print filename > sentlog} \ END{if(clear !=0){if(! system("rm -f " framedir "/" filename)) printf " deleted %s\n", filename;}}' if(! $status) set FINISHED endif endif cleanup: if($?FINISHED) then echo "done" endif exit ############################################################################### # set-up routine (moved to bottom for clarity) Setup: if(! $?user) set user = `whoami` # defaults (can be reset interdependently) set timeout = "60" # max time since last new file appeared (minutes) set framedir = "" # directory to send files from set firstfile = "" # first file (chronologically) to send set lastfile = "exit" # last file (chronologically) to send set minsize = 10617344 # file must reach this size before being sent set ruser = "" # remote username set rhost = "" # remote computer name set rdir = "" # send-to directory on remote computer if($?CLEAR) unset CLEAR #set CLEAR # uncomment to delete files after they are sent set tempfile = ./tempfile set sentlog = ./sent_home.log touch $sentlog >& /dev/null if($status) then set sentlog = ~/sent_home.log set tempfile = ~/tempfile endif touch $sentlog >& /dev/null if($status) then echo "ERROR! unable to create sent-file log" echo "please make sure either "`pwd`" or ~$user is writable! " sleep 2 set BAD goto Help endif # default: use compress (gzip is too slow) # default: use gzip (compress has a stream size limit) set compresser = "gzip --fast -c" set decompress = "gunzip -c" # machine-specific configurations set machine = `uname` set T = "" #set B = "B" set B = "" if("$machine" =~ IRIX*) then set T="L" endif if("$machine" == "Linux") then set T="hT" alias nawk awk endif if("$machine" == "OSF1") then echo "ERROR: realtime file transmission is not possible on Digital Unix" echo " this is because the OSF1 tar program is incapable of streaming" echo " archives. A workaround is being implemented, but is not yet" echo " available. " echo "" echo " You will probably have better luck on an SGI or Linux box." echo "" set BUNCHWISE set bunch_size = 50 endif # scan the command line if($#argv == 0) goto Help set i = 0 while ( $i < $#argv ) @ i = ( $i + 1 ) set arg = "$argv[$i]" # check for local directory specifier if(("$arg" =~ */*)&&("$arg" !~ *[@:]*)||(-e "$arg")) then if(-e "$arg") then test -d $arg if(! $status) then # just a directory set framedir = "$arg" continue endif test -c $arg if(! $status) then # support tapes one day? continue endif # must just be a regular file (or link) if("$firstfile" == "") then set framedir = `dirname $arg` set firstfile = `basename $arg` else # use last local filename given as a "last" file set lastfile = `basename $arg` endif continue else if("$framedir" == "") then # no files specified yet set framedir = `dirname $arg` set prefix = `basename $arg` set firstfile = `ls -lL $framedir | nawk '$5>1000000 && ! /dkc$/ {print $NF}' | egrep "^$prefix" | head -1` if(-e "${framedir}/$firstfile") then continue endif # guess that wasn't anything set framedir = "" set firstfile = "" echo "WARNING: $arg does not exist! " else # maybe this is a preemtive last file? if("$arg" =~ *.$ext) set lastfile = `basename $arg` endif endif endif # check for remote file specifier if("$arg" =~ *[@:/]*) then # retrieve remote username set ruser = `echo $arg | nawk 'BEGIN{FS="@"} NF>1{print $1}'` if("$ruser" == "") set ruser = `whoami` # get the remote computer name set rhost = `echo $arg | nawk 'BEGIN{FS="@"} {print $NF}' | nawk 'BEGIN{FS="[:/]"} {print $1}'` if("$rhost" != "") then # get remote directory name if("$arg" =~ *:*) then # everything after first colon is directory set rdir = `echo $arg | nawk 'BEGIN{FS="@"} {print $2}' | nawk '{print substr($0,index($0,":")+1)}'` set rdir = `echo $arg | nawk 'BEGIN{FS="@"} {print $2}' | nawk 'BEGIN{FS=":"} {print $2}'` else # everything after first "/" is directory set rdir = `echo $arg | nawk '/[\/]/{print substr($0,index($0,"/"))}'` endif else echo "WARNING: did not understand $arg" echo " please use: user@host:directory" endif continue endif # optional compression stuff if(("$arg" == "compress")||("$arg" == "-compress")) then set compresser = "compress -c" set decompress = "uncompress -c" if($?NO) then # disable compression set compresser = "cat" set decompress = "cat" endif continue endif if(("$arg" == "gzip")||("$arg" == "-gzip")) then set compresser = "gzip --fast -c" set decompress = "gunzip -c" continue endif # ignore last sentlog if(("$arg" == "new")||("$arg" == "-new")) then echo "clearing $sentlog ..." echo -n "" >! $sentlog endif # delete files after sending them #if(("$arg" == "clear")||("$arg" == "delete")||("$arg" == "remove")) then if(("$arg" == "delete")) then if($?NO) then unset CLEAR else set CLEAR endif endif # negative logic (for next word) unset NO if(("$arg" == "no")||("$arg" == "-no")||("$arg" == "not")) then set NO continue endif end # default timeouts (relative speed of detectors) if("$firstfile" =~ *.mar*) set timeout = 120 if("$firstfile" =~ *.img) set timeout = 60 if("$firstfile" =~ *.osc) set timeout = 200 # second pass # scan the command line set i = 0 while ( $i < $#argv ) @ i = ( $i + 1 ) set arg = "$argv[$i]" # manual setting of timeout if(("$arg" == "timeout")||("$arg" == "-timeout")) then if($?NO) then # set timeout to 24 hours set timeout = 1440 else @ j = ( $i + 1 ) if($j <= $#argv) then if("$argv[$j]" =~ [0-9]*) then # user-specified timeout set timeout = `echo $rgv[$j] | nawk '{print $1+0}'` endif endif endif endif # negative logic (for next word) unset NO if(("$arg" == "no")||("$arg" == "-no")||("$arg" == "not")) then set NO continue endif end # defaults for bad or missing inputs if(! -e "$framedir") then # default to current directory set framedir = "." set firstfile = "" endif if("$rhost" == "") then set temp = "" echo "where shall we send $firstfile ... etc. to? [${user}@home.college.edu:/bigdisk/${user}/frames]" echo "" echo -n "-> " if(! $?DONT_ASK) set temp = "$<" if(("$temp" =~ *[@:]*)) then set argv = ( $temp ) goto Setup endif goto Help endif if("$rdir" == "") then echo "WARNING: files will be sent to ${ruser}@${rhost}'s HOME directory! " set rdir = "." endif # jump here to re-establish send where we left off reconnect: # check to see if we don't have a first filename yet if(("${firstfile}" == "")||(! -e "${framedir}/$firstfile")) then # check for an old, aborted run if(-e "$sentlog") then # extract last file sent from TAR log cat $sentlog |&\ nawk 'BEGIN{RS=" "} {print}' |\ nawk '/,$/{print substr($0,1,length($0)-1)} ! /,$/{print}' |\ tail -1 >! ${tempfile}$$ set temp = `head -1 ${tempfile}$$` rm -f ${tempfile}$$ >& /dev/null if(-e "${framedir}/$temp") then echo "reading $sentlog" set firstfile = "$temp" endif endif endif # default to the first file in the directory if(("${firstfile}" == "")||(! -e "${framedir}/$firstfile")) then set firstfile = `ls -lLrt $framedir | nawk -v size=$minsize '$5>=size{print $NF}' | head -1` endif # still nothing? if(("${firstfile}" == "")||(! -e "${framedir}/$firstfile")) then # wait for something to appear set firstfile = "" # maybe just send the directory? endif # set the target frame size if(("$firstfile" != "")&&(-e "${framedir}/$firstfile")) then set minsize = `ls -lL ${framedir}/${firstfile} | nawk '$5+0>0{print $5}'` # get filename extension too set ext = `echo $firstfile | nawk 'BEGIN{FS="."} {print $NF}'` endif goto Return_from_Setup ################################## # Future plans # # use cpio instead of tar? # implement bunch-wise send # # checksum remote files after transfer (retransmit?) # send directories? # #