我制作了以下脚本来搜索某些进程,显示每个进程使用pflags,并在找到带有“pause”的单词时停止:
!cat find_pause
#!/usr/bin/perl -W
use warnings;
use strict;
if (open(WCF,
"ps -ef | grep '/transfile' | cut -c10-15 | xargs -n1 pflags 2>&1 |"
)) {
while (<WCF>) {
next if ($_ =~ /cannot/);
print $_;
last if ($_ =~ /pause/);
}
close(WCF);
}
它有效,但我想知道是否有更好的方法来做到这一点。
pause
是一个低级系统调用。与read
,nanosleep
,waitid
等
使用此脚本,我想查找卡在pause
调用中的进程。我们正试图在我们的系统中找到一个错误,我们认为它可能与此有关。
答案 0 :(得分:1)
对此有两种可能的改进,具体取决于:
您是否真的需要打印pflags
命令的确切输出或其中的一些信息(例如PID和标志列表?)
pflags输出中的“暂停”是什么意思?在“proc”或“pflags”man-pages中没有任何地方,所有实际的标志都是大写的。根据其含义,可以在“/ proc” - Proc::processTable::Process的本机Perl实现中找到它。
例如,Process对象包含所有标志(in a bit vector)和进程状态(我怀疑“暂停”可能是进程状态)。
如果这些问题的答案是“Proc::processTable::Process包含足够的信息以满足我的需求”,那么更好的解决方案就是使用它:
#!/usr/bin/perl -W
use warnings;
use strict;
use Proc::ProcessTable;
my $t = new Proc::ProcessTable;
foreach $p ( @{$t->table} ) {
my $flags = $p->pid; # This is an integer containing bit vector.
# Somehow process $flags or $p->status to find "if the process is paused"
print "$flags\n";
last if paused($p); # No clue how to do that without more info from you
# May be : last if $p->status =~ /paused/;
}
但是,如果本机Perl进程没有足够的信息(不太可能,但可能),或者如果由于某种原因您真的希望打印精确的pflags
输出,那么最好的优化是构造本地pflags的PID列表 - 不是一场胜利,但你仍然失去了一堆额外的分叉进程。像这样:
#!/usr/bin/perl -W
use warnings;
use strict;
use Proc::ProcessTable;
my $t = new Proc::ProcessTable;
my $pids = join " ", map { $_->pid } @{$t->table};
if (open(WCF, "pflags 2>&1 $pids|")) {
while (<WCF>) {
next if ($_ =~ /cannot/);
print $_;
last if ($_ =~ /pause/);
}
close(WCF);
}
答案 1 :(得分:1)
在这种情况下,我不知道你认为什么是“更好的方法”,但我可以为你已有的方法提供一些技术指导:
grep '/[t]ransfile'
针对grep
输出的ps
通常存在匹配grep
进程本身的风险,这几乎是不可取的。一个简单的保护措施就是在grep
模式参数中引入一个成员的字符类。
awk '/\/[t]ransfile/{ print $2 }'
grep
+ cut
,即模式匹配后的字段提取,对于单个awk
命令来说是一项简单的任务。
请勿参阅$_
更严格,更惯用的perl会省略$_
的明确使用。试试next if /cannot/
等。
open(my $wcf, ...)
请使用词法文件句柄,否则你会被那些年龄足以记住我们无法使用它们的人所谴责。 :)