假设父shell的用户是foo
。如果您运行类似sudo -u bar -i
的内容,那么您将使用用户bar
的子shell。那么,我怎样才能找到子shell中父shell的用户?也就是说,在上面的例子中,我怎么知道父shell的用户是foo
?
更新
我理解,通过一些黑客攻击,可以使用ps
实现此目的。但是,如果一切可能的话,我会对一种不那么苛刻和更标准的方式更感兴趣。
更新2
在答案的帮助下,我最终采用了以下解决方案:
# from parent shell, user is foo
$ sudo -u bar -i PARENT=foo
# from child shell, show parent user foo
$ ps u -p $PPID | grep PARENT | cut -d= -f2
答案 0 :(得分:2)
首先,bash有一个很好的内置变量$PPID
,它保存其父进程的进程ID。
其次,/proc/<pid>/status | egrep '^Uid:' | awk '{ print $2 }'
可用于获取正在运行进程的用户ID。
这意味着以下命令将撤消直接父进程的用户ID:
cat /proc/$PPID/status | egrep '^Uid:' | awk '{ print $2 }'
所以,在su的例子中,你需要上升两个级别,因为su本身已经在新用户下运行了。因此,以下命令可用于检索产生过程的用户ID:
cat /proc/$(cat /proc/$PPID/stat | awk '{ print $4 }')/status | egrep '^Uid:' | awk '{ print $2 }'
请注意,$PPID
在存储的bash脚本中使用时的行为可能会有所不同。
答案 1 :(得分:1)
您可以执行ps -ef
并按照PPID
到PID
匹配的列表,直到找到您感兴趣的父进程。对于Linux,ps
通常会给出第一列中进程的名称。
例如,我只输入ps -ef
,并且(在我的命令之前忽略了大约一百行)得到这个(这很短,应该清楚):
UID PID PPID C STIME TTY TIME CMD
tom 2925 2887 0 19:30 pts/0 00:00:00 screen
tom 2926 2925 0 19:30 ? 00:00:02 SCREEN
tom 2981 2926 0 19:30 pts/3 00:00:00 -bin/tcsh
tom 3005 2981 0 19:30 pts/3 00:00:00 ded
tom 11877 2926 0 19:56 pts/4 00:00:00 -bin/tcsh
tom 12103 11877 0 20:28 pts/4 00:00:01 vile
tom 12254 12103 0 20:54 pts/4 00:00:00 sh -c ps -ef
tom 12255 12254 0 20:54 pts/4 00:00:00 ps -ef
并且使用sudo
,vile仍然是父级,但是具有不同的进程链:
tom 12103 11877 0 20:28 pts/4 00:00:01 vile
tom 12302 12103 0 20:59 pts/4 00:00:00 sh -c sudo ps -ef
root 12303 12302 0 20:59 pts/4 00:00:00 sudo ps -ef
root 12306 12303 0 20:59 pts/4 00:00:00 ps -ef
Linux ps
也有-H
和--forest
个选项,试图让结构更具可读性(但后者特别是通过缩进太多来打败它)。
例如,这是一个解析输出的脚本,并指出层次结构中发生登录shell的位置。 shell 名称没有标准,但登录shell通常显示为带领&#34; - &#34;在CMD
列中:
#!/usr/bin/perl -w
use strict;
use POSIX qw(getpid);
sub field($$$) {
my $text = shift;
my $first = shift;
my $last = shift;
$text = substr $text, $first, ($last - $first);
$text =~ s/^\s+//;
return $text;
}
our %processes;
# Get the current process-id
our $pid = getpid();
# Get the user for the current process
# Get a list of all processes, to reduce
if ( open ( my $fh, "ps -ef|" ) ) {
my @data = <$fh>;
close $fh;
if ( $#data > 0 ) {
my $head = $data[0];
# formats differ, but this is an example which "works"
my $c_uid = (index $head, "UID") + 3;
my $c_pid = (index $head, "PID") + 3;
my $c_ppid = (index $head, "PPID") + 4;
my $c_cmd = (index $head, "CMD");
for my $n ( 1 .. $#data ) {
chomp $data[$n];
my $n_uid = &field($data[$n], 0, $c_uid);
my $n_pid = &field($data[$n], $c_uid, $c_pid);
my $n_ppid = &field($data[$n], $c_pid, $c_ppid);
my $n_cmd = &field($data[$n], $c_cmd, length($data[$n]));
$n_uid = getpwuid($n_uid) if ( $n_uid =~ /^\d+$/ );
my %obj;
$obj{NAME} = $n_uid;
$obj{CMD} = $n_cmd;
$obj{PPID} = $n_ppid;
$processes{$n_pid} = \%obj;
}
while ( $processes{$pid} ) {
my %obj = %{ $processes{$pid} };
printf "pid %d %s \"%s\"\n", $pid, $obj{NAME}, $obj{CMD};
printf "** login %s\n", $obj{NAME} if ( $obj{CMD} =~ /^-/ );
$pid = $obj{PPID};
}
}
}
1;
并输出:
pid 2724 tom "/usr/bin/perl -w ./my-parent"
pid 2723 tom "sh -c ./my-parent"
pid 2717 tom "ded /tmp"
pid 2686 tom "-tcsh"
** login tom
pid 2685 tom "sshd: tom@pts/0 "
还使用OSX进行测试(第一列是数字):
pid 3287 tom "/usr/bin/perl -w ./my-parent"
pid 2187 tom "vile /private/tmp/my-parent"
pid 1905 tom "ded /tmp"
pid 1876 tom "-tcsh"
** login tom
pid 1868 root "su - tom"
pid 1574 thomas "ded"
pid 1569 thomas "-bash"
** login thomas
pid 1563 root "login -pf thomas"
pid 1561 thomas "/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal"
pid 468 thomas "/sbin/launchd"
pid 1 root "/sbin/launchd"
答案 2 :(得分:1)
您可以使用$PPID
变量来帮助您完成一两个命令:
#!/bin/bash
USER=`ps u -p $PPID | awk '{print $1}'|tail -1`
echo $USER
答案 3 :(得分:0)
如果您像我一样,那么您真正想要的是调用 sudo
的用户的名称。如果是这样,那么您需要按照 this question
$SUDO_USER