eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'OSProcess':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: OSProcess


Inheritance:

   Object
   |
   +--OSProcess
      |
      +--OSProcess::RemoteOSProcess

Package:
stx:libbasic
Category:
System-Support
Version:
rev: 1.142 date: 2024/04/23 19:08:27
user: cg
file: OSProcess.st directory: libbasic
module: stx stc-classLibrary: libbasic

Description:


Instances of OSProcess represent operating system processes that can be executed.
(as opposed to Smalltalk processes).
Both local and remote processes are supported.

commandString:
 If command is a String, the commandString is passed to a shell for execution
 - see the description of 'sh -c' in your UNIX manual ('cmd.exe' in your Windows manual).
 Regular input/output redirection and pipes etc. are supported as supported by
 the underlying OS's command interpreter (i.e. some limits apply to MSDOS)

 With an empty command, the shell will read commands from the passed input stream.

 If command is an Array, the first element is the command to be executed,
 and the other elements are the arguments to the command. 
 No shell is invoked in this case. Any redirection or piping can then be done
 by Smalltalk code (including piping through smalltalk streams & filters).


[instance variables:]
    pid         SmallInteger    the process id
    command     String          the command line of the running command.

[class variables:]

copyright

COPYRIGHT (c) 2018 by eXept Software AG All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

class initialization
o  initialize
Backward compatibility: Win32Process is an alias for OSProcess

instance creation
o  command: aCommandString
return an initialized instance to execute aCommandString
in the current directory (for a local process)

o  command: aCommandString directory: aStringOrFilename
return an initialized instance to execute aCommandString
in a given directory (for a local process)

o  new
return an initialized instance for a local process.
Keep track of the new instance (so we can quickly enumerate all of them)

o  onHost: aHost
return an initialized instance for a remote process running on another host

Usage example(s):

     OSProcess onHost:'localhost'
     OSProcess onHost:'exeptn'

     (OSProcess new) command:'ls'
     (OSProcess onHost:'exeptn') command:'ls'

o  programName: executableFile arguments: arrayOfStrings initialEnvironment: stringDictionary
similar to command:, but with separate command and arguments

Usage example(s):

     (self programName:'notepad.exe' arguments:#() initialEnvironment:nil)
        showWindow:true;
        startProcess

queries
o  defaultShellPath

o  isCommandWithNonZeroExitStatusOK: commandString
a heuristic hack: list commands which are known to return a non-zero
exit status even if successful.

if useful, this might be enhanced to use a class variable.
Used to prevent diff-command output from being shown as error

running OS process info
o  getTaskList
get a tasklist (windows) or process list (unix)
Calles the external tasklist or ps command and parses the output

Usage example(s):

     self getTaskList
     self getTaskList select:[:p | (p executableName ? '') includesString:'bridge' caseSensitive:false ]

o  getTaskList: all memory: mem times: times
get a tasklist (windows) or process list (unix)
Calls the external tasklist or ps command and parses the output.
If the argumet 'all' is true, all processes are listed,
if false, only the current user's processes are returned.
The list consists of instances of ProcessListEntry,
which have some protocol in common with OSProcess.
mem controls if the amount of memory is to be included (might be expensive to calculate/gather);
times controls if the cpuTIME is to be included

Usage example(s):

     self getTaskList:false memory:true times:true
     self getTaskList:true memory:true times:true

utilities
o  allInstancesDo: aBlock
return an initialized instance for a local process.
Keep track of the new instance (so we can quickly enumerate all of them)

o  commandStringForProgramName: executableFile arguments: arrayOfStrings
generate a command line string from appending args (possibley quoted) to the exe-name (with spaces)

o  possiblyQuoted: aString
should we quote or escape?

Usage example(s):

     self possiblyQuoted:'foo bar' 
     self possiblyQuoted:'foo\bar'


Instance protocol:

accessing
o  auxInStream

o  auxInStream: aStream
set an auxiliary input stream that will be available to the command as
file descriptor 3

o  auxOutStream

o  auxOutStream: aStream
set an auxiliary output stream that will be available to the command as
file descriptor 4

o  auxStream

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  auxStream: aStream
set an auxiliary input stream that will be available to the command as
file descriptor 3

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  baseCommandString
the base command (without dir-path), as string

o  command
the OS (shell-) command, as string or string-array

o  command: aStringOrArray
set the command to be executed.

If aStringOrArray is a String, the commandString is passed to a shell for execution
- see the description of 'sh -c' in your UNIX manual ('cmd.exe' in your Windows manual).
With an empty command, the shell will read commands from the passed input stream.

If aCommandString is an Array, the first element is the command to be executed,
and the other elements are the arguments to the command.
No shell is invoked in this case.

o  command: commandStringArg directory: stringOrFilenameArg
set the command to be executed and directory, where to execute.
If aStringOrArray is a String, the commandString is passed to a shell for execution
- see the description of 'sh -c' in your UNIX manual ('cmd.exe' in your Windows manual).
If aCommandString is an Array, the first element is the command to be executed,
and the other elements are the arguments to the command. No shell is invoked in this case.

o  command: commandArg directory: directoryArg inStream: inStreamArg outStream: outStreamArg errorStream: errorStreamArg
set the command to be executed & directory, where to execute.
and input/output streams.
See comments in individual setters for more info

o  command: commandArg directory: directoryArg outStream: outStreamArg errorStream: errorStreamArg
set the command to be executed & directory, where to execute.
and output/error streams.
See comments in individual setters for more info

o  command: commandArg environment: environmentArg directory: directoryArg inStream: inStreamArg outStream: outStreamArg errorStream: errorStreamArg
set the command to be executed & directory, where to execute.
and input/output streams.
See comments in individual setters for more info

o  command: commandArg environment: environmentArg directory: directoryArg inStream: inStreamArg outStream: outStreamArg errorStream: errorStreamArg auxInStream: auxInStreamArg auxOutStream: auxOutStreamArg showWindow: showWindowArg lineWise: lineWiseArg
set the command to be executed & directory, where to execute.
and input/output streams.
See comments in individual setters for more info

o  command: commandArg environment: environmentArg directory: directoryArg inStream: inStreamArg outStream: outStreamArg errorStream: errorStreamArg auxStream: auxInStreamArg showWindow: showWindowArg lineWise: lineWiseArg
set the command to be executed & directory, where to execute.
and input/output streams.
See comments in individual setters for more info

o  command: commandArg inStream: inStreamArg outStream: outStreamArg errorStream: errorStreamArg
set the command to be executed and input/output streams.
See comments in individual setters for more info

o  command: commandArg outStream: outStreamArg errorStream: errorStreamArg
set the command to be executed and output+error streams.
See comments in individual setters for more info

o  commandString
the OS (shell-) command, as string

o  directory
the directory where executed

o  directory: aStringOrFilenameOrNil
set the directory that will be set as the current directory of the command to be executed.
if nil, stx's current directory will be used

o  environment
the shell environment

o  environment: aDictionaryOrNil
set the (additional or overwritten) environment variables of the command to be executed

o  errorStream

o  errorStream: aStream
set the stream where the stderr output of the command is directed to

o  exitStatus
answer the exit status of the command (instance of OSProcessStatus).
or nil if the command has not yet been finished.

o  finishSema
wait on this semaphore if you want to wait until the OS process has finished.
There may be multiple waiters, so it is a good idea to do a #waitUncounted

o  inStream

o  inStream: aStream
set the stream where the stdin input of the command is read from

o  lineWise

o  lineWise: aBoolean
When setting to true, read linewise from the command's output and error.
This is a bit slower than lineWise = false.

You may use it also when streaming to e.g. Transcript

o  newPgrp

o  newPgrp: aBoolean
if aBoolean is true, a new process group will be created for the command and its subprocesses

o  nonNullExitStatusIsOK: aBoolean
this only affects the way, the finsihed status is displayed
(in read or normal).
Use this eg. for diff, where the exit status contains the nr. of
differences, and a non-null status is perfectly ok

o  numericPid
answer the pid of the process the command is running in,
or nil if the command has not yet been started.
Always return an integer, even in windows where pid is a handle

o  outStream
the stream where the stdout output of the command is directed to

o  outStream: aStream
set the stream where the stdout output of the command is directed to

o  pid
answer the pid of the process the command is running in,
or nil if the command has not yet been started.
Notice: on Unix, the pid is an integer;
on Windows, it is a handle.

o  showWindow

o  showWindow: aBooleanOrNil
This parameter is ignored on Unix systems.

You can control (have to - sigh) if a window should be shown for the command or not.
This is the OS's H_SHOWWINDOW argument.
If you pass nil as showWindow-argument, the OS's default is used for the particular
command, which is correct most of the time: i.e. a notepad will open its window, other (non-UI)
executables will not.
However, some command-line executables show a window, even if they should not.
(and also, there seems to be an inconsistency between windows7 and newer windows: in newer,
a shell command opens a cmd-window, whereas in windows7 it did not)
In this case, pass an explicit false argument to suppress it.

o  terminateActionBlock
the (user provided) callback block,
that will be executed when the command has finished or was terminated.
If non-nil, it will be called with optional argument:status and:self, the OSProcess.

o  terminateActionBlock: aBlock
set the callback block,
that will be called when the command has finished or was terminated.
If non-nil, it will be called with optional argument:status and:self, the OSProcess.
WARNING:
if the active-process calling #startProcess is already dead (i.e. terminated),
this callback will be called by the scheduler;
otherwise, the calling process will be interrupted to perform this callback.
Therefore: do not open any GUI or other blocking actions in it.

initialization
o  initialize
Invoked when a new instance is created.

inspecting
o  inspectorExtraMenuOperations
( an extension from the stx:libtool package )
extra operation-menu entries to be shown in an inspector.
Answers a collection of pairs containing aString and action aBlock.
aString is the label of the menu item.
aBlock is evaluated when the menu item is selected.

printing
o  printOn: aStream
(comment from inherited method)
append a user printed representation of the receiver to aStream.
The format is suitable for a human - not meant to be read back.

The default here is to output the receiver's class name.
BUT: this method is heavily redefined for objects which
can print prettier.

private
o  closeHelperStreams
close the helper streams that have been opened for shuffler processes
(remote side of pipe)

o  exitStatus: something
not used and should not be

o  logFinished
optional log some info when an OS command has been finished

o  releasePid
only used in Windows, where pid is a handle that must be released

o  setupShufflerForInput: aReadStream
if aReadStream is an internal Stream, set up a pipe for the command input.
Start a process that shuffles the data from the internal stream into the pipe
(and into the command's input).
Return the ExternalStream that should be passed to the OS process.

o  setupShufflerForOutput: aStream
if aStream is an internal Stream, set up a pipe for the command output.
Start a process that shuffles the data from the pipe's output
into the internal stream.
Return the ExternalStream that should be passed to the OS process.

o  shouldLogFinish
answer true, if a finish log is wanted

o  startCommand
the 'real' command to be executed.
Redefined for remote processes (eg. to construct a remote command string).
Command may be both an Array or a String

o  terminateShufflerProcesses
terminate all the running shuffler processes

o  terminateShufflerProcesses: aProcessCollection
terminate the running shuffler processes contained in aProcessCollection

queries
o  finishedWithSuccess
return true if so

o  isAlive
answer true if the process is still alive

o  isDead
answer true if the process is no longer alive

starting
o  execute
execute the command.
Wait until it is finished.
Abort the execution of the OS process if I am interrupted.
Answer true if it successfully terminated,
false if it could not be started or terminated with error.

Usage example(s):

        (OSProcess new command:'ls -l'; outStream:Transcript) execute

o  executeKeepingProcess
execute the command.
If I am interrupted keep the OS process as background process.
Wait until it is finished.
Answer true if it successfully terminated,
false if it could not be started or terminated with error.

o  startProcess
Start the command asynchronously (i.e. don't wait until is has finished).
If there are non-external streams, setup transfer (shuffler) processes
to transfer data from a pipe to the internal stream.

Answer true if the command could started succesfully, false if not.

NOTE: under normal circumstances, even if the command cannot be found,
the exit fom the command interpreter/shell is done some time later
and true is returned.
So you have to check later or set #terminateActionBlock: and check there.

terminating
o  kill
kill the process - the process does not get the chance to clean up

o  killGroup
kill the processGroup - the processes do not get the chance to clean up

o  terminate
terminate the process gracefully

o  terminateAllChildProcessesExcluding: aCollectionOfPids
terminate the process group.
Under Windows, this is the same as terminateWithAllChildren,
under unix, this terminates a subset of all children

o  terminateGroup
terminate the process group.
Under Windows, this is the same as terminateWithAllChildren,
under unix, this terminates a subset of all children

waiting
o  waitForOutputShufflersToFinish
to wait until the output shufflers shuffling command's outputs have finished their work

o  waitForOutputShufflersToFinishWithTimeout: secondsOrNil
to wait until the output shufflers shuffling command's outputs have finished their work

o  waitUntilFinished
wait with a veeeeeery long timeout,
in order that ProcessorScheduler>>#checkForEndOfDispatch recognizes
this waiting process as an user process which is still alive.
The timeout is meant to never occur!

o  waitUntilFinishedWithTimeout: timeout
return false if timedout; true if finished


Private classes:

    ProcessListEntry
    RemoteOSProcess
    ShufflerProcess

Examples:


send command's output to the Transcript:
  OSProcess new 
      terminateActionBlock:[:status | Transcript showCR:status. Transcript showCR:status isError];
      command:'ls -l';
      outStream:Transcript;
      lineWise:true;
      startProcess.
an invalid command:
  OSProcess new 
      terminateActionBlock:[:status | Transcript showCR:status. Transcript showCR:status isError];
      command:'lsxxx -l';
      outStream:Transcript;
      lineWise:true;
      startProcess.
send command's output to my stdout (see console):
  OSProcess new 
      command:'ls -l';
      outStream:Stdout;
      execute.
send command's output to a Smalltalk stream:
  |outStream|

  outStream := '' writeStream.

  OSProcess new 
      command:'ls -l';
      outStream:outStream;
      execute.

  outStream contents inspect.
feed it from a smalltalk stream, get command's output into a Smalltalk stream:
  |inStream outStream|

  inStream := 'hello world' readStream.
  outStream := '' writeStream.

  OSProcess new 
      command:'tr ''a-z'' ''A-Z''';
      inStream:inStream;
      outStream:outStream;
      execute.

  outStream contents inspect.
again, send output to a Smalltalk stream; watch the stream getting filled after 10 seconds:
  |outStream|

  outStream := '' writeStream.

  OSProcess new 
      command:'ls -l; sleep 10; echo =================================; echo hallo after 10s; echo >&2 +++++++++++++++++++++; cat >&2';
      outStream:outStream;
      errorStream:outStream;
      startProcess.

  outStream inspect
separate stdout and stderr:
  |outStream errStream|

  outStream := '' writeStream.
  errStream := '' writeStream.

  OSProcess new 
      command:'ls -l && ls >&2';
      outStream:outStream;
      errorStream:errStream;
      startProcess.

  outStream inspect.
  errStream inspect.
Execute commands in shell/cmd.exe and read them from stdin:
  |outStream|

  outStream := '' writeStream.

  OSProcess new 
      command:'';
      inStream:'ls -l' readStream;
      outStream:outStream;
      lineWise:true;
      execute.

  outStream contents inspect
Execute on a remote host (you must have the appropriate ssh setup):
  |outStream|

  outStream := '' writeStream.

  (OSProcess onHost:'exeptn') 
      command:'ls -l';
      outStream:outStream;
      lineWise:true;
      execute.

  outStream contents inspect


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sat, 21 Dec 2024 15:35:21 GMT