Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何快速找到用户';Perl中的终端PID?_Perl_Terminal_Pid - Fatal编程技术网

如何快速找到用户';Perl中的终端PID?

如何快速找到用户';Perl中的终端PID?,perl,terminal,pid,Perl,Terminal,Pid,下面的代码片段用于查找用户终端的PID,方法是使用ptree并从返回的结果中获取第三个PID。所有终端PID都存储在一个散列中,用户的登录名作为密钥 ## If process is a TEMINAL. ## The command ptree is used to get the terminal's process ID. ## The user can then use this ID to peek the user's terminal. if ($PID =

下面的代码片段用于查找用户终端的PID,方法是使用ptree并从返回的结果中获取第三个PID。所有终端PID都存储在一个散列中,用户的登录名作为密钥

   ## If process is a TEMINAL.
   ## The command ptree is used to get the terminal's process ID.
   ## The user can then use this ID to peek the user's terminal.
   if ($PID =~ /(\w+)\s+(\d+) .+basic/) {
    $user = $1;
    if (open(PTREE, "ptree $2 |")) {
     while ($PTREE = <PTREE>) {
      if ($PTREE =~ /(\d+)\s+-pksh-ksh/) {
       $terminals{$user} = $terminals{$user} . " $1";
       last;
      }
      next;
     }
     close(PTREE);
    }
    next;
   }

我想知道是否有更好的编码方法。这是脚本运行时间最长的部分


注意:这段代码和其他代码片段都在一个循环中,执行了几次。

我认为主要问题是这段代码在一个循环中。您不需要多次运行ptree并解析结果!您需要找到一种方法来运行ptree一次,并将其放入数据结构中,以便以后使用。也许某种简单的散列就足够了。您甚至可以只保留您的%terminals哈希并继续重用它

一些吹毛求疵的话

  • 你的两个“下一步”陈述似乎 对我来说没必要。。。你应该 可以直接移除它们

  • 替换

    $terminals{$user} = $terminals{$user} . " $1";
    
与:

  • 替换您需要的裸字树 正在用作的文件句柄 $ptreeF或类似的。。。使用 光说空话对我来说是不必要的 大约10年前的filehandles:)

  • 我不知道为什么你的$PID变量 都是大写。。。这可能会让人困惑 给代码的读者,因为它 看来有什么事 关于该变量的特殊性,以及 没有


我认为,通过避免重复执行外部命令(
ptree
,在本例中)的开销,您将获得最佳性能改进。我想寻找一个CPAN模块,它为
ptree
正在读取的数据结构提供直接接口。检查名称空间,也许?(我不确定
ptree
是否正确;这可能会使事情复杂化。)

除了上面的建议之外,还有一些仅基于发布的代码片段的附加样式和健壮性说明(如果较大的代码使它们无效,请原谅我):

  • 至少,我会先使用
    严格的
    。这也是个好主意

  • 当您无法
    open()
    使用
    ptree
    命令时,您似乎在默默地忽略该情况。这种情况可能发生的原因有很多,我无法想象你会忽视其中的一些原因,比如

  • 您没有使用
    ptree
    命令的完整路径,而是假设它在您的路径中,并且您路径中的路径是正确的


系统上有多少用户?你能把这个颠倒过来吗?列出系统中的所有-pksh ksh进程及其euid,并从中构建映射-这可能只是ps/ptree的一次执行。

我只是根据您的脚本在这里做了一些琐碎的计时(调用“cat ptree.txt”而不是ptree本身)并证实了我的想法,即您所有的时间都花在创建新的子进程和运行ptree本身上。除非您能够排除调用ptree的需要(也许有一种方法可以打开连接一次并重用它,就像nslookup一样),否则您将看不到任何真正的好处。

您是否考虑过使用“
who-u
”来告诉您哪个进程是给定tty的登录shell,而不是使用
ptree
?这将简化您的搜索-无论您还应该做哪些其他更改。

我正在考虑使用ps获取家长pid,但我需要循环此项以获取曾祖父母的pid。这就是我需要的。谢谢兰克罗



抱歉,有许多用户,每个用户最多可以打开三个终端。整个脚本用于查找正在使用文件的终端。我使用fuser查找使用文件的进程。然后使用ptree查找终端的pid兰克罗


如果您使用一个文件拥有(或可以获得)一个PID列表,并且只需要该PID的所有祖父母,那么肯定有一种更简单的方法

#!perl

use warnings;
use strict;

#***** these PIDs are gotten with fuser or some other method *****
my($fpids) = [27538, 31812, 27541];

#***** get all processes, assuming linux PS *****
my($cmd) = "ps -ef";
open(PS, "$cmd |") || die qq([ERROR] Cannot open pipe from "$cmd" - $!\n);

my($processlist) = {};
while (<PS>) {
    chomp;

    my($user, $pid, $ppid, $rest) = split(/ +/, $_, 4);
    $processlist->{$pid} = $ppid;
}

close PS;

#***** lookup grandparent *****
foreach my $fpid (@$fpids) {
    my($parent) = $processlist->{$fpid} || 0;
    my($grandparent) = $processlist->{$parent} || 0;

    if ($grandparent) {
        #----- do something here with grandparent's pid -----
        print "PID:GRANDPID - $fpid:$grandparent\n";
    }
    else {
        #----- some error condition -----
        print "ERROR - Cannot determine GrandPID: $fpid ($parent)\n";
    }
}

“这是脚本运行时间最长的部分。”其中哪一部分需要时间?ptree的执行,还是结果的混乱?这将有助于避免优化实际上没有任何区别的东西。ptree会减慢程序的速度。毫无疑问。我只是想知道是否有更好的方法来捕获ptree结果中第三行中的进程ID。这就是我从这段代码中所需要的。捕捉PID的方式看起来很合理。唯一的(微观)优化是您知道regexp将不匹配前两行。您可以只数三行,然后只在第三行进行regexp匹配。然而,考虑到时间是在ptree中,这有什么意义呢?请参阅我的另一个答案。AFAICT,ptree在循环中每次都使用不同的参数调用。Correct。ptree被称为循环中的各种时间。谢谢你的挑剔。我已经10多年没有使用perl了,因此此后的任何更改对我来说都是陌生的。我又成了一个傻瓜了。。。事实上,第二个“下一个”可能是必要的,因为它可能是从一个你没有展示的外部循环中逃逸出来的。对不起,有很多用户,每个用户最多可以打开三个终端。整个脚本用于查找正在使用文件的终端。我使用fuser查找使用文件的进程。然后使用ptree查找终端的pid。我打赌一个ps获取所有进程的数据会快得多,而且我看不出用户数量有任何实际问题。谢谢,但是终端进程太多了,我需要使用文件查找。我想用ps获取父进程的pid,但我需要循环这个来获取曾祖父的pid。这就是我需要的。谢谢
    $terminals{$user} .= " $1";
#!perl

use warnings;
use strict;

#***** these PIDs are gotten with fuser or some other method *****
my($fpids) = [27538, 31812, 27541];

#***** get all processes, assuming linux PS *****
my($cmd) = "ps -ef";
open(PS, "$cmd |") || die qq([ERROR] Cannot open pipe from "$cmd" - $!\n);

my($processlist) = {};
while (<PS>) {
    chomp;

    my($user, $pid, $ppid, $rest) = split(/ +/, $_, 4);
    $processlist->{$pid} = $ppid;
}

close PS;

#***** lookup grandparent *****
foreach my $fpid (@$fpids) {
    my($parent) = $processlist->{$fpid} || 0;
    my($grandparent) = $processlist->{$parent} || 0;

    if ($grandparent) {
        #----- do something here with grandparent's pid -----
        print "PID:GRANDPID - $fpid:$grandparent\n";
    }
    else {
        #----- some error condition -----
        print "ERROR - Cannot determine GrandPID: $fpid ($parent)\n";
    }
}
ERROR - Cannot determine GrandPID: 27538 (1)
PID:GRANDPID - 31812:2804
PID:GRANDPID - 27541:27538