process

package module
v0.0.0-...-3dbd443 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 5, 2024 License: MIT Imports: 15 Imported by: 2

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ExitInBackGround   = 601 // the exit code when the process is running in the background
	ExitTimeout        = 602 // the exit code when the process is stopped by timeout
	RealCodeNotPresent = -1  // the real exit code is not present because the process was killed or never started or timed out
)
View Source
var (
	DefaultKillSignal      = Signal{Signal: os.Kill, ThenWait: 20 * time.Millisecond}
	DefaultInterruptSignal = Signal{Signal: os.Interrupt, ThenWait: 800 * time.Millisecond}
)

Functions

func GetChildPIDs

func GetChildPIDs(pid int) ([]int, error)

func KillProcessTree

func KillProcessTree(pid int) error

KillProcessTree kills the process by using the process group id

func TryPid2Pgid

func TryPid2Pgid(cmd *exec.Cmd) bool

on linux we need to set the process group id to kill the whole process tree now any kill command have to add -pgid to kill the whole process tree like: syscall.Kill(-ts.process.processInfo.Pid, syscall.SIGKILL) returnning true to indicate that the process group id is set

Types

type ProcCallback

type ProcCallback func(string, error) bool // the callback to call when output is received

type ProcChildCntChangeCallback

type ProcChildCntChangeCallback func(int) // a callback for the process handler

type ProcData

type ProcData struct {
	Pid         int         // process id
	Cmd         string      // command line
	ThreadCount int         // number of threads
	Threads     []int       // list of threads pids
	Childs      []int       // list of child pids
	ChildProcs  []*ProcData // list of child processes
}

basic struct to hold the data of a process

func NewProc

func NewProc(pid int) (*ProcData, error)

ReadProc reads the process data of a process with the given pid and returns a ProcData struct

func ReadProc

func ReadProc(pid int) (*ProcData, error)

func (*ProcData) CountChilds

func (pd *ProcData) CountChilds(offset int) int

func (*ProcData) Stop

func (pd *ProcData) Stop(signals ...Signal) error

Stop sends the given signals to the child processes and then to the process itself. any of these child processes can have child processes they will be stopped too the signal order is important. you can use one of the default Signnals, the containing the regular signal and the ThenWait time, that is used to give the process time to stop. or you can send your own signals. like so:

proc.Stop(process.Signal{Signal: syscall.SIGINT, ThenWait: 1 * time.Second}, process.Signal{Signal: syscall.SIGKILL, ThenWait: 10 * time.Millisecond})

if the process is not running anymore, we will return nil this is also used by the ProcessWatch.Stop() function

func (*ProcData) StopChilds

func (pd *ProcData) StopChilds(signals ...Signal) error

ProcData.Stop sends the given signals to the child processes any of these child processes can have child processes they will be stopped too

func (*ProcData) WalkChildProcs

func (pd *ProcData) WalkChildProcs(startLevel int, f func(p *ProcData, parentPid int, level int) bool)

WalkChildProcs walks through the child processes of the process. this is a recursive function and calls the given function for each child process. the function gets the child process data, the parent pid and the level as parameter the level is the level of the child process in the process tree. this is mostly used internally by calling WalkChildProcs from ProcessWatch. but can also be used to get any childs starting from a different level, if needed.

type ProcHndlCallback

type ProcHndlCallback func(error) // a callback for the process handler

type ProcInfoCallback

type ProcInfoCallback func(*os.Process) // the callback to call when the process is started

type Process

type Process struct {
	// contains filtered or unexported fields
}

func NewProcess

func NewProcess(cmd string, args ...string) *Process

NewProcess creates a new process with the given command and arguments

func NewTerminal

func NewTerminal(args ...string) *Process

Create a new process by using the default terminal as defined in the terminal package if no arguments are given, is seems to be intended to be used for interactive processes

func (*Process) AddStartCommands

func (p *Process) AddStartCommands(args ...string)

AddStartCommands sets the arguments to pass to the command without waiting for any other setup. other than Command(string) you do not need to setup the whole environment and control structures.

func (*Process) BlockWait

func (p *Process) BlockWait(tickTime time.Duration) error

BlockWait blocks the current thread until the process is stopped. it uses a tick time to check if the process is stopped in intervals. this if meant to be used by tests. not in production code except you know what you are doing. most of the time you want to use the OnOutput callback to handle the output of the process and stop the process by using the Stop() method. or use go routines to handle the process output and stop the process if needed. using this method is a sign you do not need a background process.

func (*Process) Command

func (p *Process) Command(cmd string) error

Command sends a command to the process. this command is send to the process by using the inPipe. the command will be send to the process as a string with a newline at the end. to get the response of the process, you need to set the onOutput callback. this is only possible if the process is set to stay open. if the process is not set to stay open, this will return an error. if the process is not started, this will return an error. if the process is stopped, this will return an error. if the inPipe is nil, this will return an error. if the command could not be send to the process, this will return an error.

func (*Process) Exec

func (p *Process) Exec() (int, int, error)

Exec starts the process onece or in background depending on the stayOpen flag. if its started in background, it will return directly after the process is started. so the return codes are not the real exit codes of the process. instead they are an internalcode that indicates the process is running in background.

  • the internal exit code of the process
  • the real exit code of the process (if we have one. if not then -1 on error or 0 for some expected states like killed)
  • an error if one occured

func (*Process) GetLogger

func (p *Process) GetLogger() mimiclog.Logger

GetLogger returns the logger for the process

func (*Process) GetProcessWatcher

func (p *Process) GetProcessWatcher() (*ProcessWatch, error)

GetProcessWatcher returns the process watcher for the process.

func (*Process) IsStarted

func (p *Process) IsStarted() bool

returns if the process is started

func (*Process) Kill

func (p *Process) Kill() (int, int, error)

Kill kills the process and all its childs it uses the DefaultKillSignal to kill the processes. So this is the Hard way to kill a process. if you want to stop a process in a more graceful way use the Stop() method instead. it returns

  • the internal exit code of the process
  • the real exit code of the process (if we have one. if not then -1 on error or 0 for some expected states like killed)
  • an error if one occured

func (*Process) SetCombinePipes

func (p *Process) SetCombinePipes(combine bool)

SetCombinePipes sets whether or not to combine the output and error pipes this will change the behavior of the process because error messages will be handled as output. only errors that are returned by the process itself will be handled as errors and pushed to the onOutput callback. this can be usefull for command they runs once so you do not have to handle the error pipe, because you should get the error then anyway. for processes that stay open, you should not use this because you will not get the errors while runtime.

func (*Process) SetKeepRunning

func (p *Process) SetKeepRunning(stayOpen bool)

SetKeepRunning sets whether or not the process should stay open. If it does, it will not be stopped after the process handles the startup commands. this will change the behavior of the process because the started process will wait for inputs or beeing stopped by the Stop() method.

func (*Process) SetLogger

func (p *Process) SetLogger(logger mimiclog.Logger)

SetLogger sets the logger for the process Fullfilling the mimiclog.Logger interface

func (*Process) SetOnChildCountChange

func (p *Process) SetOnChildCountChange(callback ProcChildCntChangeCallback)

SetOnChildCountChange sets the callback to call when the child count of the process changes. this is only usefull for processes that stay open.

func (*Process) SetOnInit

func (p *Process) SetOnInit(callback ProcInfoCallback)

SetOnInit sets the callback to call when the process is started. you will get the process object as argument. you can use this to get the process id and do something with it. but be carefull to not kill the process by accident. this package should handle the process for you. so you should not need to handle it by yourself.

func (*Process) SetOnOutput

func (p *Process) SetOnOutput(callback ProcCallback)

SetOnOutput sets the callback to call when output is received. Depending on the combinePipes flag, the error messages will be handled as output. the callback: func(string, error) bool

  • the string is the output of the process
  • the error is the error of the process
  • the bool is the return value of the callback. if false is returned, the process will be stopped. if true is returned, the process will continue to run.

while runtime and an not combined pipe, anything that will be written to the error pipe will be handled as error. but also as message. so there is no need to handle booth messages in case of error.

process.SetOunOutput(func(msg string, err error) bool {
  if err != nil {
    // error.Error() is the same as msg. so no need to handle it twice
    return false // stop the process in this example. you can also return true to keep the process running
  }
  // do something with the message
  return true
})

func (*Process) SetOnWaitDone

func (p *Process) SetOnWaitDone(callback ProcHndlCallback)

SetOnWaitDone sets the callback to call when the process is stopped after a regular wait for cmd execution. this is not called if the process is stopped by any other reason like timeout or killing the process.

func (*Process) SetReportChildCount

func (p *Process) SetReportChildCount(report bool)

enable reporting the child count if changed. this is mostly usefull for processes that stay open. and is ment togehther with the SetOnChildCountChange callback. but you can also use it without the callback just to get the child count by the logger output (debug level needed)

func (*Process) SetTimeout

func (p *Process) SetTimeout(timeout time.Duration)

SetTimeout sets the timeout for the process. If the process is not stopped after the timeout, it will be stopped

func (*Process) Stop

func (p *Process) Stop() (int, int, error)

Stop stops the process. for this the default stop procedure is used. that means first the process willget an interrupt signal. then we wait for a short time. if the process is still running, we will kill it. this is the soft way to stop a process. if you want to kill a process in a more hard way, use the Kill() method instead. it returns

  • the internal exit code of the process
  • the real exit code of the process (if we have one. if not then -1 on error or 0 for some expected states like killed)
  • an error if one occured

func (*Process) WaitUntilRunning

func (p *Process) WaitUntilRunning(tickTime time.Duration) (time.Duration, error)

WaitUntilRunning blocks the current thread until the process is running. it uses a tick time to check if the process is running in intervals. this can be usefull to make sure the process is running before you send commands to it.

type ProcessWatch

type ProcessWatch struct {
	// contains filtered or unexported fields
}

func NewProcessWatcherByCmd

func NewProcessWatcherByCmd(cmd *exec.Cmd) (*ProcessWatch, error)

NewProcessWatcherByCmd creates a new ProcessDef struct and returns a pointer to it the ProcessDef struct holds the process data of the given process

func NewProcessWatcherByPid

func NewProcessWatcherByPid(pid int) (*ProcessWatch, error)

NewProcessWatcherByPid creates a new ProcessDef struct and returns a pointer to it same as NewProcessWatcherByCmd but with a pid as parameter

func NewProcessWatcherByProcessInfo

func NewProcessWatcherByProcessInfo(proc *os.Process) (*ProcessWatch, error)

NewProcessWatcherByProcessInfo creates a new ProcessDef struct and returns a pointer to it same as NewProcessWatcherByCmd but with a os.Process struct as parameter

func (*ProcessWatch) CountChildsAll

func (proc *ProcessWatch) CountChildsAll() int

func (*ProcessWatch) GetChilds

func (proc *ProcessWatch) GetChilds() []int

GetChilds returns the list of PID's of child processes of the process

func (*ProcessWatch) GetCmd

func (proc *ProcessWatch) GetCmd() string

GetCmd returns the command line of the process

func (*ProcessWatch) GetPid

func (proc *ProcessWatch) GetPid() int

GetPid returns the pid of the process

func (*ProcessWatch) GetProcessInfo

func (proc *ProcessWatch) GetProcessInfo() *os.Process

GetProcessInfo returns the os.Process struct of the process

func (*ProcessWatch) GetThreadCount

func (proc *ProcessWatch) GetThreadCount() int

GetThreadCount returns the number of threads of the process these are NOT the child processes. these are the threads of the process itself

func (*ProcessWatch) GetThreads

func (proc *ProcessWatch) GetThreads() []int

GetThreads returns the list of PID's of threads of the process

func (*ProcessWatch) IsRunning

func (proc *ProcessWatch) IsRunning() (bool, error)

IsRunning checks if the process is still running. this is done by requesting the process data again. if an error occurs then the process is not running anymore because the process data can not be read. that means that we will return false if an error occurs so this is you should check instead the error itself. the error is useful if you want to know why the process data can not be read. but again: for a process that is stopped, you will get always an error.

func (*ProcessWatch) Kill

func (proc *ProcessWatch) Kill() error

Kill sends the kill signal to the process it uses the KillProcessTree function to kill the process tree. this way we can include some os specific code to kill the process tree.

func (*ProcessWatch) SetLogger

func (proc *ProcessWatch) SetLogger(logger mimiclog.Logger)

SetLogger sets the logger for the process if no logger is set, a null logger will be used

func (*ProcessWatch) StopChilds

func (proc *ProcessWatch) StopChilds(signals ...Signal) error

ProcessWatch.StopChilds sends the given signals to the child processes any of these child processes can have child processes. they will be stopped too. the signal order is important. you can use one of the default Signnals, the containing the regular signal and the ThenWait time, that is used to give the process time to stop. or you can send your own signals. like so:

proc.StopChilds(process.Signal{Signal: syscall.SIGINT, ThenWait: 1 * time.Second}, process.Signal{Signal: syscall.SIGKILL, ThenWait: 10 * time.Millisecond})

func (*ProcessWatch) StopWithDefaultSigOrder

func (proc *ProcessWatch) StopWithDefaultSigOrder() error

StopWithDefaultSigOrder sends the default signals to the child processes DefaultInterruptSignal and DefaultKillSignal this is the same as calling StopChilds(DefaultInterruptSignal, DefaultKillSignal) instead of just stopping the current process, we also taking care about the child processes. this way we can make sure that the process tree is stopped, and we do not have any zombie processes.

func (*ProcessWatch) Update

func (proc *ProcessWatch) Update() error

Update updates the process data of the process. this is done by requesting the process data again. if an error occurs then the process is not running anymore. at least this is the usual case. because the process data can not be read.

func (*ProcessWatch) WaitForStart

func (proc *ProcessWatch) WaitForStart(timeout, waitTick time.Duration) error

WaitForStart waits until the process is started. or until the timeout is reached. this is ment for use in cases, we just want to wait until the process is started, before we start working with them. here we do not check any internal flags or something like that. we just check if the process is running in the system. so this would also return true if the process is running, but not able to handle some inputs. this is depending on the process itself. for checking if the process handle inputs, you need to check the output of the process. (if the application outputs some text on start)

func (*ProcessWatch) WaitForStop

func (proc *ProcessWatch) WaitForStop(timeout, waitTick time.Duration) (time.Duration, error)

WaitForStop waits until the process is stopped. or until the timeout is reached. this is different to the usual Timeout function, because this will not count for the Timeout. this function is ment for use in cases, we just want to wait until the process is stopped, without forcing them being killed. if the (local) timeout is reached, we will return an error, but the process will still be running. this can be combined with the Timeout function, to force the process to stop after the timeout is reached. but then make sure to set the timeout to a higher value than the WaitForStop timeout.

func (*ProcessWatch) WalkChildProcs

func (proc *ProcessWatch) WalkChildProcs(f func(p *ProcData, parentPid int, level int) bool)

WalkChildProcs walks through the child processes of the process and calls the given function for each child process the function gets the child process data, the parent pid and the level as parameter the level is the level of the child process in the process tree the function returns a bool. if the bool is true, the child processes of the child process will be walked too

type Signal

type Signal struct {
	Signal   os.Signal
	ThenWait time.Duration
}

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL