TurboScript

Turbo command processor can act as an automated builder by reading instructions from a .me file to create a new image. Turbo Shell can act as an interactive interpreter of TurboScript.

A .me script is a text file containing a set of instructions that the Turbo command processor or the Turbo Shell follows to create a container. In Turbo command processor, at the end of the script, a new image is created from the container and the container is deleted.

The syntax of a TurboScript generally follows the pattern:

instruction <arg 1> <arg 2> ...
instruction <arg 1> <arg 2> ...
instruction <arg 1> <arg 2> ...

The script is read and executed top-to-bottom and is not case-sensitive.

All scripts have an implicit commit at the end of the script. After the last instruction in the script, it executes turbo commit on the container. If a name was not provided to the build command (via the -n or --name flag) then the new image will be created with its ID as its name.

Syntax Rules

  1. TurboScript are line-delimited and must only contain 1 instruction per line. Line continuation is not supported.
  2. All lines must follow the general structure: instruction <args>
  3. Inline comments are not supported. Comments must be applied at the beginning of a line and are applied to the entire line.

Comments

Comments are denoted by the # character.

# This is a comment

Comments cannot be made inline with a command. Comments must be specified at the beginning of a line.

# This is a valid comment

layer nodejs/nodejs  # This is not a valid comment

Conditions

Any TurboScript instruction can have an optional when clause at the end of the line to specify the conditions which must be met before the instruction will be executed. The general form is instruction when expression.

cmd "echo This is Windows7" when host has os:Windows7

These are the currently supported expressions:

  • host has architecture:x86
  • host has architecture:x64
  • host has os:WindowsXP
  • host has os:Windows2003
  • host has os:WindowsVista
  • host has os:Windows2008
  • host has os:Windows7
  • host has os:Windows2008r2
  • host has os:Windows8
  • host has os:Windows2012
  • host has os:Windows8.1
  • host has os:Windows2012r2
  • host has os:Windows10

Note that client OSes are not differentiated from server OSes so "WindowsXP" is equivalent to "Windows2003", etc.

Expressions can be combined with AND, OR, NOT, and parenthesis.

layer clean when (not host has os:windows7 and not host has os:windows8.1)
layer spoonbrew/iis7-base when host has os:windows7
layer spoonbrew/iis8-base when host has os:windows8.1

Command Reference

batch

The batch instruction is used for joining multiple commands of the same type in TurboScript.

batch <command>
	<line 1>
	<line 2>
	<...>

If <command> is cmd or empty then all following indented lines will be put into a single batch file. Otherwise, these lines will be turned into separate commands.

The first non-indented line terminates the batch section and resumes normal command processing.

Example

You can use the batch instruction to execute a series of commands that share their state.

# Create a new directory with a text file inside of it.
batch cmd
  mkdir c:\new_folder
  cd c:\new_folder
  echo text content > text_file.txt
# Set several environment variables
batch env
  var1="value 1"
  var2="value 2"
  var3="value 3"

cmd

The cmd instruction is used to run a command in the container.

The instruction has three forms:

# Execute the application directly
cmd ("executable", "param1", "param2") 

# Interpret the command by cmd.exe, defaults to using cmd.exe /c
cmd <command> <param1> <param2>

# Pass parameters to the image's startup file
cmd <param1> <param2>

Please note that turbo.exe always runs outside of the container on the host even if passed as cmd parameter.

Form 1: As an Executable

If you wish to launch an executable and optionally supply parameters to that executable, you must express the desired executable as a tuple of strings and give the full path to the executable (unless it is on the local system or container's PATH). Using this syntax, parameters are passed directly to the executable.

# Open foo.txt in notepad
cmd ("c:\windows\system32\notepad.exe", "c:\users\user\desktop\foo.txt")

Form 2: As a Shell Command

Using this syntax, each command is executed in its own command prompt -- a new command prompt being spawned for each instruction. Any stateful commands (cd, for example), must be chained to other commands with an ampersand to have their desired effect.

For example, to read C:\spoon\text-file.txt:

# Does not work
cmd cd C:\turbo
cmd more text-file.txt

# Works!
cmd cd C:\turbo & more text-file.txt

Note: If you wish to use cd functionality in your script, consider using the WORKDIR instruction.

Form 3: As Parameters

Using this syntax, the parameters are sent to the default startup file in the base image. If multiple base images are specified, the startup file from last image listed will be used.

copy

The copy instruction is used to copy a file or directory from a TurboScript or an XAPPL configuration directory.

copy <source> <destination>

# There is also an alias:
cp <source> <destination>

The source path may point to an inner subdirectory of the one mentioned above, but must not point above it. This restriction does not apply to the Turbo Shell.

The destination may either be an absolute path, or a relative path. In the latter case, the file is copied into a location relative to the current working directory.

Examples:

copy turbo.me .
copy setup\installer.msi C:\setup\
cp app-1.2.3.4.msi setup\installer.msi

disable

The disable instruction disables the specified VM setting inside the container.

disable <vm setting>

Only one setting can be disabled per instruction. To disable multiple VM settings, use multiple disable instructions.

See VM Settings section for details on available options.

echo

The echo instruction simply echoes a string argument.

echo "Hello, world"

enable

The enable instruction enables the specified VM setting inside the container.

enable <vm setting>

Only one setting can be enabled per instruction. To enable multiple VM settings, use multiple enable instructions.

See VM Settings section for details on available options.

env

The env instruction creates a new environment variable inside the working container.

env <name>="<value>"

This environment variable will be persisted to the output image by the build command.

Only one environment variable can be added per env instruction. To add multiple environment variables to the working container, use multiple env instructions. Well known system paths like C:\Windows\System32 will be replaced by a variable that will be converted at runtime to the appropriate path for the execution environment.

When multiple environment variables with the same name are defined in set of images used to run a container, the value from last image is used. For two environment variables, PATH and PATHEXT, special behavior is defined. All values are concatenated together using the semicolon as the joining character. The value from the last image appears first and the host value is at the end.

env foo="bar"
env path="c:\path to executables\"

In the container these variables will have the following values:

foo="bar"
path="c:\path to executables;C:\WINDOWS\system32;C:\WINDOWS"

Variables can be reset within the same TurboScript by repeating the env command for the same variable name. The last value will be stored in the image. To remove the variable from the image, use the following command:

env foo=

Please note that if variable foo is also defined in one of layer images and final image is created with --no-base flag then it will be still loaded into containers created with it.

Environment variables can be overridden in a container by explicitly setting the variable to a new value or when an application or installer sets a new value.

hosts

The hosts instruction modifies host name resolution within a container.

hosts <ip address|local host name> <host name>

The syntax for this command matches that of the hosts file in Windows where the first parameter is a host name or IP address and the second parameter is the name to resolve the host name/IP address to.

This setting is persisted to the output image so that any containers created from that image will have these DNS settings applied.

# Make the loopback ip resolve to mydomain.net
hosts 127.0.0.1 mydomain.net

# Redirect requests to google.com to localhost
hosts localhost google.com

import

The import instruction imports content of specified file into current image.

import <import type> <path to file>

Supported import types:

  • svm - turbo image file
  • msi - msi file
  • thinapp - thinapp configuration file

isolate

The isolate instruction sets the isolation setting of a named object.

isolate "<objectType>:<name or path>" <isolation>

Supported object types:

  • kernel - kernel objects (full isolation only)
  • file - file system
  • window - window objects

Supported isolation types:

  • full - Enable read and write isolation.
  • cow - Copy on write enables write isolation, allows read from host operating system.
  • merge - Reads and writes using host operating system if available.

layer

The layer instruction creates a new container and sets the base image(s) for that container.

layer <image>

The layer instruction can be omitted if a clean base image is desired. Multiple layer instructions are additive.

Multiple images can be specified in a single layer instruction by separating each image with a comma or space. If the same file, registry entry, or environment variable exists in multiple images added via the layer instruction, then the one from whichever image was specified last will win the conflict and be used in the virtual environment. Virtual machine settings are taken from the last image specified in the layer instruction.

Due to this "layering" approach, it is a good practice to specify images with newer versions of applications or libraries after images with older versions.

layer <image 1> <image 2>

# Start container with git and node.js
layer git/git nodejs/nodejs

Note: To initialize an empty container, use the clean image

layer clean

meta

The meta instruction sets the metadata value for the output image.

meta <name>="<value>"

Standard metadata properties are listed below:

  • Title
  • Description
  • Publisher
  • Website
  • Version

Additionally, metadata can be used to control namespace, name, and tag of the output image.

Custom metadata can be specified using other name-value pairs.

# Add a title
meta title="application name"

meta namespace="organization"
meta name="application"
meta tag="0.1"

# Add custom metadata
meta internal-name="new-name"

require

The require instruction defines a runtime requirement which should be checked and enforced before the output image is launched. If the requirement cannot be satisfied, the image will not be run.

require <requirement>

The following requirements are supported:

  • privilege:admin
  • architecture:x86
  • architecture:x64
  • minosver:6.1.7601

Example:

# Fail if image is not launched on 64-bit machine
require architecture:x64

requires

The requires instruction defines a build time requirement which should be enforced immediately. If the requirement cannot be satisfied, the build will fail.

requires <requirement>

See the require instruction for the list of supported requirements.

Example:

# Run TurboScript in elevated command prompt
requires privilege:admin

route

The route instruction adds a route mapping.

route add <route-specifiation>
route block <route-specifiation>

The route add and route block instructions are equivalent to --route-add and --route-block flags to the turbo new command, respectively. They use the same syntax for route-specifiation.

Examples:

# Block all tcp ports
route block tcp

# Map container port 80 to local port 8080
route add tcp://80:8080

# Block access to IP address 192.168.1.123
route block ip://192.168.1.123

setworkdir

The setworkdir instruction sets the working directory which is used by the output image at runtime.

setworkdir <path>

If a setworkdir command is not specified then all commands will be executed from the same working directory as the native command prompt. The <path> specified must exist on host or be created within the container.

shellextension

The shellextension instruction is used to enable a shell extension in the output image.

shellextension <context menu handler CLSID> <extension dll> <executable>

If an image contains shell extensions, the MergeStartupDir VM setting should be enabled to allow operations on file system items using the context menu in Windows Explorer.

Examples:

enable MergeStartupDir

# shellextension <context menu handler CLSID> <extension dll> <executable>
shellextension "{B41DB860-64E4-11D2-9906-E49FADC173CA}" "@PROGRAMFILES@\WinRAR\rarext.dll" "@PROGRAMFILESX86@\WinRAR\winrar.exe"
shellextension "{B41DB860-8EE4-11D2-9906-E49FADC173CA}" "@PROGRAMFILESX86@\WinRAR\rarext.dll" "@PROGRAMFILESX86@\WinRAR\winrar.exe"

Values required to enable the shell extension were copied from the following locations in the system registry:

Parameter Value Registry path

context menu handler CLSID

{B41DB860-64E4-11D2-9906-E49FADC173CA}

@HKCR@\WinRAR32\shellex\ContextMenuHandlers

extension dll

@HKCR@\CLSID\{B41DB860-64E4-11D2-9906-E49FADC173CA}\InProcServer32

@PROGRAMFILES@\WinRAR\rarext.dll

@PROGRAMFILESX86@\WinRAR\rarext.dll

executable

@HKCR@\WinRAR\shell\open\command

@PROGRAMFILES@\WinRAR\rarext.dll

@PROGRAMFILESX86@\WinRAR\rarext.dll

startup file

The startup file instruction is used to specify the startup file or script to run when a new container is created from this image (using turbo run).

The instruction has multiple forms:

  1. startup file <command> <param1> <param2> (executes the application directly)
  2. startup file ("executable", "param1", "param2") (executes the application directly)
  3. startup file [("executable1", "param1", "param2"), ("executable2", "param1", "param2"), ...] (executes the list of applications directly)
  4. startup file trigger=("executable", "param1", "param2") (assigns a trigger name to a startup file)
  5. startup file trigger=[("executable1", "param1", "param2"), ("executable2", "param1", "param2"), ...] (assigns a trigger name to a collection of startup files)

This instruction is only applied to the output image and does not affect the intermediate container.

If startup file is not specified then the startup file setting is inherited from last image listed in the layer command. Well known system paths like C:\Windows\System32 will be replaced by a variable that will be converted at runtime to the appropriate path for the execution environment.

As an Executable

If you wish to launch a process from an executable and optionally supply parameters to that executable, you must express the desired executable as a tuple of strings and give the full path to the executable (unless it is on the local system or container's PATH). Using this syntax, parameters are passed directly to the executable.

# "clone" and "https://github.com/turboapps/docs" are passed to git.exe
startup file ("git.exe", "clone", "https://github.com/turboapps/docs")

As a Shell Command

You may also launch a process using basic command prompt syntax. To open a Command Prompt window with a message:

# Hello world is passed to the 'echo' shell command
startup file cmd.exe /k echo hello world

Multiple Startup Files

It is possible to specify multiple startup files which will be launched simultaneously using the array syntax.

# set multiple default startup files for "test-shotgun" image
startup file [("c:\windows\system32\notepad.exe"), ("c:\windows\regedit.exe")]

# launch both notepad and regedit
turbo run test-shotgun

Startup File Triggers

A startup file, or collection of startup files, can be assigned a trigger name. When this is done, the startup file(s) specified will only launch when using turbo run with the --trigger flag. This can be useful when setting up shortcuts to multiple applications inside the same image.

# in turbo.me file to create "test-trigger" image...
startup file [("c:\windows\system32\notepad.exe"), ("c:\windows\regedit.exe")]
startup file doc=[("c:\windows\system32\notepad.exe", "c:\doc\welcome.txt"), ("c:\windows\system32\notepad.exe", "c:\doc\howto.txt")]


# from command-prompt...

# launch both notepad and regedit are launched
> turbo run test-trigger

# launch welcome.txt and howto.txt in notepad
> turbo run test-trigger --trigger=doc

sync

The sync instruction enables or disables synchronization for a specific path. By default all directories except the @LOCALAPPDATA@ directories are synchronized. The sync instruction is applied recursively to all sub directories.

sync enable|diable "<path>"

Example

# Disable synchronization for the app-settings directory
sync disable C:\apps-settings

# Enable synchronization for the sub directory
sync enable C:\app-settings\important-settings

using

The using instruction adds an additional, temporary image(s) for that container.

using <image>

Multiple images can be specified in a single using instruction by separating each image with a comma or space. If the same file, registry entry, or environment variable exists in multiple images added via the using instruction, then the one from whichever image was specified last will win the conflict and be used in the virtual environment. If the same file, registry entry, or environment variable exists in two images, one added via the using instruction and one added via the using instruction, then the one in the using image will win the conflict. Virtual machine settings are taken from the last image specified in the using instruction.

Due to this "layering" approach, it is a good practice to specify images with newer versions of applications or libraries after images with older versions.

If the next instruction after using is indented, a scope is defined and the images specified in the using instruction are available only in this scope.

using python
  cmd python --version

cmd python --version || echo Python not available!

Note: Images added with using keyword are NOT included in final image

var

The var instruction sets value of a variable.

var <name>="<value>"

The value can be an expression involving strings and other variables.

var foo="bar"
var myvar=foo + "baz"

A few special variables are implicitly defined:

  • last - Output of last executed command
  • spoonversion - Version string of the binary
  • year - Current year
  • month - Current month number
  • day - Curent day number
  • hour - Current hour
  • minute - Current minute
  • second - Current second
  • dateiso - Current date in yyyyMMdd format
  • date - Current date
  • time - Current time

For programs started in the build container, variables are available as environment variables.

var version = ""
using python
  cmd python getLatestVersion.py
  var version = last

using wget
  cmd wget https://example.com/application-%version%.exe

meta name = "application"
meta tag = version

workdir

The workdir instruction sets the working directory inside the container.

workdir <path>

If a workdir command is not specified then all commands will be executed from the same working directory as the native command prompt. The <path> specified must exist on host or be created within the container before this instruction.

Unlike cmd cd <path>, the workdir instruction will persist the working directory to all subsequent instructions.

Questions? Projects? Talk to us.