Search
Text Size:
Smaller Text Normal Text Larger Text

Facebook

Follow us on Twitter

Usage and examples of Sequencer scripts

The basic way of using the sequencer is by typing sequencer commands in a terminal window. The sequencer commands are exactely like any other UNIX command in the way that they are executed and exists as processes. As they get executed by the shell (C shell by default), all aspects of job control, shell syntax etc. applies to the sequencer commands as they do to any other UNIX command.

They can be put in the background, using "Ctrl-Z, bg" or using "&" after the command. An example of this is the "expose" command. If given normally, i.e. executing in the foreground, the command will not return until the image is read out and stored on disk. You can execute the command in the background ("expose &") and get the command prompt back immediately. In this case you can use the "about" command to about the on-going exposure.

These comments are only highlights of a small number of possibilities available. The real "sequencer manual" is, in fact, a manual of the UNIX C shell (or the shell of your choice if using a script).

There is great flexibility when writing scripts for the sequencer. As the normal UNIX tcsh shell is used, the syntax is well documented elsewhere

Click here for a manual in C shell script writing

It is also possible to use BASH for making scripts, in any case the full command names must be used (e.g. alfosc.xbin). The full command names for the different command groups can be found in the command reference in the header for the command groups (i.e. BIAS, instrument, TCS, etc.)

You may copy any instrument script to your own directory for editing, for instance doing:

cp ~staff/alfosc.polspecwin  my.polspecwin


There are some basic rules that must be followed to get the correct behaviour.


  • The first line of the script MUST be

    #!/bin/tcsh

    or

    #!/bin/bash

    in the case you want to use BASH.

  • Before you can use your script, you have to make it executable with the command

    chmod +x my_script

  • Commands (in this case sequencer commands) can be executed in the background putting a '&' after the command. In this case, the script will immediately continue to the next command in the script.

  • The script can use parameters given on the command line. These are accessible in the variables $1, $2 etc.
    In the script executed like this:

    my_script var1 var2

    var1 will be available as $1 and var2 as $2.

  • Your script can (and should if it is complicated) log informative messages to the talker (and thus to the user), using the logger command.
    Three levels of logging can be used - DEBUG, NOTE and ERROR. DEBUG is used for functionality debugging and can only be seen when this level has been enabled in the Talker. NOTE is the normal way of logging informative messages. ERROR is only used for errors produced by the programme/script. The ERROR messages will appear in red in the Talker. Here is how to use it:

    /usr/bin/logger -p local0.debug -t "scriptname" "[NOTE]: My note"

    for normal log messages

    /usr/bin/logger -p local0.debug -t "scriptname" "[DEBUG]: My note"

    for debug log messages

    /usr/bin/logger -p local0.debug -t "scriptname" "[ERROR]: My note"

    for error log messages

    , where "scriptname" must be an informative name of your script. Alternatively, '$0' can be used as scriptname to use the current filename. The square brackets, the colon and the following space must be there.

  • We strongly advice to notify the talker upon start and end of script execution:

    logger -p local0.debug -t "$0" "[NOTE]: Script started as $0 $*"

    ... the script ...

    logger -p local0.debug -t "$0" "[NOTE]: Script ended successfully"

    The '$0' will echo the script name, and '$*' will echo the parameters which the script was called with.


An example:

An ALFOSC script that will make a 300 second exposure with a teloffset of variable size (to be given on the command line) in 3 filters can be written like this:

#!/bin/tcsh

logger -p local0.debug -t "$0" "[NOTE]: Script started as $0 $*" 

set xoffset = $1
set yoffset = $2
set filters = "1 2 3"

foreach filter ($filters)
  alfoscinst.filter $filter
  alfosc.expose 300
  alfosc.teloffset $xoffset $yoffset
end

logger -p local0.debug -t "$0" "[NOTE]: Script ended successfully"
exit
This script will then be used like

myscript 10.0 10.0

The commands that moves an element (a filter, grism, arm etc.etc) will not complete until this movement has been made. This means that in the script above, the 'expose' command will not start until the filter has arrived at the commanded position and the 'teloffset' command will not start until the exposure (and readout) has finished.

Dealing with error

Any program that you execute from inside a script may end because of an error. The way programs tell you about errors is through status codes. This status code is a number from 0 to 255, that you can find in the $? variable. This variable will always contain the status code for the latest program that has finished running before testing for said code. Note that This Doesn't Apply to Programs That Have Been Running in the Background. It's difficult to track the return code for those programs, and thus you will never get it from them.

A value of 0 means "no error". Any other value means "something happened", and will be considered an error.

Of course, having a variable with a numeric value defining if there was an error (or not) in the previous command, allows us to test for errors using an "if" construct.

Shell script interpreters may react to the errors automatically, or not. This behaviour is controlled using the "-e" modifier in the first line of the script, like this:

  #!/bin/tcsh -e
If this "-e" is specified, the script will abort as soon as a program returns an error code if the error is not captured somehow. If the "-e" modifier is not specified, then you're responsible for all the error handling.

The following explanation on capturing and treating errors assume you've specified the -e. As it's been said, the script will abort if the last executed program (that is not in the background) exits with an error code. There are a couple of subtleties when it comes to defining "the last executed program". For example, in here:

  #!/bin/csh -e

  echo "This line is executed"
  # This is a program that returns an error
  faulty_program
  echo "This line is never executed"
In this case it's quite clear what happens, but there are other modes where certain subtleties determine which code we get, like this:
  #!/bin/csh -e

  echo "This line is executed"
  faulty_program | non_faulty_program
  echo "This line *is* executed too"
What happened here? When there's a sequence of programs, only the last one to be executed is taken into account. In this case, we had a sequence of piped programs, and the only return code that the shell cares about is the one from the last program in the pipe. The first one in line failed, but the second didn't, and so the script continued happily. This is something we need to have in mind, because errors can slip without us noticing, while we thought the script was going to fail in case something happens.

Other sequences are the ones where programs are separated by || or by &&. Those are rather useful when controlling errors. And they work the following way:

  • When two programs are separated by || (two vertical bars), the second one will be executed only if the first one fails. You could interpret a line saying program1 || program2 as if it reads "do this thing and, if it fails do this other".

    Note that if the first program doesn't fail, the second one never executes, and the shell considers this as a non-error situation. If the first program fails, the second one is executed, and it will be its return code the one that the shell takes into account to figure out if it needs to abort or not.

  • When two programs are separated by &&, the second one will be executed only if the first one returned without error.

    Now, if the first program fails, the second won't execute, and the shell will get the error code from the first program, because it was the last one to be executed. Then, this is an error and the script will abort.

By using || and &&, we can easily control the execution of certain programs, and what to do in case of failure (or success). An example use is logging and quit after a critical error, like this:

  # If the following fails, the rest of the script shouldn't work
  alfosc.exp 5 || ( logger -p local0.debug -t "myscript" "[ERROR]: Couldn't expose. Aborting"; exit 1 )
Back to top Last modified: 14-Sep-2012