简体   繁体   English

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

[英]How can I find out the original username a process was started with?

There is a perl script that needs to run as root but we must make sure the user who runs the script did not log-in originally as user 'foo' as it will be removed during the script. 有一个perl脚本需要以root身份运行,但我们必须确保运行该脚本的用户最初不以用户'foo'登录,因为它将在脚本中被删除。

So how can I find out if the user, who might have su-ed several times since she logged in has not impersonated 'foo' at any time in that chain? 那么我如何才能知道自登录以来可能多次上过几次的用户是否在该链中的任何时候都没有冒充'foo'?

I found an interesting perl script that was calling the following two shell scripts, but I think that would only work on Solaris. 我发现了一个有趣的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}\'`;

This needs to work on both Linux and Solaris and I'd rather eliminate the repeated calls to he the shell and keep the whole thing in Perl. 这需要在Linux和Solaris上工作,我宁愿消除对shell的重复调用,并将整个事情保留在Perl中。

Quick and dirty and (UNIX only): 快速和脏和(仅限UNIX):

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

The who am i command returns the owner of the TTY - ie who you were when you logged in. who am i命令返回TTY的所有者 - 即您登录时的身份。

If you want to do this in pure perl: 如果你想在纯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

This will return the correct user, even after multiple su's. 这将返回正确的用户,即使在多个su之后。 This usually freaks out your (less experienced) sysadmins. 这通常吓坏了你(经验较少)的系统管理员。

I recognized a corner case when calling scripts from mc (at least in our RHEL's), which results that the who am i does not output anything. 我从mc调用脚本时认识到了一个极端情况(至少在我们的RHEL中),这导致who am iwho am i没有输出任何东西。 To circumvent that, I produced the following one-liner in bash: 为了避免这种情况,我在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}')

Essentially, this walks backwards on the tree output of ps -u $USER fh and then crops on the topmost username column. 从本质上讲,这会在ps -u $USER fh的树输出上向后移动,然后在最顶端的ps -u $USER fh上裁剪。

Thoughts, better solutions are welcome :-) 想法,更好的解决方案是受欢迎的:-)

Here's a Perl program that checks for direct setuid change: 这是一个检查直接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());

But since you mentioned that the setuid change may have occured anytime before, you probably have to parse the output of ps : I would do it using the following command. 但是既然你提到setuid更改可能在之前的任何时候发生过,你可能需要解析ps的输出:我会使用以下命令来完成它。 This command only uses features defined in POSIX , so I hope it is portable to all kinds of systems: 此命令仅使用POSIX中定义的功能,因此我希望它可以移植到各种系统:

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

Maybe the following is what you want. 也许以下是你想要的。 The function hasBeenUser reads the process table and then follows the process chain from the current process down the parent process. 函数hasBeenUser读取进程表,然后从当前进程沿着父进程跟随进程链。 If any of the processes on the way has a user or real user field equal to the username in question, the function returns a nonzero value. 如果路上的任何进程的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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何启动一个不是原始进程的子进程的新进程? - How can I launch a new process that is NOT a child of the original process? 如何在 shell 脚本中杀死刚启动的 Java 进程? - How can I kill a just started Java process in shell script? 如何找出Linux中正在运行哪个进程的PHP脚本? - How can I find out which PHP script a process is running in Linux? 如何在Debian上使用start-stop-daemon启动的进程重定向进程输出? - How can I redirect process output from a process started with start-stop-daemon on Debian? 我可以捕获我启动的另一个进程的输出吗? - Can I capture the output of another process that I started? 如何处理网址中“ /”之后的数据而不将其视为目录? - How can i process the data after '/ ' in url with out treating it as directory? 如何查找进程是处于死锁状态还是正在等待I / O. - How can I find whether a process is in deadlock or is waiting for I/O 如何使用bash找到某个文件中的哪些行不是由另一个文件中的行启动的? - How can I find which lines in a certain file are not started by lines from another file using bash? 如何找出Linux进程何时退出? - How to find out when process exits in Linux? 如何找出正在读取磁盘的进程? - How to find out which process is reading disk?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM