【问题标题】:Determining each unique process owner on linux system确定 linux 系统上每个唯一的进程所有者
【发布时间】:2014-11-25 23:50:54
【问题描述】:

正如标题所说,我正在尝试制作一个 bash 脚本,该脚本获取系统上每个唯一进程的所有者,并计算该用户拥有的进程总数以及该用户拥有的所有进程的内存总和。我知道ps aux 显示了我需要的所有信息,但是我如何获取每个唯一所有者并将其存储在一个变量中,以便我可以获得每个用户所需的信息?

我正在考虑使用awk 来获取第一列(用户名)并将用户名存储在array 中。我会使用if 语句来检查用户名是否已经在数组中,如果没有,则添加它。除了我不知道如何在 bash shell 中使用数组,而且这种方法似乎不是一种有效的方法。有谁知道这样做的更有效的方法?

样本输出

owner
Num Procs: 2, Mem: 3100, Curr CPU: 0
Hog: 00:00:00 sshd: owner@pts/16

root
Num Procs: 71, Mem: 52644, Curr CPU: 0
Hog: 01:33:41 /usr/bin/X :0 -br -audit 0 -auth /var/lib/gdm/:0.Xauth -nolisten tcp vt7

【问题讨论】:

  • 显示将产生该示例输出的示例输入,以便我们帮助您编写脚本来处理该示例输入。
  • 我没有示例输入,我必须创建作为脚本的输入。
  • 没有。所需的脚本是将输入转换为输出的工具。脚本的输入是 ps aux 的输出或您正在运行的任何其他命令产生的任何内容。您已经从脚本中显示了所需的输出,现在只需发布脚本将收到的输入以生成该输出。
  • 但这就是问题所在,我不知道输入应该是什么,我只知道 ps aux 显示我需要的所有内容,并使用 awk 获取每一列。但从那里,我迷路了。
  • 好的,所以运行ps aux 并捕获它的输出。这是 awk 脚本的示例输入。现在手动编辑该 ps aux 输出的副本,使其看起来像您希望 awk 脚本输出的样子。这是脚本的示例输出。将它们都发布,我们可以为您提供帮助。如果ps aux 输出长度为 1,000 行,那么显然将其修剪为一些合理数量的相关行,例如10个左右。

标签: linux bash awk process


【解决方案1】:

下面的gawk 脚本应该会有所帮助。在这里,我将ps -eo user,%cpu,%mem 的输出重定向到gawk 脚本。

gawk 脚本解析ps 输出并将用户cpumemprocess 相关信息存储在一个数组中并显示。

#!/usr/bin/gawk -f

NR > 1 {
    array[$1]["cpu"]+=$2
    array[$1]["mem"]+=$3
    array[$1]["proc"]++
}

END {
    PROCINFO["sorted_in"]="@ind_str_asc"
    for (users in array) {
        printf("User: %s\n",users)
        printf("Num Procs: %s, ", array[users]["proc"])
        printf("Mem: %s, ", array[users]["mem"])
        printf("Curr CPU: %s", array[users]["cpu"])
        print("\n")
    }
}

输出:

$ ps -eo user,%cpu,%mem|./proc.awk
User: 102
Num Procs: 1, Mem: 0, Curr CPU: 0

User: 105
Num Procs: 1, Mem: 0, Curr CPU: 0

User: avahi
Num Procs: 2, Mem: 0, Curr CPU: 0

User: colord
Num Procs: 2, Mem: 0.3, Curr CPU: 0

User: daemon
Num Procs: 1, Mem: 0, Curr CPU: 0

User: dnsmasq
Num Procs: 1, Mem: 0, Curr CPU: 0

User: root
Num Procs: 81, Mem: 0.8, Curr CPU: 1.2

User: rtkit
Num Procs: 1, Mem: 0, Curr CPU: 0

User: statd
Num Procs: 1, Mem: 0, Curr CPU: 0

User: www-data
Num Procs: 5, Mem: 0, Curr CPU: 0

注意:此程序使用特定于 gawk 的功能,默认情况下这些功能应该在您的系统中可用。

【讨论】:

  • 脚本不起作用,我收到各种错误。另外,我注意到脚本需要一个 args。是否可以通过调用 proc.awk 来创建脚本?
  • 你是如何运行脚本的,你得到的错误信息是什么?
  • 我通过调用 ps -eo user,%cpu,%mem|./proc.awk 在 linux shell 命令行上运行脚本。我在每个使用的二维数组(如 array[$1]["cpu"] 以及右方括号和左方括号之间的错误点)上都遇到语法错误。
  • 二维数组是gnu awk 功能。看起来您的机器没有 gnu awk 并且可能有其他替代品,例如 mawk。如果您使用的是 ubuntu/debian,请输入 sudo apt-get install gawk 进行安装。
【解决方案2】:

如果您坚持完全在 bash 中执行此操作,将会变得非常尴尬,最终结果将难以阅读。尽管您可以在 bash 中编写相当复杂的脚本,但 bash 确实旨在用于编写脚本以自动执行简单、重复的任务。 bash 真的不太适合做复杂的计算,比如那样。

但是,如果你坚持使用 bash:

ls -ald /proc/[0-9]* | awk ' { print $3 } ' | sort | uniq -c

这可以让您计算每个用户名当前在系统上运行的进程数。

for f in /proc/[0-9]*/stat; do echo `ls -l $f | awk ' { print $3 } '` `awk ' { print $24 * 4096 } ' <$f`; done | perl -e 'while(<STDIN>) { my @w=split; $n{$w[0]} += $w[1]; } print join("", map { "$_=$n{$_}\n"; } sort keys %n);'

这给出了每个进程使用的 RAM 的总字节数。它从 /proc/stat 读取 RSS 列,该列给出了每个进程使用的页面数,我相信在大多数常见的 Linux 平台上每个页面都是 4096 字节(如果需要,针对您的特定平台进行调整)。使用 VSZ(即虚拟进程大小)会产生误导。

但正如我刚才提到的,在我看来,bash 并不是真正适合这种黑客行为的工具。我认为在 Perl 中做所有事情可能会更好。最后,我无法避免最后求助于一些 Perl 黑客技术,将所有内容加起来。等效的 bash 代码会更长、更复杂。

【讨论】:

  • 什么目录的 ls?
  • “哪个目录的 ls 输出”的哪一部分你不明白?你在说什么数组?我给你的两个例子根本没有使用数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-08
  • 1970-01-01
  • 2015-09-26
  • 2011-12-29
  • 1970-01-01
  • 1970-01-01
  • 2010-10-21
相关资源
最近更新 更多