我实际上很喜欢使用 STDIN 的想法,所以如果有人在此页面上亮起,请考虑是否可以在您的情况下使用 STDIN。
但我想发布我自己的答案,它使用 Expect Perl 模块,因为:
- 我使用了它,并且证明它至少可以在 Linux 上运行(尽管评论中的问题提到该模块在 Windows 上运行时存在问题);
- 由于问题的标题没有提及
cryptsetup
(可以接受 STDIN 上的密码),因此 Expect 模块在这里就像一个通用解决方案,它应该适用于其他工具;
我的解决方案如下。我没有阅读太多文档,所以可能有更好的方法来做到这一点。对我来说,掌握对象实例化的概念和期望/发送方法就足够了。
您创建一个实例,就像您刚刚在终端中启动一个程序一样:
my $exp = Expect->new('progName', ($arg1, $arg2, $etc));
expect
然后可以通过(等待/确认程序向用户的输出)和send
(允许用户“输入”)方法与它进行交互。
expect
可以在标量或列表上下文中调用(我使用了列表一个),它接受一个字符串或正则表达式,期望输出什么以及持续多长时间。如果在指定时间内没有出现预期的输出,则会引发错误:
#sec to wait for #use regexp (don't match exactly) #regexp to match against
my @out = $exp->expect(10, '-re', 'smth');
send
只接受输入
$exp->send('some chars');
就是这样,只需要创建一个脚本,它就可以像人类用户一样工作。
以防万一它对某人有用,我将发布我的完整的 cryptsetup 特定解决方案(我已经在一个虚拟卷上对其进行了测试,它能够挂载,并且我已经在一个真实卷上运行它6k 组合尝试没有任何明显的问题):
*我忘了在这里关闭文件描述符,所以应该close($fd)
在适当的地方添加
use strict;
use warnings;
use feature 'say';
# I installed Expect with its deps locally in my situation, so I had to change @INC
BEGIN {
unshift(@INC, './perl-mods/lib/perl5/');
unshift(@INC, './perl-mods/lib/perl5/x86_64-linux-thread-multi/');
}
use Expect;
my $devName = '/dev/sdb3';
my $combinationsFileName = 'combs.txt';
open(my $fd, '<', $combinationsFileName);
my $lineCount = 0;
while (<$fd>) {
my $pass = $_;
chomp($_);
say $_ . ' ' . ++$lineCount;
my $exp = Expect->new('cryptsetup', ('open', $devName, 'crypt-vol')) or die 'err 1';
my @out = $exp->expect(10, '-re', 'Enter passphrase') or die 'err 2';
$exp->send($pass);
@out = $exp->expect(10, '-re', 'No key available') or die 'err 3';
#if cryptsetup returned an error code
if ($out[1]) {
die $out[1] . ' ' . $pass;
}
}