Process Utilities

To use the bindings from this module:

(import :std/misc/process)

run-process

(run-process cmd
             [coprocess: ...]
             [check-status: #t]
             [environment: #f]
             [directory: #f]
             [stdin-redirection: #t]
             [stdout-redirection: #t]
             [stderr-redirection: #f]
             [pseudo-terminal: #f]
             [show-console: ...]) -> any | error

  cmd                := list of strings, [path . arguments]
  coprocess          := procedure interacting with process
  check-status       := procedure or truth value
  environment        := list of strings, ["VAR=VALUE" ...]
  directory          := dir, working directory
  stdin-redirection  := boolean, standard input redirection
  stdout-redirection := boolean, standard output redirection
  stderr-redirection := boolean, standard error redirection
  pseudo-terminal    := boolean, terminal or pipes (UNIX)
  show-console       := boolean, show or hide console (Windows)

Synchronously runs cmd in a subprocess, where cmd is expected to be a list consisting of a path to an executable on the filesystem and its arguments.

The following keyword settings are available:

  • coprocess: A procedure that specifies how to interact with the process, which it receives as an argument, and what should be returned from run-process. Defaults to reading the whole output as a string via std/misc/ports#read-all-as-string if either stdout-redirection or stderr-redirection is true, otherwise to void.
  • check-status: Declares how to handle the exit status of the process upon termination. If a procedure is provided, then it will be called with the process' exit status and a list of process creation arguments. If check-status is #t, the default, then the exit status is checked and an error is raised in case it differs from 0. Lastly, the exit status is simply ignored, when check-status is #f.
  • environment: Indicates the set of environment variable bindings that the process receives. Each element of the list is a string of the form VAR=VALUE, where VAR is the name of the variable and VALUE is its binding. When environment is #f, which is the default, the process inherits the environment variable bindings of the Scheme program.
  • directory: Sets the working directory of the process. When it's #f, the default, then the process uses the value of (current-directory).
  • stdin-redirection: Indicates how the standard input of the process is redirected. The default #t will redirect the standard input from the process-port (i.e. what is written to the process-port will be available on the standard input). #f will leave the standard input as-is, which typically results in input coming from the console.
  • stdout-redirection: Indicates how the standard output of the process is redirected. The default #t will redirect the standard output to the process-port (i.e. all output to standard output can be read from the process-port). #f will leave the standard output as-is, which typically results in the output going to the console.
  • stderr-redirection: Indicates how the standard error of the process is redirected. #t will redirect the standard error to the process-port (i.e. all output to standard error can be read from the process-port). The default #f will leave the standard error as-is, which typically results in error messages being output to the console.
  • pseudo-terminal: Applies to UNIX. It indicates what type of device will be bound to the process’ standard input and standard output. #t will use a pseudo-terminal device (this is a device that behaves like a tty device even though there is no real terminal or user directly involved). The default #f will use a pair of pipes. The difference is important for programs which behave differently when they are used interactively, for example shells.
  • show-console: Applies to Microsoft Windows. It controls whether the process’ console window will be hidden or visible. The default value of this setting is true if any of the port redirection option is false.

More information can be found in section 17.7.2 Process devices of the Gambit manual.

Examples:

> (run-process ["date" "--utc"] coprocess: read-line)
"Tue 21 May 2019 12:22:20 PM UTC"

> (run-process ["/usr/bin/ls"])
"desktop\ndev\ndocuments\ndownloads\nmusic\nnotes\npictures\nvideos\n"

> (import :std/misc/ports)
> (run-process ["ls" "-l"] coprocess: read-all-as-lines)
("drwxr-xr-x.  2 user user  4096 Mar 26 13:26 desktop"
 "drwxr-xr-x.  8 user user  4096 May 13 14:28 dev"
 "drwxr-xr-x. 12 user user 12288 May 19 17:26 documents"
 "drwxr-xr-x.  2 user user  4096 May 20 10:13 downloads"
 "drwxrwxr-x.  8 user user  4096 May  1 15:13 music"
 "drwxr-xr-x.  2 user user  4096 May 21 10:53 notes"
 "drwxr-xr-x.  9 user user  4096 Apr 30 19:08 pictures"
 "drwxrwxr-x.  3 user user 12288 May 21 09:41 videos")


> (def (word-count path)
    (run-process ["wc" path]
                 coprocess: (lambda (process)
                              (with ([l w c] (filter number? (read-all process)))
                                (displayln "lines: " l "\nwords: " w "\nchars: " c)))))
> (word-count "/home/user/dev/scheme/nums.txt")
lines: 5
words: 5
chars: 10

run-process/batch

(run-process/batch cmd) -> void

  cmd := list of strings, [path . arguments]

Runs a batch process with stdin closed, and both stdout and stderr on the current console. Same as (run-process cmd coprocess: close-output-port stdout-redirection: #f).

Examples:

> (def files ["file1.txt" "file2.txt" "file3.txt"])
> (for-each (lambda (file) (run-process/batch ["touch" file])) files)
> (run-process/batch (append ["zip" "big.zip"] files))
adding: file1.txt (stored 0%)
adding: file2.txt (stored 0%)
adding: file3.txt (stored 0%)

invoke

(invoke program args
   [stdout-redirection: #f]
   [stderr-redirection: #f]
   [stdin-redirection: #f]
   [coprocess: ...]
   [check-status: #t]
   [environment: #f]
   [directory: #f]
   [show-console: ...]

Invoke a program with arguments args, in a way very similar to run-process above, except that the program is specified separately from the arguments, and the defaults for standard port redirections are different.

Examples:

> (invoke "date" ["--utc"] stdout-redirection: #t coprocess: read-line)

filter-process

(filter-with-process command writer reader
   [directory: #f]
   [environment: #f])

Invoke a Unix command to filter some data, wherein the writer procedure takes an output port as argument and writes pre-filtered data to the port, the command then filters the data, reading it from its standard input, processing it and writing the filtered result to its standard output, and the reader procedure takes an input port as argument and reads the filtered data from it. The optional keyword arguments directory: and environment: are passed to run-process.

Examples:

> (check (filter-with-process ["sh" "-c" "echo BEGIN ; cat ; echo END"]
           (lambda (proc) (display "ab\ncd\nef\n" proc))
           read-all-as-lines)
("BEGIN" "ab" "cd" "ef" "END")