Osh's Command-Line Interface

The osh executable interprets its command-line arguments as osh syntax. Osh should be usable from any shell, although some osh CLI syntax may require escapes in some shells. (The osh CLI has been tested most extensively using the bash shell.)

CLI Usage

This osh command prints the integers 0 through 9 and prints the square of each:
    zack$ osh gen 10 ^ f 'x: x**2' ^ out
Comments:

As a syntactic convenience, the token $ can be used instead of ^ out at the end of an osh command sequence. However, if this is done, then only default behavior for out is obtained. (The out command has options for formatting, and for writing to files.)

Input can be passed to an osh command sequence using a Unix pipe as follows:

    zack$ cat /usr/share/dict/words | osh ^ select 'w: len(w) >= 20' $
This command begins by writing the contents of /usr/share/dict/words to stdout. A Unix pipe is used to send this stream of data to osh. "osh ^" is a special syntactic form which converts each line of input from stdin into a Python string (omitting the line terminator \n). These strings are passed to the next command which keeps only those strings whose length is at least 20, and prints them to stdout.

Remote Execution

There is one other special syntactic form, used for remote execution. Example:
    zack$ osh @fred [ sh date ] $
    ('101', 'Mon Aug  6 23:03:26 EDT 2007')
    ('102', 'Mon Aug  6 23:03:26 EDT 2007')
    ('103', 'Mon Aug  6 23:03:27 EDT 2007')
This executes the bracketed command sequence, sh date on each node of cluster fred. sh is an escape to a native shell, so sh date runs the date command on each node. Typical output is shown above. Output from sh date would normally be a single value, e.g. 'Mon Aug 6 23:03:26 EDT 2007', but remote execution prepends the name of the node that generated the output, (in this case there are three such nodes, 101, 102 and 103).

Running Arbitrary Python Code

There are two mechanisms for running Python code from the osh command-line interface. One technique is to define variables, functions, etc. in .oshrc and then refer to those symbols in osh commands, (see Configuring osh for details).

The other approach is to use the osh commands imp and py. imp imports modules for use by commands later in the command sequence. py runs arbitrary Python code; the intent is to define symbols that can be used by commands later in the command sequence. Both commands pass objects received on the input stream to the output stream. In both cases, the import or python code is executed once, before objects start flowing on the streams connecting commands in the command sequence. For example, the following command line prints the area of circles with radii 0, 1, 2, ... 9:

    zack$ osh py 'pi = 3.14159265358979' ^ gen 10 ^ f 'r: (r, pi * r**2)' $
    (0, 0.0)
    (1, 3.14159265359)
    (2, 12.5663706144)
    (3, 28.2743338823)
    (4, 50.2654824574)
    (5, 78.5398163397)
    (6, 113.097335529)
    (7, 153.938040026)
    (8, 201.06192983)
    (9, 254.469004941)

Error and Exception Handling

If something goes wrong during the execution of an osh command, an exception or error handler is invoked. For example, division by zero raises the ZeroDivisionError exception. The default exception handler prints a description of the problem to stderr. Example:
    zack$ osh gen 3 ^ f 'x: x / (x-1)' $
    (0,)
    f#3[x: x / (x-1)](1):  exceptions.ZeroDivisionError: integer division or modulo by zero
    (2,)
gen 3 generates the integers 0, 1 and 2. These integers are piped to the function x: x / (x-1) which raises ZeroDivisionError for x = 1. The first and third lines of output show the expected output for x = 0 and 2, printed to stdout. The middle line goes to stderr:

A similar mechanism is used in case an osh command writes to stderr. Each line going to stderr is passed to an error handler, and the default error handler adds context information and writes to osh's stderr. (Only the sh command is currently capable of invoking this mechanism, as it is the only command that can write to stderr.)

The default exception and error handlers can be overridden. This can be done by invoking set_exception_handler and set_error_handlerf from .oshrc. (See the documentation on the module osh.error for details.)