On 02/02/2012 11:00, [email protected] wrote:
> Hi, I need run 3 external program and redirected output: first | second |
> third
>
> For example:
> df -hT | grep -v -E 'tmpfs|ecryptfs' | grep 'sda2'
> it gives
> /dev/sda2 ext4 19G 11G 7,6G 58% /
>
> I use this
> http://wiki.lazarus.freepascal.org/Executing_External_Programs#How_to_redirect_output_with_TProcess
> sample code. It works fine for first | second.
>
> For three programs I try edit it:
>
>
> function threePipe(inputA, inputB, inputC: string): string;
> var
> FirstProcess, SecondProcess, ThirdProcess: TProcess;
> Buffer: array[0..127] of char;
> ReadCount: Integer;
> ReadSize: Integer;
> begin
> FirstProcess := TProcess.Create(nil);
> SecondProcess := TProcess.Create(nil);
> ThirdProcess := TProcess.Create(nil);
>
> FirstProcess.Options := [poUsePipes];
> SecondProcess.Options := [poUsePipes];
> ThirdProcess.Options := [poUsePipes,poStderrToOutPut];
>
> FirstProcess.CommandLine := inputA;
> SecondProcess.CommandLine := inputB;
> ThirdProcess.CommandLine := inputC;
>
> FirstProcess.Execute;
> SecondProcess.Execute;
> ThirdProcess.Execute;
>
while (Firstprocess.Running or SecondProcess.Running or ThirdProcess.Running) do
begin
if Firstprocess.Running then
begin
if (FirstProcess.Output.NumbytesAvailable > 0) then
begin
ReadSize := FirstProcess.Output.NumBytesAvailable;
if ReadSize > SizeOf(Buffer) then
ReadSize := SizeOf(Buffer);
ReadCount := FirstProcess.Output.Read(Buffer[0], ReadSize);
SecondProcess.Input.Write(Buffer[0], ReadCount);
// at the end of this, we have written max. 128 bytes to
SecondProcess' input
end; // if no more bytes, we could terminate the FirstProcess but
having it here
// may race when the lot starts: when FirstProcess just started
but has no output yet
// or if for some reason it stops on the way;
// some checking for first process's errors may be a good idea
too, here.
end
else
SecondProcess.CloseInput; // when first process ends, input to second also
ends
if SecondProcess.Running then
begin
if (SecondProcess.Output.NumBytesAvailable > 0) then
begin
ReadSize := SecondProcess.Output.NumBytesAvailable;
if ReadSize > SizeOf(Buffer) then
ReadSize := SizeOf(Buffer);
ReadCount := SecondProcess.Output.Read(Buffer[0], ReadSize);
ThirdProcess.Input.Write(Buffer[0], ReadCount);
end;
end
else
ThirdProcess.CloseInput;
if ThirdProcess.Running then
begin
if (ThirdProcess.Output.NumbytesAvailable >0) then
begin
ReadSize := ThirdProcess.Output.NumBytesAvailable;
if ReadSize > SizeOf(Buffer) then
ReadSize := SizeOf(Buffer);
if ReadSize > 0 then
begin
ReadCount := ThirdProcess.Output.Read(Buffer, ReadSize);
Write(Copy(Buffer,0, ReadCount)); // i think no writeln, but
write (grep gives you ^M on each line IIRC)
end;
end;
end;
end;
> while FirstProcess.Running or (FirstProcess.Output.NumBytesAvailable > 0) do
> begin
> if FirstProcess.Output.NumBytesAvailable > 0 then
> begin
> ReadSize := FirstProcess.Output.NumBytesAvailable;
> if ReadSize > SizeOf(Buffer) then
> ReadSize := SizeOf(Buffer);
> ReadCount := FirstProcess.Output.Read(Buffer[0], ReadSize);
> SecondProcess.Input.Write(Buffer[0], ReadCount);
> end;
> end;
> SecondProcess.CloseInput;
>
> while SecondProcess.Running or (SecondProcess.Output.NumBytesAvailable > 0)
> do
> begin
> if SecondProcess.Output.NumBytesAvailable > 0 then
> begin
> ReadSize := SecondProcess.Output.NumBytesAvailable;
> if ReadSize > SizeOf(Buffer) then
> ReadSize := SizeOf(Buffer);
> ReadCount := SecondProcess.Output.Read(Buffer[0], ReadSize);
> ThirdProcess.Input.Write(Buffer[0], ReadCount);
> end;
> end;
> ThirdProcess.CloseInput;
>
>
> while ThirdProcess.Running do
> Sleep(1);
> ReadSize := ThirdProcess.Output.NumBytesAvailable;
> if ReadSize > SizeOf(Buffer) then
> ReadSize := SizeOf(Buffer);
> if ReadSize > 0 then
> begin
> ReadCount := ThirdProcess.Output.Read(Buffer, ReadSize);
> //WriteLn(Copy(Buffer,0, ReadCount));
> end
> else
> WriteLn('grep did not find what we searched for. ',
> ThirdProcess.ExitStatus);
>
// here;
> FirstProcess.Free;
> SecondProcess.Free;
> ThirdProcess.Free;
> threePipe := Copy(Buffer,0, ReadCount); // and this will be nonsense -
> better have another variable accounting all bytes out from third process
> end;
>
>
>
> But after i call
> Label1.Caption:=threePipe('df -hT', 'grep -v -E ''tmpfs|ecryptfs''', 'grep
> ''sda2''');
> function my application end with infinite loop.
>
> Where I do an error?
>
Thought compiled only.
But:
- uses same buffer to pass between stages, adjusts buffer to size between
reads, does not
stop to read the whole buffer output from first process or second process, just
passes buffer
as it comes
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus