在ps中被列为(bash)的进程,尽管它们会被立即监视



我试图获得一些短时间进程的进程信息,所以我制作了一个测试脚本来帮助我。

我启动了一个运行连续循环的后台任务,将ps的输出管道连接到awk,以寻找新的进程。循环以处理器允许的速度运行。为了测试我的程序,我启动脚本,然后运行一些后台sleep任务。像这样:

watchPIDs 10
sleep 1&
sleep 2&
sleep 3&

上面的10意味着让我的脚本运行10秒。尽管循环以处理器允许的速度运行,但我认为一些睡眠命令";生与死;在某个东西注册之前,它扰乱了我的结果。。。有时我看到上面例子中的sleep 1进程显示为(bash)(在bash周围有括号(而不是sleep 1

在谷歌上搜索括号命名法会发现以下内容:

括号表示命令覆盖了其名称,或者ps找不到名称,而该ps正在打印"会计名称">

我不太确定这是否适用于这里,或者我可能不理解。。。这可能是我的剧本中的一些错误,我不明白。。。否则,当我几乎可以肯定我的脚本运行得足够快时,为什么我不总是为该进程取一个名称sleep 1呢;参见";在它死之前的那个过程(毕竟,它确实为那个过程获得了正确的PID(?

这是我的代码(主要是awk(:

watchPIDs()
{
[ "${1}" ] || { echo "No time duration specified, exiting..."; return -1; }
set +bm
end=$(( `date +%s` + ${1} ))
{
while [ `date +%s` -lt ${end} ]; do ps -o pid=,ppid=,pgid=,command=; done |
exec awk ' BEGIN { fmt = "%-10.10s%-10.10s%-10.10s %-.70sn"; }
{
old=0
for ( pid in pids ) if ( pids[pid] == $1 ) { old = 1; break; }
if ( old == 0 ) {
pids[i++] = $1
match($0, " *" $1 " +" $2 " +" $3 " " )
pidInfo[i-1] = sprintf(fmt, $1, $2, $3, substr($0, RLENGTH))
}
} END {
print ""
printf fmt, "PID", "PPID", "PGID", "Command"
for ( j = 0; j < i; j++ ) printf "%s", pidInfo[j]
}' &
} 2>/dev/null
}

示例输出,上面列出了测试用例:

PID       PPID      PGID       Command
62246     62245     62246       -bash
62573     62246     62246       -bash
62574     62246     62246       awk  BEGIN { fmt = "%-10.10s%-10.10s%-10.10s %-.70sn"; }12        
63097     62246     62246       (bash)
63552     62246     62246       sleep 2
63985     62246     62246       sleep 3

谢谢!

您似乎在前台运行循环,并将其管道化,使其成为一个在后台运行的子shell,调用awk,但随后(exec(用该子shell替换当前进程。老实说,我不确定它的最终效果是什么,但在调试时,如果有2>/dev/null的话,你肯定不应该在那里,你可以用bash -x watchPIDs 10运行它,看看它在做什么。

在任何情况下,都可以试试这个(未经测试,因为我的ps没有-o选项(:

#!/usr/bin/env bash
watchPIDs()
{
[ "${1}" ] || { echo "No time duration specified, exiting..." >&2; return 1; }
{
set +bm
end=$(( $(date +%s) + $1 ))
while (( $(date +%s) < $end )); do ps -o pid=,ppid=,pgid=,command=; done |
awk ' BEGIN { fmt = "%-10.10s%-10.10s%-10.10s %-.70sn"; }
{
old=0
for ( pid in pids ) if ( pids[pid] == $1 ) { old = 1; break; }
if ( old == 0 ) {
pids[++i] = $1
match($0, " *" $1 " +" $2 " +" $3 " " )
pidInfo[i] = sprintf(fmt, $1, $2, $3, substr($0, RLENGTH))
}
} END {
print ""
printf fmt, "PID", "PPID", "PGID", "Command"
for ( j = 1; j <= i; j++ ) print pidInfo[j]
}'
} &
}
watchPIDS "$@"

我只是用awk命令将你的循环移到后台,然后整理其他一些东西。

显然,如果这真的存储在shell脚本中,那么您可以在后台调用该函数。

要运行sleep,Bash将首先调用fork((,然后在子进程中调用execve((,将自己替换为sleep。因此,在forkexecve之间,子进程名称仍然是bash

(不过我不知道是谁加的括号。(

最新更新