The agent reuses ExternalProgram class from liby2util, class Process is derived from ExternalProgram and adds stderr reading/writing, output buffering and a posibility to send a specified signal.
The complete path description is available in the autodocs/ directory.
// start a subprocess, remember the id
integer id = (integer)(SCR::Execute(.process.start_shell, "/usr/bin/find /usr -type d"));
string line = "";
while(SCR::Read(.process.running, id) == true)
{
// read stderr
line = (string)SCR::Read(.process.read_line_stderr, id);
if (line != nil)
{
y2warning("Error: %1", line);
}
// read stdout
line = (string)SCR::Read(.process.read_line, id);
if (line != nil)
{
// process the output here
...
}
else
{
// there was no output, wait for a while
// give the subprocess time to print something
// NOTE: change the constand in respect to the running command,
// increase it for processes which print few lines
sleep(20);
}
ret = (symbol) UI::PollInput();
// check if the abort button was pressed
if (ret == `abort)
{
SCR::Execute(.process.kill, id); // kill the subprocess
break;
}
}
// process the remaining lines in the stdout buffer
while (line != nil);
{
UI::ChangeWidget(`id(`dir), `Value, line);
line = (string)SCR::Read(.process.read_line, id);
}
// process the stderr buffer here
...
The agent can start a subprocess in two ways
Note that the arguments are passed differently in each case. Shell execution requires the argument in the command, the arguments must be escaped to be processes correctly. The direct execution uses an optional map, the arguments are passed as a list of strings at key "args". In this case the armunets need not to be escpaed.
Example:
Start echo "\"foo bar\"" command:
When a subprocess produces too much output which is not read it is stopped when the buffers are full. (In my test it was about after 64kB, but this is system dependent.)
So it is a good idea to read the output regularly. It is possible to read the output (using .process.read(_line) and .process.read_stderr(_line) paths) when the process is running or just read the output to the internal buffers in the agent (using Read(.process.running), in addition to checking the status it read the outputs) and read them later at once when the process is finished.
Ladislav Slezák <lslezak@novell.com>