posixtask
SCRIPT
,
PROPERTY
,
VALUE

The posixtask statement executes a POSIX shell script in the background using NSTask.


Parameters

This statement has three parameters:

script – specifies the shell script code to be run.

property – an optional script. See below for detailed descriptions of the different properties that can be specified. Properties can be specified in either upper or lower case, for example SCOPE or scope.

value – the value for the property specified by the previous parameter.


Description

This statement executes a POSIX shell script in the background using NSTask. Unlike the posixscript function, this statement doesn’t wait for the script to finish before continuing. The script will run in the background and the user can do other things while the script is running.

Although the script runs in the background, it’s not completely independent of Panorama. The script can send it’s output to Panorama variables, and you can specify Panorama code that will run automatically when the script is finished.

Shell Script

The first parameter used with this statement must always be the shell script you want to run. This code consists of one or more POSIX shell commands, like this command that lists the contents of the current directory:

posixtask "ls -l"

You can run two or more shell commands by joining them with a semicolon. This example lists the contents of the Library directory.

posixtask "cd ~/Library;ls -l"

See Standard Output below to learn how to access the output from your shell commands.

There are hundreds of different shell commands available. Describing all of these commands is beyond the scope of this documentation, but there are many books available, as well as numerous web resources.

Note: Unlike the shellscript( function, no substitutions are performed on the script code, so you cannot embed Panorama variables and formulas into the code (of course you can use a formula to build the code any way you want).

Post Script Actions

You may want to run some additional Panorama code after the shell script is finished. To do that, use the "CODE" option. This example will delete all files within the SecretProject folder, then display a notification telling you that the files have been deleted.

posixtask "cd ~/Secret\ Project;rm -r *","code",{nsnotify "Secret Project Shredded!"}

Note: Be VERY careful with the rm shell command – it’s super dangerous.

By default, you cannot rely on Panorama being in a certain state when the code begins. For example, you should not rely on a particular window or database being active when the shell script finishes. In fact, the database that started running the script might not even be open by the time the script finishes running. So make sure you code defensively and check the state you perform any action that depends on that state.

Standard Output

UNIX shell scripts send all of there output to a portal called standard output. By default, the posixtask statement sends standard output to a local variable named _stdOut. You can access this local variable in the code you have set up to run after the script finishes. Here is a simple example that displays the contents of the Library directory in a dialog (using the displaydata statement).

posixtask "cd ~/Library;ls -l","code",{displaydata _stdOut}

If you wish, you can use the stdout option to customize the name of the variable used for standard output.

posixtask "cd ~/Library;ls -l",
    "stdout","libraryContents",
    "code",{displaydata libraryContents}

When you customize the name of the variable like this, Panorama will create the variable as a fileglobal variable instead of as a local variable. This allows you to display the variable in a form object. As the shell script generates output, Panorama will automatically update the form object as needed. If you are simply displaying the output in a form, you may not even need any post script code – all you need to do is route the output into a variable.

posixtask "cd ~/Library;ls -l","stdout","libraryContents"

The posixtask statement appends the standard output to the specified variable. This means that if you run posixtask more than once, the variable will contain the appended output of each run of the script. If you want only the most recent output you need to clear out the task before running the shell script, like this:

letfileglobal libraryContents = ""
posixtask "cd ~/Library;ls -l","stdout","libraryContents"

If necessary, you can use the scope option to explicitly specify the type of variable that will be generated. The available scopes are local, database (fileglobal), window (windowglobal) and global. You can abbreviate these options with only the first letter (l, d, w or g). Here is an example that routes the output to a local variable named libraryContents.

posixtask "cd ~/Library;ls -l",
    "scope","local",
    "stdout","libraryContents",
    "code",{displaydata libraryContents}

Note: If you plan to display the variable in a form, you should use the database option. Otherwise the variable will not update properly as output is generated.

Filtering Standard Output

This statement normally takes the text generated by the shell script and sends it directly to the variable you have specified (or _StdOut if none was specified), without any modification. However, it is also possible to set up a formula to pre-filter the text, before it is sent to the variable. This can be especially useful if you are immediately displaying the text in a form.

The filter is set up with the linefilter option. It’s called linefilter because the text is filtered on a line by line basis. The option is a formula that takes the original text from the shell script (which is passed by the import() function) and transforms it into a modified value. This example converts the text to all upper case.

posixtask "cd ~/Library;ls -l",
    "stdout","libraryContents",
    "linefilter,{upper(import()}

This example checks to see if the 4th word in each line contains admin. If it does, the line is pass through, if not, nothing is passed. This takes advantage of the fact that if nothing is passed, the line is not passed through to the variable at all, so this has the effect of only showing files that are owned by admin.

posixtask("cd ~/Library;ls -l",
    "stdout","libraryContents",
    "linefilter,{?(nthword(onewhitespace(import()),4) contains "admin",import(),"")}

Standard Error

In addition to sending text to standard output, UNIX also has a standard error portal. By default, the posixtask statement sends standard error output to a local variable named _stdError. This works just like ths _stdOut variable, except that it will contain error information. You can use the stderror option to customize the name of the variable used for standard error.

posixtask "cd ~/Library;ls -l",
    "scope","local",
    "stdout","libraryContents",
    "stderror","libraryError",
    "code",|||if libraryError<>""
       message libraryError
    else
       displaydata libraryContents
    endif
    |||

Note that the scope option controls both stdout and stderror - you cannot set the scope of these separately.

Script Task Identifier

If you want your Panorama code to interact with the script after it is launched, you must assign it an identifier. You can use the task or identifier option to assign a task identifier.

posixtask "cd ~/Library;ls -l","task","Library Catalog"

The task ID must be unique, you cannot run two tasks with the same name at the same time. If you do, the posixtask statement will fail with an error.

To get a list of all the currently running posix tasks, use the info(“posixtasks”) function. This will return a carriage return delimited list of all posix tasks that are currently running in the background.

To stop a specific posix task right now, before it finishes normally, use the stopposixtask statement.

stopposixtask "Library Catalog"

Using WaitForTask with PosixTask

Earlier you learned how to use the code option to run Panorama code after the shell script finishes. There’s a second way to do this, using the waitfortask statement.

To use this technique you must set up a task identifier (as described in the previous section). Then you can follow the posixtask statemint with a waitfortask statement. The code will pause and wait for the shell script to finish in the background, then continue with the rest of the code. Since the shell script is running in the background, you can do other things in the meantime while this is happening, which can be very useful if the shell script takes minutes to finish.

posixtask "cd ~/Library;ls -l","task","Library Catalog"
waitfortask "Library Catalog"
displaydata _stdOut

You may think that the example above is the same as this example:

displaydata posixscript("cd ~/Library;ls -l")

The difference is that the first example allows other tasks to be performed while the shell script is running. In the second example everything stops until the script is finished - Panorama can’t do anything else until the script is finished.

Note: If you’re planning to use the waitfortask technique, you might want to switch over to the posixtask( function instead of the posixtask statement. This function is designed to make using waitfortask super simple, as shown here.

waitfortask posixtask("cd ~/Library;ls -l")
displaydata _stdOut

Advanced: It’s possible to combine the code option with the waitfortask technique. If you do, you must add the code resumeaftertask «taskid» at the end of your code:

posixtask "cd ~/Library;ls -l",
    "task","Library Catalog",
    "code",|||nsnotify "Catalog done" resumeaftertask «taskid»|||
waitfortask "Library Catalog"
displaydata _stdOut

The example above is rather silly, there’s really no reason why the nsnotify statement couldn’t be put after the waitfortask statement. We couldn’t think of a more realistic example of this technique, so probably you’ll never need to use this technique. But if you ever do, now you know how.


See Also


History

VersionStatusNotes
10.2NewNew in this version.