Calls external programs, creates pipelines, etc. (simplified interface)
Signal handlers: When you call the function call
, signal handlers
are automatically installed by Shell_sys.install_job_handlers, unless
this installation has already been performed. You can configure these
handlers by Shell_sys.configure_job_handlers. The handlers remain
in effect even after call
returns.
Note that this has a global side effect on the whole process, because there is only one set of signal handlers.
The following functions are simplified versions of the
Shell_sys.job
abstraction.
The string contains the called commands in a readable representation. The list enumerates the return codes of the processes that have been started for the commands.
A producer generates data sent to a called process
A consumer receives data from a called process
An assignment redirects file descriptors while calling a process
Creates a command descriptor, to be used in call
. The anonymous
string argument is the name of the executable to invoke. If the name
contains a '/', it is simply interpreted as the filename of the
executable. Otherwise the command is searched in the current PATH.
argv[0]
. By
default, this argument is derived from the name of the executable.
cmdname
). By default []
.
[stdin; stdout; stderr]
.
The same as command
but with a slightly different interface: Use
cmd "ls" [ "/dir/file" ]
instead of
command ~arguments:[|"/dir/file"|] "ls"
The named arguments have the same meanings as in command
.
Starts the pipeline represented by the list of commands; i.e.
if [c1;c2;...;cN]
is passed, this corresponds to the pipeline
c1 | c2 | ... | cN
(in shell notation).
The function returns normally if all processes can be started and
terminate regularly with exit code 0. If a process terminates with
some other exit code, and ignore_error_code
is set, the function
returns normally, too. The latter does not apply if a process terminates
because of a signal (which triggers always the exception
Subprocess_error
).
If a process terminates with an exit code other than 0 and
ignore_error_code
is not set (the default), or if a process is
terminated because of a signal, the exception Subprocess_error
will be raised. For every command the process result is included
in the exception argument.
If a process cannot be started (e.g. because of insufficient
resources), the function will try to shut down the already running
part of the pipeline by sending SIGTERM to these processes.
It is not checked whether the processes actually terminate (no
"wait" for them); an appropriate exception will be raised.
In the case that it is not even possible to perform these cleanup
actions, the exception Shell_sys.Fatal_error
will be raised.
When the function raises an exception other than Subprocess_error
,
a serious error condition has happened, and it is recommended
to exit the program as soon as possible.
true
, exit codes other than 0 of the
subprocesses are ignored. This does not apply to signals, however.
By default false
.
Same_as_caller
.
Looks at the error codes of the job, and raises
Subprocess_error
when there is an error that cannot be ignored.
As error conditions are considered non-zero exit codes of any
called processes, or signals terminating any of the called processes.
true
, exit codes other than 0 of the
subprocesses are ignored. This does not apply to signals, however.
By default false
.
Arranges a redirection such that writing to src
or reading from src
will actually write to target
or read from target
(i.e., the target
descriptor is duplicated and replaces
the src
descriptor just before the process is launched.)
Note that assignments work only if the descriptors are shared
with the called process, so they must also be contained in the
descriptors
list of command
or cmd
. Furthermore, the
close-on-exec flag must not be set.
Same as assign
, but infix notation. For example,
stdout >& stderr
creates an assignment such that all output
to stdout is redirected to stderr.
f >& g
is the same as assign ~src:f target:g
. It should
be used for output assignments (as in the Bourne shell).
Same as assign
, but infix notation. For example,
stdin <& f
creates an assignment such that the called process
reads from the open file descriptor f
.
f <& g
is the same as assign ~src:f target:g
. It should
be used for input assignments (as in the Bourne shell).
Returns the target and the source of the assignment as
pair of descriptors (target,src)
.
Creates a producer taking the data from a string s
. After these data
are sent, the pipeline is closed.
s
where the data slice to transfer begins.
By default 0
.
pos
to the end of the
string are taken.
Creates a producer taking the data from a stream of strings. After the data are sent, the pipeline is closed.
Creates a producer taking the data from a function. See
Shell_sys.add_producer for the meaning of the producer
function.
Creates a producer taking the data from the file whose name is passed to this function.
Creates a producer taking the data from the file descriptor passed to this function.
Creates a consumer writing the data by calling a function. See
Shell_sys.add_consumer for the meaning of the consumer
function.
Creates a consumer writing the data into the file whose name is
passed to this function. Unless append
is given, the file is
truncated and overwritten. If append
is true
, the data are
appended to the file. By default, append
is false
.
Creates a consumer redirecting the data to the file descriptor
The following examples show toploop sessions using Shell
.
Call the command "ls" without redirection:
# call [ command "ls" ];;
IDEAS s1.ml~ shell.mli~ shell_sys.ml~ unix_exts.ml
META shell.a shell.ml~ shell_sys.o unix_exts.mli
Makefile shell.cma shell_sys.cmi t unix_exts.mli~
Makefile~ shell.cmi shell_sys.cmo testjob unix_exts.ml~
depend shell.cmo shell_sys.cmx testjob~ unix_exts.o
libshell.a shell.cmxa shell_sys.ml unix_exts.cmi unix_exts_c.c
log shell.ml shell_sys.mli unix_exts.cmo unix_exts_c.c~
s1.ml shell.mli shell_sys.mli~ unix_exts.cmx unix_exts_c.o
\- : unit = ()
The output of "ls" is collected in the buffer b
:
# let b = Buffer.create 10;;
val b : Buffer.t = <abstr>
# call ~stdout:(to_buffer b) [ command "ls" ];;
\- : unit = ()
# Buffer.contents b;;
\- : string =
"IDEAS\nMETA\nMakefile\nMakefile~\ndepend\n..."
Because "/a" does not exist, "ls" will fail. The command writes the message to stderr (not redirected here), and returns with an exit code of 1, triggering an exception:
# call [ command ~arguments:[| "/a" |] "ls" ];;
/bin/ls: /a: No such file or directory
Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
Here, the message written to stderr is collected in b
:
# Buffer.clear b;;
\- : unit = ()
# call ~stderr:(to_buffer b) [ command ~arguments:[| "/a" |] "ls" ];;
Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
# Buffer.contents b;;
\- : string = "/bin/ls: /a: No such file or directory\n"
Here, the output of "cat" becomes the input of "sort":
# call [ command ~arguments:[|"META"|] "cat"; command "sort" ];;
archive(byte) = "shell.cma"
archive(native) = "shell.cmxa"
description = "Unix shell functions"
linkopts = "-cclib -lshell"
requires = "unix str"
version = "0.0"
\- : unit = ()
The same, but the output of "sort" is collected in the buffer b
:
# Buffer.clear b;;
\- : unit = ()
# call ~stdout:(to_buffer b) [ command ~arguments:[|"META"|] "cat"; command "sort" ];;
\- : unit = ()
# Buffer.contents b;;
\- : string =
"archive(byte) = \"shell.cma\"\narchive(native) = \"shell.cmxa\"\ndescription = \"Unix shell functions\"\nlinkopts = \"-cclib -lshell\"\nrequires = \"unix str\"\nversion = \"0.0\"\n"
The contents of the string s
are written to the input of "sort":
# let s = "f\na\nd\nc\n";;
val s : string = "f\na\nd\nc\n"
# call ~stdin:(from_string s) [ command "sort" ];;
a
c
d
f
\- : unit = ()
It is possible to have several redirections. Here, the string s
is
sorted by "sort", and the output is collected in the buffer b
:
# Buffer.clear b;;
\- : unit = ()
# call ~stdout:(to_buffer b) ~stdin:(from_string s) [ command "sort" ];;
\- : unit = ()
# Buffer.contents b;;
\- : string = "a\nc\nd\nf\n"
Here, the output and errors of "ls" are both collected in the buffer
b
:
# Buffer.clear b;;
\- : unit = ()
# call ~stdout:(to_buffer b)
[ command
~assignments:[ stderr >& stdout ]
~arguments:[| "/a" |]
"ls" ];;
Uncaught exception: Shell.Subprocess_error ["/bin/ls", Unix.WEXITED 1].
# Buffer.contents b;;
\- : string = "/bin/ls: /a: No such file or directory\n"
Of course, all features can be combined arbitrarily.
Note that error reporting is better than in a traditional shell, because the exit codes of all started commands are returned. (Shells usually only return the exit code of the last command of a pipeline.)
For non-standard pipelines, you can also use the functions in Shell_sys. "call" is a simple concatenation of Shell_sys invocations.