1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
|