Recent

Author Topic: Unix command Execution with output problem.  (Read 757 times)

BSaidus

  • Hero Member
  • *****
  • Posts: 542
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Unix command Execution with output problem.
« on: February 11, 2023, 01:10:34 pm »
Hello.
Given the following OpenBSD unix command line:
Code: Text  [Select][+][-]
  1. /usr/bin/netstat -in -f inet|awk '{ print $1,"\t",$3,"\t",$4; }'|grep -v -e lo0 -e enc -e pflog -e tun|grep Link|sed 's/*//'|awk '{ if( system("[ ! -f /var/run/dmesg.boot ]") == 0) system("dmesg >/var/run/dmesg.boot"); cmd="grep ^"$1" /var/run/dmesg.boot"; while((cmd|getline drv0)>0) {$4=drv0} close(cmd); print $1,"\t",$3,"\t",$4;}'
  2.  
after execution it will display following
Code: [Select]
pcn0     08:00:27:0a:65:2d       pcn0 at pci0 dev 3 function 0 "AMD 79c970 PCnet-PCI" rev 0x10, Am79c970A, rev 0: apic 2 int 19, address 08:00:27:0a:65:2d
pcn1     08:00:27:78:3c:29       pcn1 at pci0 dev 8 function 0 "AMD 79c970 PCnet-PCI" rev 0x40, Am79c973, rev 0: apic 2 int 16, address 08:00:27:78:3c:29
em0      08:00:27:8d:4a:c6       em0 at pci0 dev 9 function 0 "Intel 82540EM" rev 0x02: apic 2 int 17, address 08:00:27:8d:4a:c6
em1      08:00:27:00:0c:c8       em1 at pci0 dev 10 function 0 "Intel 82543GC" rev 0x02: apic 2 int 18, address 08:00:27:00:0c:c8
I made a wrapper for the process.runcommand function and try to execute this command as follow
Code: Pascal  [Select][+][-]
  1. function fpExecCmd(const ACmd: String; const AArgs: array of string): String;
  2. begin
  3.   if not process.RunCommand( ACmd, AArgs, Result ) then
  4.   begin
  5.     Result := 'Error Message';
  6.   end;
  7. end;
  8.  
  9.   Result := fpExecCmd( '/usr/bin/netstat', ['-in', '-f', 'inet',
  10.                 '|','awk' , '''{ print $1,"\t",$3,"\t",$4; }''',
  11.                 '|','grep', '-v', '-e', 'lo0', '-e', 'enc', '-e', 'pflog', '-e', 'tun',
  12.                 '|','grep', 'Link',
  13.                 '|','sed' , '''s/*//''',
  14.                 '|','awk' , '''{ if( system("[ ! -f /var/run/dmesg.boot ]") == 0) system("dmesg >/var/run/dmesg.boot"); cmd="grep ^"$1" /var/run/dmesg.boot"; while((cmd|getline drv0)>0) {$4=drv0} close(cmd); print $1,"\t",$3,"\t",$4;}'''] );
  15.  
  16. var
  17.   LRet: String ;
  18. begin
  19.   LRet := fpExecCmdNetStat();
  20.   WriteLn(LRet);
  21.  
  22. end.
  23.  
  24.  

The execution gives the 'Error Message'.
I've tried different combination but ... not successful.
Any one have an idea ??
Thanks.
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

BSaidus

  • Hero Member
  • *****
  • Posts: 542
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: Unix command Execution with output problem.
« Reply #1 on: February 11, 2023, 01:25:05 pm »
Hi,
Find one solution but, do not like to me.
Code: Pascal  [Select][+][-]
  1. function fpExecCmdNetStatSh(): String;
  2. const
  3.   CNetSh: String = 'netstat -in -f inet|awk ''{ print $1,"\t",$3,"\t",$4; }''|grep -v -e lo0 -e enc -e pflog -e tun|grep Link|sed ''s/*//''|awk ''{ if( system("[ ! -f /var/run/dmesg.boot ]") == 0) system("dmesg >/var/run/dmesg.boot"); cmd="grep ^"$1" /var/run/dmesg.boot"; while((cmd|getline drv0)>0) {$4=drv0} close(cmd); print $1,"\t",$3,"\t",$4;}''';
  4. var
  5.   Ltemp: TStringList;
  6.   Lstr: String;
  7. begin
  8.    Ltemp := TStringList.Create;
  9.    Lstr := '#!/bin/sh' + LineEnding + CNetSh;
  10.    try
  11.      Ltemp.Text := Lstr;
  12.      Ltemp.SaveToFile('t.sh');
  13.      Result := fpExecCmd('/bin/sh', ['t.sh']);
  14.    finally
  15.      Ltemp.Free;
  16.      DeleteFile('t.sh');
  17.    end;
  18. end;
  19.  
  20. var
  21.   LRet: String ;
  22. begin
  23.   LRet := fpExecCmdNetStatSh();
  24.   WriteLn(LRet);
  25. end.
  26.  

It works, but ... I seek the way to run it using function offred by process unit.
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Unix command Execution with output problem.
« Reply #2 on: February 11, 2023, 01:43:55 pm »
It works, but ... I seek the way to run it using function offred by process unit.
If you wish to use the functionality from TProcess then simply use it ? The wiki is full of examples.

If something is not working for you when using tprocess then you really have to state what is not working for you. You can use the exact same commands with tprocess as you did with fpexeccmd.

PS if you rely on shell internals then the only way to solve it is by using the shell. Otherwise you can omit the part where you save it to a script-file.

edit: PPS: your 'working' solution does not work for me on a linux system, thus sorry to say I can't test for you. What system/OS do you use ?
« Last Edit: February 11, 2023, 02:15:14 pm by TRon »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Unix command Execution with output problem.
« Reply #3 on: February 11, 2023, 03:31:14 pm »
If you want to have shell interpretation in your commandlines, you must call a shell interpreter to interpret it. This includes piping like > etc.

 Otherwise it goes straight to the kernel, without any interpretation. So try:

 
Code: Pascal  [Select][+][-]
  1.   Result := fpExecCmd( '/bin/sh', ['-c',wh/usr/bin/netstat and whole rest of commandline in single string'])



PierceNg

  • Sr. Member
  • ****
  • Posts: 369
    • SamadhiWeb
Re: Unix command Execution with output problem.
« Reply #4 on: February 11, 2023, 03:35:35 pm »
Code: [Select]
'netstat -in -f inet|awk ''{ print $1,"\t",$3,"\t",$4; }''|grep -v -e lo0 -e enc -e pflog -e tun|grep Link|sed ''s/*//''|awk ''{ if( system("[ ! -f /var/run/dmesg.boot ]") == 0) system("dmesg >/var/run/dmesg.boot"); cmd="grep ^"$1" /var/run/dmesg.boot"; while((cmd|getline drv0)>0) {$4=drv0} close(cmd); print $1,"\t",$3,"\t",$4;}''

It works, but ... I seek the way to run it using function offred by process unit.


First, the way the original command is constructed, you'll need to feed it to a shell. Each of the awk, grep, sed etc is a process by itself. To run the script without shell, your program will have to do what the shell does: fork/exec each process and join up their stdin/stdout using pipes, i.e., work like a shell. So might as well just use the shell to run your script.

Second, it should be possible to write a single awk program that does all the awk/grep/sed stuff so your process pipeline should simply be <netstat output> | <single awk program>. And from there, you could implement what the single awk program does in Pascal. Then, you could use TProcess to run the netstat command and process its output in your Pascal program.

But I have a question: Why not just run t.sh? Why replicate the work in Pascal?

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Unix command Execution with output problem.
« Reply #5 on: February 11, 2023, 03:38:54 pm »
@BSaidus:
As marcov wrote, but on a Linux system I get stuck here:
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   sysutils, classes, process;
  7.  
  8. function fpExecCmd(const ACmd: String; const AArgs: array of string): String;
  9. begin
  10.   if not process.RunCommand( ACmd, AArgs, Result ) then
  11.   begin
  12.     Result := 'Error Message';
  13.   end;
  14. end;
  15.  
  16. //   CNetSh: String = 'netstat -in -f inet|awk ''{ print $1,"\t",$3,"\t",$4; }''|grep -v -e lo -e enc -e pflog -e tun|grep Link|sed ''s/*//''|awk ''{ if( system("[ ! -f /var/run/dmesg.boot ]") == 0) system("dmesg >/var/run/dmesg.boot"); cmd="grep ^"$1" /var/run/dmesg.boot"; while((cmd|getline drv0)>0) {$4=drv0} close(cmd); print $1,"\t",$3,"\t",$4;}''';
  17. function phase1: string;
  18. var
  19.   ret: string absolute result;
  20.   cmd: string;
  21. begin
  22.  cmd := 'netstat -in -f inet | awk ''{ print $1,"\t",$3,"\t",$4 }'' | grep -v -e lo0 -e enc -e pflog -e tun';
  23.  ret := fpExecCmd('/usr/bin/bash', ['-c', cmd]);
  24. end;
  25.  
  26. var
  27.   Lines: TStringList;
  28.   Line : string;
  29. begin
  30.   Lines := TStringList.Create;
  31.   Lines.Text := phase1;
  32.   for Line in Lines do WriteLn(Line);
  33.   Lines.Free;
  34. end.
  35.  
  36. (* output
  37. Kernel   table
  38. Iface    RX-OK   RX-ERR
  39. eth0     87205   0
  40. eth1     0       0
  41. lo       24      0
  42. *)
  43.  
.. because there is no "Link" to grep for me.

Thaddy

  • Hero Member
  • *****
  • Posts: 14213
  • Probably until I exterminate Putin.
Re: Unix command Execution with output problem.
« Reply #6 on: February 11, 2023, 04:27:17 pm »
It would also be nice if Process would be created...?
Specialize a type, not a var.

BSaidus

  • Hero Member
  • *****
  • Posts: 542
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: Unix command Execution with output problem.
« Reply #7 on: February 13, 2023, 09:22:47 am »
Thank you all for advices.
I take the advice of @marcov.
It works well.
 :)
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Unix command Execution with output problem.
« Reply #8 on: February 13, 2023, 09:26:44 am »
It would also be nice if Process would be created...?

It is an unit ?

 

TinyPortal © 2005-2018