如何使用free pascal 调用bash命令

本文档解决的问题是:如何使用free pascal 调用bash命令

首先安装free pascal

这里一开始走了弯路,直接pkg search pascal,发现没有....

原来它的名字叫fpc ,所以应该pkg search fpc

pkg search fpc
pkg: No SRV record found for the repo 'FreeBSD'
fpc-3.2.3                      Free Pascal compiler with Turbo and Delphi compatibility
fpc-devel-3.3.1.20240503       Free Pascal compiler with Turbo and Delphi (devel)
fpc-devel-source-3.3.1.20240503 Free Pascal compiler with Turbo and Delphi compatibility (source)
fpc-docs-3.2.2                 Free Pascal compiler Adobe Acrobat(tm) documentation
fpc-source-3.2.3               Free Pascal compiler with Turbo and Delphi compatibility (source)
pdfpc-4.6.0_6                  Keynote-like multi-monitor presentation viewer

也可以从官网下载适合自己的版本:

Free Pascal - Download

使用Pascal调用bash

Executing External Programs - Free Pascal wiki

一个例子

// This is a 
// FLAWED
// demo program that shows
// how to launch an external program
// and read from its output.
program launchprogram;
 
// Here we include files that have useful functions
// and procedures we will need.
uses 
  Classes, SysUtils, Process;
 
// This is defining the var "AProcess" as a variable 
// of the type "TProcess"
// Also now we are adding a TStringList to store the 
// data read from the programs output.
var 
  AProcess: TProcess;
  AStringList: TStringList;

// This is where our program starts to run
begin
  // Now we will create the TProcess object, and
  // assign it to the var AProcess.
  AProcess := TProcess.Create(nil);
 
  // Tell the new AProcess what the command to execute is.
  AProcess.Executable := '/usr/local/bin/ppcx64'; 
  AProcess.Parameters.Add('-h'); 

  // We will define an option for when the program
  // is run. This option will make sure that our program
  // does not continue until the program we will launch
  // has stopped running. Also now we will tell it that
  // we want to read the output of the file.
  AProcess.Options := AProcess.Options + [poWaitOnExit, poUsePipes];
 
  // Now that AProcess knows what the commandline is it can be run.
  AProcess.Execute;
  
  // After AProcess has finished, the rest of the program will be executed.
 
  // Now read the output of the program we just ran into a TStringList.
  AStringList := TStringList.Create;
  AStringList.LoadFromStream(AProcess.Output);
   
  // Save the output to a file and clean up the TStringList.
  AStringList.SaveToFile('output.txt');
  AStringList.Free;
 
  // Now that the output from the process is processed, it can be freed.
  AProcess.Free;   
end.

 编译

fpc ppc.fpc
Free Pascal Compiler version 3.2.2 [2024/04/04] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: FreeBSD for x86-64
Compiling ppc.fpc
Linking ppc
/usr/local/bin/ld.bfd: warning: /usr/local/lib/fpc/3.2.2/units/x86_64-freebsd/rtl/prt0.o: missing .note.GNU-stack section implies executable stack
/usr/local/bin/ld.bfd: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
53 lines compiled, 0.2 sec

执行

./ppc

查看输出:

cat output.txt |more
Free Pascal Compiler version 3.2.2 [2024/04/04] for x86_64
Copyright (c) 1993-2021 by Florian Klaempfl and others
/usr/local/bin/ppcx64 [options] <inputfile> [options]
 Put + after a boolean switch option to enable it, - to disable it.
  @<x>   Read compiler options from <x> in addition to the default fpc.cfg
  -a     The compiler does not delete the generated assembler file
      -a5        Don't generate Big Obj COFF files for GNU Binutils older than 2.25 (Windows, NativeNT)
      -al        List sourcecode lines in assembler file
      -an        List node info in assembler file (-dEXTDEBUG compiler)
      -ao        Add an extra option to external assembler call (ignored for internal)
      -ap        Use pipes instead of creating temporary assembler files
      -ar        List register allocation/release info in assembler file
      -at        List temp allocation/release info in assembler file
  -A<x>  Output format:
      -Adefault  Use default assembler
      -Aas       Assemble using GNU AS
      -Agas      Assemble using GNU GAS
      -Agas-darwin Assemble darwin Mach-O64 using GNU GAS
      -Amasm     Win64 object file using ml64 (Microsoft)

另一个例子,长时间运行的输出

program LargeOutputDemo;

{$mode objfpc}{$H+}

uses
  Classes, SysUtils, Process; // Process is the unit that holds TProcess

const
  BUF_SIZE = 2048; // Buffer size for reading the output in chunks

var
  AProcess     : TProcess;
  OutputStream : TStream;
  BytesRead    : longint;
  Buffer       : array[1..BUF_SIZE] of byte;

begin
  // Set up the process; as an example a recursive directory search is used
  // because that will usually result in a lot of data.
  AProcess := TProcess.Create(nil);

  // The commands for Windows and *nix are different hence the $IFDEFs
  {$IFDEF Windows}
    // In Windows the dir command cannot be used directly because it's a build-in
    // shell command. Therefore cmd.exe and the extra parameters are needed.
    AProcess.Executable := 'c:\windows\system32\cmd.exe';
    AProcess.Parameters.Add('/c');
    AProcess.Parameters.Add('dir /s c:\windows');
  {$ENDIF Windows}

  {$IFDEF Unix}
    AProcess.Executable := '/bin/ls';

    {$IFDEF Darwin}
      AProcess.Parameters.Add('-recursive');
      AProcess.Parameters.Add('-all');
    {$ENDIF Darwin}

    {$IFDEF Linux}
      AProcess.Parameters.Add('--recursive');
      AProcess.Parameters.Add('--all');
    {$ENDIF Linux}

    {$IFDEF FreeBSD}
      AProcess.Parameters.Add('-R');
      AProcess.Parameters.Add('-a');
    {$ENDIF FreeBSD}
 
    AProcess.Parameters.Add('-l');
  {$ENDIF Unix}

  // Process option poUsePipes has to be used so the output can be captured.
  // Process option poWaitOnExit can not be used because that would block
  // this program, preventing it from reading the output data of the process.
  AProcess.Options := [poUsePipes];

  // Start the process (run the dir/ls command)
  AProcess.Execute;

  // Create a stream object to store the generated output in. This could
  // also be a file stream to directly save the output to disk.
  OutputStream := TMemoryStream.Create;

  // All generated output from AProcess is read in a loop until no more data is available
  repeat
    // Get the new data from the process to a maximum of the buffer size that was allocated.
    // Note that all read(...) calls will block except for the last one, which returns 0 (zero).
    BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);

    // Add the bytes that were read to the stream for later usage
    OutputStream.Write(Buffer, BytesRead)

  until BytesRead = 0;  // Stop if no more data is available

  // The process has finished so it can be cleaned up
  AProcess.Free;

  // Now that all data has been read it can be used; for example to save it to a file on disk
  with TFileStream.Create('output.txt', fmCreate) do
  begin
    OutputStream.Position := 0; // Required to make sure all data is copied from the start
    CopyFrom(OutputStream, OutputStream.Size);
    Free
  end;

  // Or the data can be shown on screen
  with TStringList.Create do
  begin
    OutputStream.Position := 0; // Required to make sure all data is copied from the start
    LoadFromStream(OutputStream);
    writeln(Text);
    writeln('--- Number of lines = ', Count, '----');
    Free
  end;

  // Clean up
  OutputStream.Free;
end.

将代码存到文件里,比如起名test.fpc, 然后编译并执行:

fpc test.fpc
./test

执行后输出:

./test

total 3760

43907011   16 -rw-r--r--   1 skywalk  staff     6208  8  9 22:01 test.o

43906993    8 -rw-r--r--   1 skywalk  staff     3157  8  9 22:01 test.fpc

43907017 3736 -rwxr-xr-x   1 skywalk  staff  1911744  8  9 22:02 test

1447254    0 drwxr-xr-x  47 skywalk  staff     1504  8  9 22:01 ..

43906897    0 drwxr-xr-x   5 skywalk  staff      160  8  9 22:02 .

--- Number of lines = 6----

可以看到成功的调用了 

将命令设为/bin/ps ,也成功了。

AProcess.Executable := '/bin/ps';

但是测试/usr/bin/top没有成功,看代码里,需要输出完毕才能处理,但是像top这样永远在输出的,这段代码就适合了。

Using input and output of a TProcess

See processdemo example in the Lazarus-CCR SVN.

Hints on the use of TProcess关于TProcess的使用提示

当创建跨平台应用的时候,可以使用"{$IFDEF}" 和 "{$ENDIF}"来设定特定操作系统的可执行命令。

Example:

{...}
AProcess := TProcess.Create(nil)

{$IFDEF WIN32}
  AProcess.Executable := 'calc.exe'; 
{$ENDIF}

{$IFDEF LINUX}
  AProcess.Executable := FindDefaultExecutablePath('kcalc');
{$ENDIF}

AProcess.Execute;
{...}

macOS show application bundle in foreground在macOS中以前台方式显示应用程序包

可以通过TProcess启动应用程序包内的可执行文件来启动该应用程序包。例如:

 AProcess.Executable:='/Applications/iCal.app/Contents/MacOS/iCal';

这将启动日历应用,但窗口可能会出现在当前应用之后。为了将应用程序置于前台,你可以使用open工具并带上-n参数:

 AProcess.Executable:='/usr/bin/open';
 AProcess.Parameters.Add('-n');
 AProcess.Parameters.Add('-a'); // optional: specifies the application to use; only searches the Application directories
 AProcess.Parameters.Add('-W'); // optional: open waits until the applications it opens (or were already open) have exited 
 AProcess.Parameters.Add('Pages.app'); // including .app is optional

如果你的应用程序需要参数,你可以在--args参数之后传递所有参数,这些参数将被传递给应用程序:

 AProcess.Parameters.Add('--args');
 AProcess.Parameters.Add('argument1');
 AProcess.Parameters.Add('argument2');

See also: macOS open command.

 

Run detached program运行分离的程序

通常情况下,由你的应用程序启动的程序是一个子进程,当你的应用程序被终止时,这个子进程也会被终止。当你想要运行一个独立运行的程序时,可以使用以下方式:

var
  Process: TProcess;
  I: Integer;
begin
  Process := TProcess.Create(nil);
  try
    Process.InheritHandles := False;
    Process.Options := [];
    Process.ShowWindow := swoShow;

    // Copy default environment variables including DISPLAY variable for GUI application to work
    for I := 1 to GetEnvironmentVariableCount do
      Process.Environment.Add(GetEnvironmentString(I));

    Process.Executable := '/usr/bin/gedit';  
    Process.Execute;
  finally
    Process.Free;
  end;
end;

调试

Redirecting input and output and running under root这个例子在mac没通过

在输入密码后,程序退出,无显示 。应该是passwd密码处理那块没兼容。

另外里面ls的路径Mac下也没有。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值