#!/usr/bin/python from osh.api import * osh(gen(10), f(lambda x: x**2), out())The last line of this script works as follows:
One way to fix this is to write a function which collects the output, and execute it using the f command:
#!/usr/bin/python from osh.api import * squares = [] def collect_output(x): squares.append(x) osh(gen(10), f(lambda x: x**2), f(collect_output)) print squares
The osh API provides a simpler alternative. If the last command in the command sequence is return_list, then the output from the previous command is accumulated and returned as the value of the osh invocation, e.g.
#!/usr/bin/python from osh.api import * print osh(gen(10), f(lambda x: x**2), return_list())
To pass lines of text from stdin to osh, use the stdin command. For example, the following script can be used to print sorted input:
#!/usr/bin/python from osh.api import * osh(stdin(), sort(), out())
#!/usr/bin/python from osh.api import * osh(remote("fred", sh("date"), out()))The output from this script might look like this:
('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')
The osh command executes 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. 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).
If the command sequence to be executed remotely has more than one command, then the commands need to be organized into a list. For example, this script finds all java processes running on each node of cluster fred:
#!/usr/bin/python from osh.api import * osh(remote("fred", [f(processes), expand(), select('p: "java" in p.command_line()')]), out())The list of remotely executed commands works as follows:
However, there is one situation in which the string form of function is required. If a function is to be executed remotely, then the function must be written using a string. (The reason for this is that command sequences to be executed remotely are pickled and sent to each node over ssh. Strings can be pickled but functions cannot be.)
#!/usr/bin/python from osh.api import * osh(gen(3), f(lambda x: x / (x-1)), out())The output from this script is:
(0,) f#2[<function <lambda> at 0x5b0f0>](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 lambda 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.)