diff options
-rwxr-xr-x | astro/casa-script | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/astro/casa-script b/astro/casa-script new file mode 100755 index 0000000..615b7eb --- /dev/null +++ b/astro/casa-script @@ -0,0 +1,111 @@ +#!/bin/sh +# +# usage: casa-script <script.py> [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" </dev/null >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 |