如何找到进程启动时的原始用户名?

时间:2010-03-14 11:15:16

标签: linux perl shell process solaris

有一个perl脚本需要以root身份运行,但我们必须确保运行该脚本的用户最初没有以用户“foo”身份登录,因为它将在脚本中被删除。

那么我如何才能知道自登录以来可能多次上过几次的用户是否在该链中随时冒充“foo”?

我发现了一个有趣的perl脚本,它调用了以下两个shell脚本,但我认为这只适用于Solaris。

my $shell_parent = 
`ps -ef | grep -v grep | awk \'{print \$2\" \"\$3}\' | egrep \"^@_\" | awk \'{print \$2}'`;

my $parent_owner = 
`ps -ef | grep -v grep | awk \'{print \$1\" \"\$2}\' | grep @_ | awk \'{print \$1}\'`;

这需要在Linux和Solaris上运行,我宁愿消除对shell的重复调用,并将整个内容保存在Perl中。

4 个答案:

答案 0 :(得分:1)

快速而又脏(和仅限UNIX):

my $user = (split /\s/,`who am i`)[0];

who am i命令返回TTY的所有者 - 即您登录时的身份。

如果你想在纯perl中这样做:

use POSIX;
my $tty = POSIX::ttyname(1); # The tty we are running in
my $uid = (stat $tty)[4];    # The owner uid of that tty
my $user = getpwuid($uid);   # The user with that uid

这将返回正确的用户,即使在多次su后也是如此。这通常吓坏了你(经验较少)的系统管理员。

答案 1 :(得分:0)

这是一个检查直接setuid更改的Perl程序:

#! /usr/bin/perl

sub callingUser() {
    my ($login, $pass, $uid, $gid) = getpwuid($<);
    return $login;
}

sub effectiveUser() {
    my ($login, $pass, $uid, $gid) = getpwuid($>);
    return $login;
}

printf("Real user name: %s\n", effectiveUser());
printf("Calling user name: %s\n", callingUser());

但是既然你提到setuid更改可能在之前的任何时候发生过,你可能需要解析ps的输出:我会使用以下命令来完成它。此命令仅使用POSIX中定义的功能,因此我希望它可以移植到各种系统中:

ps -e -o pid,ppid,user,ruser

答案 2 :(得分:0)

也许以下是你想要的。函数hasBeenUser读取进程表,然后从当前进程沿着父进程跟踪进程链。如果路上的任何进程的userreal user字段等于相关用户名,则该函数返回非零值。

#! /usr/bin/perl

sub hasBeenUser($) {
        my ($username) = @_;

        my $procs = {};
        open(PS, "ps -e -o pid,ppid,user,ruser |") or die;
        while (defined(my $line = <PS>)) {
                next unless $line =~ m"^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+$";
                my ($pid, $ppid, $user, $ruser) = (int($1), int($2), $3, $4);
                $procs->{$pid} = [$pid, $ppid, $user, $ruser];
        }
        close(PS) or die;

        my $pid = $$;
        while (exists($procs->{$pid})) {
                my $proc = $procs->{$pid};
                delete $procs->{$pid}; # don't risk ending in an endless loop.
                warn "D: checking process $pid\n";
                if ($proc->[2] eq $username || $proc[3] eq $username) {
                        warn "E: process $pid was called by $username.\n";
                        return 1;
                }
                last if $pid < 2;
                $pid = $proc->[1];
        }
        return 0;
}

hasBeenUser("del"); # should return 0
hasBeenUser("root"); # should return nonzero

答案 3 :(得分:0)

我从mc调用脚本时识别出一个极端情况(至少在我们的RHEL中),这导致who am i不输出任何内容。为了避免这种情况,我在bash中制作了以下单行:

REALUSERNAME=$(ps uhp `ps -AjH | grep \`ps -u $USER fh | awk '{ print $0; if(index($0, "ps -u $USER fh")) exit 0;}' | tac | awk '{if(!index($0, "\\\\\_")){print $1; exit 0;}}'\` | awk '{print $3}'` | awk '{print $1}')

基本上,这会在ps -u $USER fh的树输出上向后移动,然后在最顶端的用户名列上裁剪。

思考,欢迎更好的解决方案: - )