首选的跨平台 IPC Perl 模块是什么?

2024-04-30

我想创建一个简单的 IO 对象,它代表一个向另一个程序打开的管道,我可以在应用程序运行时定期写入另一个程序的 STDIN。我希望它是防弹的(因为它可以捕获所有错误)并且是跨平台的。我能找到的最佳选择是:

open

sub io_read {
    local $SIG{__WARN__} = sub { }; # Silence warning.
    open my $pipe, '|-', @_ or die "Cannot exec $_[0]: $!\n";
    return $pipe;
}

优点:

  • 跨平台
  • Simple

缺点

  • No $SIG{PIPE}捕获管道程序中的错误
  • 是否发现其他错误?

IO::Pipe

sub io_read {
    IO::Pipe->reader(@_);
}

优点:

  • Simple
  • 返回 OO 接口的 IO::Handle 对象
  • 由 Perl 核心支持。

缺点

  • 仍然没有$SIG{PIPE}捕获管道程序中的错误
  • Win32 不支持(或者至少,它的测试 https://metacpan.org/source/GBARR/IO-1.25/t/io_pipe.t被跳过)

IPC::Run

IPC::Run 中没有用于写入文件句柄的接口,仅附加到标量。这看起来……很奇怪。

IPC::运行3

这里也没有文件句柄接口。我可以使用代码引用,该引用将被重复调用以假脱机到子进程,但查看源代码,它似乎实际上写入临时文件,然后打开它并假脱机its管道命令的内容STDIN. Wha?

IPC::Cmd

仍然没有文件句柄接口。


我在这里缺少什么?似乎这应该是一个已解决的问题,但令我感到惊讶的是,事实并非如此。 IO::Pipe 最接近我想要的,但缺乏$SIG{PIPE}错误处理和缺乏对 Windows 的支持令人苦恼。 JDWIM 的管道模块在哪里?


感谢 @ikegami 的指导,我发现在 Perl 中交互式读取和写入另一个进程的最佳选择是 IPC::Run。但是,它要求您正在读取和写入的程序在完成对其 STDOUT 的写入后具有已知的输出,例如提示。这是一个执行的例子bash,运行了吗ls -l,然后打印该输出:

use v5.14;
use IPC::Run qw(start timeout new_appender new_chunker);

my @command = qw(bash);

# Connect to the other program.
my ($in, @out);
my $ipc = start \@command,
    '<' => new_appender("echo __END__\n"), \$in,
    '>' => new_chunker, sub { push @out, @_ },
    timeout(10) or die "Error: $?\n";

# Send it a command and wait until it has received it.
$in .= "ls -l\n";
$ipc->pump while length $in;

# Wait until our end-of-output string appears.
$ipc->pump until @out && @out[-1] =~ /__END__\n/m;

pop @out;
say @out;

因为它作为 IPC 运行(我假设),bash写入 STDOUT 后不会发出提示。所以我用new_appender()函数让它发出一些我可以匹配的东西来找到输出的结尾(通过调用echo __END__)。我还在调用后使用了匿名子例程new_chunker将输出收集到数组中,而不是标量中(只需将对标量的引用传递给'>'如果你想要的话)。

所以这可行,但在我看来,由于很多原因,它很糟糕:

  • 通常没有有用的方法来知道 IPC 控制的程序是否已完成打印到其 STDOUT。相反,您必须在其输出上使用正则表达式来搜索通常意味着已完成的字符串。
  • 如果它不发出一个,你必须欺骗它发出一个(就像我在这里所做的那样——上帝保佑我是否应该有一个名为__END__, 尽管)。如果我控制数据库客户端,我可能必须发送类似的内容SELECT 'IM OUTTA HERE';。不同的应用需要不同的new_appender hacks.
  • 书写魔法$in and $out标量感觉很奇怪并且是远距离作用。我不喜欢它。
  • 人们无法像文件句柄那样对标量进行面向行的处理。因此,他们的效率较低。
  • 使用能力new_chunker获得面向行的输出很好,尽管仍然有点奇怪。不过,假设 IPC::Run 有效地缓冲了程序的输出,这会恢复一些从程序读取输出的效率。

我现在意识到,尽管 IPC::Run 的界面可能会更好一点,但总体而言,IPC 模型的弱点尤其使其难以处理。没有通用的 IPC 接口,因为人们必须了解太多正在运行的特定程序的细节才能使其工作。这没关系,maybe,如果您确切地知道它将如何对输入做出反应,并且能够可靠地识别它何时完成发出输出,并且不需要太担心跨平台兼容性。但这还远远不足以满足我对一种普遍有用的方式来与 CPAN 模块中的各种数据库命令行客户端进行交互的需求,该模块可以分发到整个操作系统主机。

最后感谢评论里的打包建议一篇博文 http://www.justatheory.com/computers/databases/dbi-in-sqitch.html,我决定放弃使用 IPC 来控制这些客户端,而使用the DBI http://metacpan.org/module/DBI, 反而。它提供了优秀的API,健壮、稳定、成熟,并且没有IPC的缺点。

我对那些追随我的人的建议是:

  • 如果您只需要执行另一个程序并等待它完成,或者在运行完成后收集其输出,请使用IPC::系统::简单 https://metacpan.org/module/IPC%3a%3aSystem%3a%3aSimple。否则,如果您需要与其他东西交互交互,请尽可能使用 API。如果不可能,那么使用类似的东西IPC::Run https://metacpan.org/module/IPC%3a%3aRun并尽力充分利用它,并准备好放弃大量时间来让它“恰到好处”。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

首选的跨平台 IPC Perl 模块是什么? 的相关文章

  • 在 Perl 中查找标量变量的数据类型

    我有一个接受用户输入的函数 输入可以是整数 浮点数或字符串 我有三个重载函数 应该根据输入数据的数据类型调用它们 例如 如果用户输入一个整数 比如100 则应该调用具有整数参数的函数 如果用户输入字符串 例如 100 则应调用具有字符串参数
  • Perl 如何存储/处理非常大的数字?是否应该使用模块来代替 Perl 的默认处理方法?

    我需要添加 50 位数字 因此我将它们作为 字符串 处理 并编写了自己的函数将它们相加 后来 为了它的地狱 我尝试了这个 readFile shift ARGV sub readFile my file shift contains a b
  • C中的pipe()和fork()

    我需要创建两个子进程 一个子进程需要运行命令 ls al 并将其输出重定向到下一个子进程的输入 而下一个子进程又将对其输入数据运行命令 sort r n k 5 最后 父进程需要读取该数据 已排序的数据 并将其显示在终端中 终端中的最终结果
  • 将日期转换为指定格式并比较两个日期

    给定两个日期 Date1 format yyyy mm dd hh mm ss eg 2013 05 21 07 47 21 Date2 format Day Month date hh mm ss yyyy eg Thu Aug 1 09
  • Emacs cperl - 常量块中的缩进

    我正在运行基于 GNU Emacs 24 3 50 2 的 Aquamacs 3 0a cperl 版本是 6 2 当我编辑 Perl 常量块时 我得到了我不想要的额外缩进 use constant ONE gt 1 TWO gt 2 TH
  • 如何将 cpanminus 与本地 CPAN::Mini 一起使用?

    我已经创建了自己的 CPAN 本地副本minicpan http search cpan org rjbs CPAN Mini 1 111007 bin minicpan并设法重新配置 cpan 来使用它 太棒了 但是我将如何使用它cpan
  • 如何使用管道字符分隔符分隔字段

    我知道这个问题已经被问过 但我发现没有一个解决方案对我有用 我有一个程序 其输出如下 COUNT 293 1 lps 我对第二个字段感兴趣 但是这些尝试都没有成功 spawn 1 cut d f2 spawn 1 cut d f2 spaw
  • Perl 中的 Fork 无法在从文件读取的 while 循环内工作

    我正在运行一个 while 循环来读取文件中的每一行 然后使用该行的数据将进程分叉给子进程 N 行之后 我想等待子进程结束并继续接下来的 N 行 等等 它看起来像这样 while w
  • 多维哈希排序 - Perl [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我真的需要一些帮助来理解这个哈希并对
  • 真实设备中的 Android strace

    我有以下情况 我想监控Android手机上的系统调用 所以 我编写了一个脚本来做到这一点 使用 Android 模拟器可以完美地工作 将应用程序的痕迹写入我的 Ubuntu 上的特定文件中 问题是当我连接一个真实的手机来分析它时 它在结果文
  • 为什么Perl的SUPER调用不使用箭头方法?

    我注意到 当您调用超类的方法时 您需要执行以下操作 my self class gt SUPER new 为什么不是这样 my self class gt SUPER gt new 我怀疑是因为 class gt SUPER gt new
  • Perl Moose TypeDecorator 错误。我该如何调试?

    我最近遇到了一个问题 非常感谢您的见解 我在圣诞节前在 PerlMonks 上发布了类似的问题 并提供了一些从 MooseX Declare 切换的反馈 http www perlmonks org node id 877703 1 我现在
  • Perl 中如何释放内存?

    我的代码如下所示 my var my var new while 1 while my k v each var a sub v var A map var var new keys var new var new B sub a sub
  • linux + ksh + 向下舍入或向上舍入 - 浮点数

    在我的 ksh 脚本中 我只需要计算整数 有时我会得到浮点数 例如 3 49 或 4 8 等 所以我需要根据以下规则将浮点数转换为整数 示例 3 49 will be 3 2 9 will be 3 4 1 will be 4 23 51
  • 为什么我不应该使用 UNIVERSAL::isa?

    根据这个 http perldoc perl org UNIVERSAL html http perldoc perl org UNIVERSAL html 我不应该使用 UNIVERSAL isa 而应该使用 obj gt isa 或 C
  • 如何同时正确使用管道和信号?

    我有 2 个孩子 我想将信号从孩子发送到父母 并将答案 随机数 为什么 为什么不 命名管道从父母发送到每个孩子 我有这个代码 include
  • 如何为不同的 Perl 应用程序安装专门的环境?

    就功能而言是否有与 Python 相同或接近的东西虚拟环境 http pypi python org pypi virtualenv what it does 但是对于 Perl 来说呢 我已经用 Python 进行了一些开发 并且将非系统
  • Path::Class::File 或 ::Dir & Moose 初始化和强制

    目前有 package Local use warnings use Moose use Method Signatures Simple use Path Class File use Path Class Dir method buil
  • Perl 中可以使用哪种语法糖来减少左/右值运算符与 if 语句的代码?

    那里有很多语句 因为 Perl 是一种非常甜蜜的语言 但任何语言中最常用的语句都是 if 语句和设置值的组合 我想我已经找到了很多 但仍然存在一些空白 最终 目标是不必多次编写变量名 这是我到目前为止所拥有的 r s r s unless
  • 为什么我只得到第一个捕获组?

    https stackoverflow com a 2304626 6607497 https stackoverflow com a 2304626 6607497 and https stackoverflow com a 370042

随机推荐

  • TypeScript / JavaScript - 导入所有类型

    如何从某个文件导入所有类型 假设我有myClass ts and otherClass ts 我想从中导入所有课程otherClass ts 我见过很少的导入语法 import ClassA ClassB ClassC from other
  • 清除另一个应用程序的 Symfony 缓存

    我想通过后端应用程序中的操作清除前端应用程序的缓存 我怎样才能实现这个目标 我相信在 symfony 1 2 中执行此操作的正确方法如下 sfContext switchTo frontend switch to the environme
  • 如何在 Kotlin 中列出字段注释?

    我有一个注释 public interface Field String value 和java类 由它注释 public class Animal Field name private String name 我尝试通过下一个代码列出所有
  • 动态下拉框?

    我有一个名为类别的数据库表 如下所示 我正在尝试做一个动态下拉框 索引脚本显示为
  • 如何使用 C# 在 WinForm 中手动绑定到蓝牙低功耗设备?

    这个问题的回答大多是 Windows UWP 发现后连接到 BLE 设备 https stackoverflow com questions 35420940 windows uwp connect to ble device after
  • 由于配置错误,执行失败:Java 中的 Lambda 代理响应格式错误

    我的函数是通过代理 API 网关调用的 该函数执行正常 但 API 调用返回 502 错误 Mon Dec 30 18 16 25 UTC 2019 Endpoint response body before transformations
  • 在 Windows 上安装 Apache Spark

    我需要安装阿帕奇火花 http spark apache org 在 Windows 机器上 根据文档 我应该在我的机器上安装 sbt 并覆盖其默认选项以使用最大 2G RAM 经过多次尝试后 我决定选择 maven 我覆盖了默认选项以使用
  • 检查类型是否为未知类型

    有没有办法检查类型参数T事实上是unknown type 我知道可以检查any 解决方案在这里 https stackoverflow com a 55541672 11153160 但想知道unknown 最简单的解决方案是这样的 typ
  • CRTP:表达式模板的编译器相关问题

    我遇到了以下代码 存储在 crtp cc 中 的编译器相关问题 include
  • 是否可以在 SignalR hub 方法中返回预编码的 JSON 字符串?

    在 MVC 项目中 我在集线器上有一个与此类似的方法 public string Foo return DoCrazyThingThatReturnsJson 不幸的是 SignalR 或其他东西 接受编码的 JSON 字符串并愉快地对其进
  • 使某些代码只运行一次

    我有一些代码只想在 MainViewController 中运行一次 它应该在每次用户启动应用程序时运行 但仅在 MainViewController 加载后运行 我不想运行它 void applicationDidFinishLaunch
  • 在 Google App Engine 上运行的 Spring Boot Web 应用程序 - 引发 jetty 异常

    当我执行时gradlew appengineRun 我一直得到 Starting a Gradle Daemon subsequent builds will be faster Mar 26 2018 5 47 48 PM java ut
  • 来自 alpine 软件包存储库的 Numpy 无法导入 c 扩展

    我正在制作一个需要 pandas 和 numpy 的 docker 映像 但通过 pip 安装大约需要 20 分钟 这对于我的用例来说太长了 然后我选择从 alpine 软件包存储库安装 pandas 和 numpy 但似乎无法正确导入 n
  • Java日期格式转换

    我目前正在从请求对象中提取三个表单字段输入 日 月 年 该月的第 11 天为 Day 11 12 月为 12 月 今年将是 2010 年 我需要将其转换为 Java Date 对象 但由于发生了很多变化 我不确定将其存储在 java 对象中
  • Code::Blocks 中的单个项目中有多个主要 C++ 文件?

    我不经常写代码 有时我连续 6 个月每天编写代码 然后长达 2 年不编写代码 这种方法迫使我保留一堆我 以及其他更好的程序员 编写的代码或参考代码 时隔很长一段时间 我在写代码时都会提到这个 库 我读了它 我执行了它 这对我精神焕发有很大帮
  • 查找 system.out.println 代码中的位置

    假设我正在一个非常大的项目中工作 并且注意到有一个空的打印行 所以我假设有一个 System out println 位于代码中的某个位置 除了在整个项目中搜索所有出现的 System out println 之外 我该如何尝试找出它在哪里
  • 在 C++ 中类继承的情况下强制延迟方法解析

    考虑以下类结构 class foo public int fun cout lt lt in foo lt lt endl class bar class1 public foo public int fun cout lt lt in b
  • 编译 XNA 项目时,无法执行请求的操作错误

    第二次编译项目时 出现以下错误消息 我必须关闭 VS 2010 重新加载时它会编译 如果我做出改变 那么问题又回来了 无法复制文件 obj x86 Debug MyFile dll 无法对打开的用户映射部分的文件执行请求的操作 我因为另一个
  • Swift NSPredicate 不在

    我有一个包含 X 个项目的数组 我需要通过 uid 过滤掉特定项目 我写了以下谓词 我认为它是正确的 我面临的问题是 Swift 编译器只允许我使用接受 argumentArray 的初始化程序 let uids 34885a9f0897f
  • 首选的跨平台 IPC Perl 模块是什么?

    我想创建一个简单的 IO 对象 它代表一个向另一个程序打开的管道 我可以在应用程序运行时定期写入另一个程序的 STDIN 我希望它是防弹的 因为它可以捕获所有错误 并且是跨平台的 我能找到的最佳选择是 open sub io read lo