首页 > 解决方案 > 使用带有多个管道进程的 Perl system() 检测错误

问题描述

我正在尝试从 GPG 加密文件中实现 MySQL 数据库恢复。

以下效果非常好:

my $status = system(
    "gpg --pinentry-mode loopback --passphrase $passphrase --decrypt $my_encrypted_backup_file"
  . " | "
  . "mysql --host=myhost --user=myuser --password=mysecret mydatabase"
);

假设没有错误条件

但是,如果在第一个过程中发生错误情况(例如不正确的 $passphrase),$status == 0则错误地指示成功。我理解这是因为状态是从第二个进程 mysql 进程返回的。

是否有一种通用的方法,使用system(), 从所有管道连接的进程中获取状态,或者在任何一个这样的进程失败时以某种方式检测错误?

顺便说一句,我已经自己测试gpg过(没有将其输出通过管道传输到 mysql),并且当输入了不正确的 $passphrase 时,它​​确实返回了一个错误代码。

一种解决方法可能是一些选项标志,mysql当它没有从gpg. 另一种解决方法是分解进程并使用某种 tmp 文件。但是,我想要一个更通用的解决方案。谢谢!

标签: perlerror-handlingpipeipc

解决方案


如果您需要这样的精细控制,请不要使用外壳。

调用mysql可以替换为使用DBIDBD::mysql库。gpg可以替换为Crypt::GPG

如果这是不可能的,请自己使用open及其|--|模式进行管道。

open(
    my $gpg_out,
    "-|",
    "gpg --pinentry-mode loopback --passphrase $passphrase --decrypt $my_encrypted_backup_file"
) or die "Can't run gpg: $!";

open(
    my $mysql_in,
    "|-",
    "mysql --host=myhost --user=myuser --password=mysecret mydatabase"
) or die "Can't run mysql: $!";

while(my $line = <$gpg_out>) {
    print $mysql_in $line;
}

close $gpg_out;
close $mysql_in;

推荐阅读