I'm trying to implement a MySQL database restore from a GPG-encrypted file.
The following works perfectly well:
my $status = system(
"gpg --pinentry-mode loopback --passphrase $passphrase --decrypt $my_encrypted_backup_file"
. " | "
. "mysql --host=myhost --user=myuser --password=mysecret mydatabase"
);
assuming no error conditions.
However, if an error condition occurs during the first process (such as an incorrect $passphrase), $status == 0 which erroneously indicates success. I understand this is because the status is returned from the second process, the mysql process.
Is there a generalized way, using system(), to either obtain the status from all the piped-together processes, or to somehow detect an error if any one such process fails?
BTW, I have tested gpg by itself (without its output being piped into mysql) and it does return an error code when an incorrect $passphrase is entered.
A workaround might be some option flag in mysql that returns an error when it receives nothing from gpg. Another workaround is to break up the processes and use a tmp file of some sort. However, I'd love a more generalized solution. Thanks!
If you need fine control like that, don't use the shell.
Calls to mysql can be replaced with using the DBI and DBD::mysql libraries. gpg can be replaced with Crypt::GPG.
If this is not possible, do the piping yourself with open and its |- and -| modes.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With