#!/bin/sh # # usage: casa-script [script arguments...] # # Credit: https://github.com/pkgw/pwpy - intfbin/casa-script # License: GPLv3+ # # This tool makes it possible to run scripts in a full CASA environment from # the command line in the sanest way I can muster (for my personal definition # of "sane"). Expected usage is in a hashbang line in the script: # # #! /usr/bin/env casa-script # # -*- python -*- # ... # # The elements of sanity are: # # - casapy is invoked in a temporary directory, so that the logfile turds it # likes to drop everywhere get cleaned up. # - command-line arguments are made accessible to the script in a clean-ish # way (last I checked, this didn't work with straight-up casapy) # - output is redirected so that casapy's incessant chatter can be silenced # - the GUI is disabled # # Unfortunately I am unable to do anything about casapy's terrible startup # time. # # Inside the temporary directory, the invocation directory of this script is # symlinked under the name 'data'. All file paths should begin with 'data/', # with special care for command-line arguments, which will need post-processing. # # The command-line arguments to the invoked script are saved, separated by # **NULs**, in a file in the temporary directory called 'args'. These can be # retrieved with: # # argv = open ('args').read ().split ('\0')[2:-1] # # or # args = open ('args').read ().split ('\0')[3:-1] # # The output of casapy is redirected to files 'stdout' and 'stderr' in the # temporary working directory. The standard output and error of this script # are linked to FIFOs in the work directory named 'csout' and 'cserr'. # Therefore, to selectively output data to the invoker, do # # csout, cserr = open ('csout', 'w', 1), open ('cserr', 'w', 1) # ... # print >>csout, 'info: this script works' # ... # print >>cserr, 'warning: your data are broken' # # Keep in mind that the script is being executed in CASA's IPython # environment, so the environment is highly non-vanilla. Because IPython # just prints exceptions to the screen, you need to wrap the entire program # in a try/except block and handle them manually: # # # after setting up cserr # try: # ... entire program ... # except SystemExit: # pass # except: # import os, sys, traceback # traceback.print_exception (*sys.exc_info (), file=cserr) # os._exit (1) # # Note that we need to use os._exit() to be able to actually exit with an # error return code. Do not use sys.exit() or (CASA's) exit(). # Set up a fully-qualified path name to the input script so that CASA can # always find it, even when we hop around in subdirectories. Otherwise it # tries to evaluate the filename as a line of Python. script=$(cd $(dirname $1) && pwd)/$(basename $1) if [ ! -e "$script" ] ; then echo >&2 "error: cannot find input script \"$1\"; should be at \"$script\"" exit 1 fi workdir=`mktemp -d casascript.XXXXXXXXX` cd "$workdir" ln -s .. data cp /proc/$$/cmdline args mkfifo csout cserr || exit 1 # Process group management insanity: # http://stackoverflow.com/a/1645157/3760486 I'm sure I could do a # better/cleaner job of this, but I'm pretty sure this code errs on the side # of safety, and that's my priority. trap : SIGTERM SIGINT cat csout & killpids="-$!" cat cserr >&2 & killpids="$killpids -$!" casapy --log2term --nogui -c "$script" stdout 2>stderr & killpids="$killpids -$!" wait $! retval=$? if [ $retval -gt 128 ] ; then kill -- $killpids fi if [ $retval -ne 0 ] ; then echo >&2 "error: casapy exited with error code $retval; preserving work directory $workdir" else cd .. [ x"$CASASCRIPT_DEBUG_WORK" != x ] || rm -rf "$workdir" fi exit $retval