Manual:BoxedCommand/cs

BoxedCommand is a part of the Shellbox library that allows for transparently executing shell commands either locally (like normal) or on a remote server running the Shellbox server component. This page covers how to use it inside MediaWiki, as it mostly replaces the Shell framework introduced in 1.30.

A lightly edited and annotated example from Extension:SyntaxHighlight:

Přehled
BoxedCommand allows executing commands in a sandbox, including possibly on an entirely different server. Commands are executed in an empty temporary directory, so any files need to be copied in using the BoxedCommand functions. Regardless of what sandboxing method sysadmins have configured, BoxedCommand aims to transparently make things just work.

Getting a BoxedCommand
A ShellCommandFactory can be obtained from MediaWikiServices, then call. The argument to  should be the name of the Shellbox configured in. Typically each extension will use its own name here, unless there is an advantage to further isolate commands from each other by using separate Shellboxes.

There are various additional hardening measures that can be set at this point such as enabling firejail's default seccomp filter or disabling network access. They will only be used if the sandboxing system supports them.

Finally, set a route name (TODO: this doesn't really do anything).

It is common for extensions to have a static function named  that returns a configured   object:

Constructing the command
Parameters can be passed by calling. These will be automatically escaped, raw parameters can be passed by using. The utility function  allows for escaping user-input before passing it to. Environment variables can be passed as an array to.

If you want stderr to be merged with stdout, call.

Many commands deal with files, so Shellbox makes it convenient to do so with the following helper functions:

Standard input can be passed by using.
 * - Creates a file with the name  with the contents   before execution
 * - Same as, but reads the contents from
 * - If it exists, save the file with name  into memory after execution
 * - Same as, except it saves the contents to
 * - Similar to, except it saves everything that matches the glob of
 * - Similar to, except all files are saved into the directory

Using a shell wrapper
It is common to run external commands in pipeline. For example, Score will run abc2ly to convert ABC markup to LilyPond and then generate images using lilypond from the LilyPond markup. Traditionally this would have been two Shell::command invocations, one for abc2ly, then another for lilypond using the output from abc2ly. However, this can cause unnecessary overhead when using a remote Shellbox server, since file contents need to be sent back and forth as HTTP requests unnecessarily. One practice is to use a shell script to run multiple commands, possibly interpreting the output.

Take a look at Score's scripts/ directory for examples on how this works.

Interpreting the result
Calling  will give you a   object. The following methods are useful:


 * : null if includeStderr was used
 * : if an output file was registered with, get that file's contents
 * : whether that file was received
 * : if an output file was registered with, get that file's contents
 * : whether that file was received

Examples

 * Extension:Score probably has the most complex uses of Shellbox's functionality, including using shell wrappers and output globbing. See the conversion patch.
 * Extension:SyntaxHighlight has very simple uses. See the conversion patch.