Perl IPC::Run3:如何模拟 stdin 到 child 进程的 pty?

Perl IPC::Run3: How to emulate a pty for stdin to child process?

这是 的跟进问题,尽管它们确实不相关。

取下面的示例代码:

use strict;
use warnings;
use IPC::Run3;

sub foo
{
    my $cmd = shift;
    my $CH_IN = "foo\n";
    run3($cmd, $CH_IN, my $CH_OUT, my $CH_ERR);
    return 1;
}
my @LIST = ( 'command','arg1','arg2','arg3' );
foo \@LIST;

以上代码command是另一个perl脚本。 child 脚本调用 who -m 以从终端查找谁拥有 stdin,这是为了在 child 或 parent 脚本被使用 root 或其他通用调用的情况下使用系统用户。

当 parent 调用时,我从 child 得到的错误如下。

Use of uninitialized value in split at child.pl line 354.
WHOAMI is undef

Child 下面的代码。

第 354 行附近的代码:

# Function Name:        'determine_user'
# Function Inputs:      'Optional Scalar: Username to login as'
# Function Returns:     'If username is provided: Scalar: the username provided, If username is not provided: The output of who -m'
# Function Description: 'Figures out the user to login as'
sub determine_user
{
    my $USER = shift;
    if (!defined $USER)
    {
        my $WHOAMI;
        open my $WHOPROC, q{-|}, 'who -m'                   or die "Unable to open 'who -m' for output.\n";
        $WHOAMI=<$WHOPROC>;
        close $WHOPROC                                      or die "Unable to close 'who -m'.\n";
        $USER       = split m{[\s]+}xms, $WHOAMI          or die "WHOAMI is undef\n";    # This is line 354
    }

    chomp $USER;

    return $USER;
}

当我从命令行调用 child 脚本时,上面的代码工作得很好,但是由于 who -m 试图查看谁拥有终端的标准输入,并且终端已被替换parent 脚本,我相信我需要找到一种方法来在 运行 从 parent 中调用 who -m 时使用模拟 pty。无论是通过修改 child 还是 parent 或两者都没有关系,因为我可以修改两者。

所以我的问题是:我如何 运行 parent 内部的 child 并且仍然依赖 who -m 的输出被馈送到 child?

编辑:ikegami 在他的回答评论中提供了最佳解决方案。它没有回答问题,但确实解决了我的问题。

My ssh daemon sets env var SSH_TTY, so you could use perl -MFile::stat -E'say scalar(getpwuid(stat($ENV{SSH_TTY})->uid))'. Default to scalar(getpwuid($>)) if it's not set.

who -m 专门给出了有关连接到其标准输入的终端的信息。

-m     only hostname and user associated with stdin

您更换了终端,因此无法从中获取信息。

$ who -m
ikegami  pts/1        ...

$ who -m </dev/null

$

您可以删除 -m 并只使用 who

$ who </dev/null
ikegami  pts/1        ...

或者,您可以使用 $ENV{USER}getpwuid($>)(执行进程的用户名)。