如何捕获子进程的输出?

如何捕获子进程的输出?

我试图捕捉 sftp 的密码提示,但不知何故它不是来自 STDIN 或 STDERR。它可能来自子流程。

以下是我的测试。我尝试将密码提示重定向到文件。我尝试了文件句柄号 1 到 4。但没有成功。

mypc:/home/myname$ sftp localhost >/tmp/junk
myname@localhost's password:

mypc:/home/myname$ sftp localhost 2>/tmp/junk
myname@localhost's password:

mypc:/home/myname$ sftp localhost 3>/tmp/junk
myname@localhost's password:

mypc:/home/myname$ sftp localhost 4>/tmp/junk
myname@localhost's password:

这是我的操作系统

mypc:/home/myname$ uname -a
Linux mypc 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

mypc:/home/myname$ which sftp
/usr/bin/sftp

我需要捕获它的原因是因为我正在编写一个 Perl 脚本来测试 sftp 连接。如果我被允许将 Perl 的 Expect 模块安装在我的工作场所中,我本可以使用它。

谢谢

答案1

1. 为什么简单的指令无法捕获密码提示?

  • 该提示可能来自子进程。
  • 这可能是一个特殊的设计,以便提示符不会与用户可能捕捉到的 stdout 和 stderr 混合在一起。

参考:当 stdout 和 stderr 都重定向时,ssh 如何/为什么输出到 tty?

2.如何捕捉?

我们可以使用 Perl 的 Expect 模块。测试如下图所示

myname@mypc:/mnt/c/users/myname$ perl -MExpect -e 'print ${Expect->spawn("sftp localhost")->expect(3, [qr/.+/])}[2], "\n";'
umyname@localhost's password:

myname@mypc:/mnt/c/users/myname$ perl -MExpect -e 'print ${Expect->spawn("sftp localhost")->expect(3, [qr/.+/])}[2], "\n";'  >/tmp/junk

这基本上将从 tty 到 stdout 的所有内容分组。

相关内容