问题
This is a follow up question to IPC::Open3 and determining if child is waiting for input though they admittedly are not related.
Take the following sample code:
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;
For the above code command
is another perl script. The child script calls who -m
to find who owns stdin from the terminal, which is intended to be used in case the child or parent script is called using root or another generic system user.
The error I get from the child when called by the parent is as follows.
Use of uninitialized value in split at child.pl line 354.
WHOAMI is undef
Child code below.
Code around line 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;
}
The code above works just fine when I call the child script from the command line, but since who -m
is trying to see who owns stdin of the terminal and the terminal has been replaced by the parent script, I believe I need to find a way to call who -m with an emulated pty when running from the parent. Whether that's by modifying the child or the parent or both doesn't matter, as I can modify both.
So my question is: how can I run the child inside of the parent and still rely on the output of who -m
being fed to the child?
EDIT: ikegami has provided the best solution in the comments of his answer. It does not answer the question, but it does solve my problem.
My ssh daemon sets env var
SSH_TTY
, so you could useperl -MFile::stat -E'say scalar(getpwuid(stat($ENV{SSH_TTY})->uid))'
. Default toscalar(getpwuid($>))
if it's not set.
回答1:
who -m
specifically gives information about the terminal connected to its stdin.
-m only hostname and user associated with stdin
You've replaced the terminal, so you can't obtain information from it.
$ who -m
ikegami pts/1 ...
$ who -m </dev/null
$
You could drop the -m
and use just who
.
$ who </dev/null
ikegami pts/1 ...
Alternatively, you could use $ENV{USER}
or getpwuid($>)
(the name of the user as which the process is executing) instead.
来源:https://stackoverflow.com/questions/41475421/perl-ipcrun3-how-to-emulate-a-pty-for-stdin-to-child-process