【问题标题】:Awk syntax error with system call系统调用的 awk 语法错误
【发布时间】:2017-01-25 14:28:58
【问题描述】:

我有以下 shell 脚本:

#!/bin/bash

top -n 1 -p $(pgrep -d',' -f R) | grep R | awk '{if ($2 != "PID" && int($10) > 50) 
{
    kill_cmd = "echo kill " $1 " | bash -";
    system(kill_cmd);
}}'

如果我将系统调用更改为 print 语句,则结果输出看起来与我预期的一样:echo kill <some_pid> | bash - 我还能够运行 print 语句的输出而不会出错。

系统调用错误提示:语法错误靠近意外标记`('

该脚本的目的是使用 top 查看正在运行的 R 进程,并在它们使用超过 50% 的系统内存时终止它们。

【问题讨论】:

  • 如果调试打印语句如您所说的那样产生预期的输出,那么您的脚本中没有任何内容会产生您所说的错误消息,因此您在诊断/描述的某个地方犯了错误问题。在 system() 调用之前添加 print "<" kill_cmd ">" 然后运行 ​​cat -v script; ./script 并将结果复制/粘贴到您的问题中,这样我们就可以准确地看到您正在运行的命令以及它产生的输出和错误消息。

标签: awk


【解决方案1】:

在您的情况下,以下陈述是错误的,您不需要 echo,|bash -

kill_cmd = "echo kill " $1 " | bash -";
system(kill_cmd);

你可以使用(注意:确保PID列在$1,我猜应该是$2

$ top -n 1 -p $(pgrep -d',' -f R) | 
  awk '/R/ && $2 != "PID" && int($10) > 50{system("kill " $2 )}'

如下所示

$ awk 'BEGIN{system("date")}'
Tue Jan 24 12:41:08 IST 2017

不用每次都调用system(),你可以在最后通过管道传递

任一

$ top -n 1 -p $(pgrep -d',' -f R) | 
  awk '/R/ && $2 != "PID" && int($10) > 50{ print "echo kill " $2 }' | bash

$ top -n 1 -p $(pgrep -d',' -f R) | 
  awk '/R/ && $2 != "PID" && int($10) > 50{ print  $2 }' | xargs kill -9

例如

$ awk 'BEGIN{for(i=1;i<=5;i++)print "echo test :"i; print "date"}' 
echo test :1
echo test :2
echo test :3
echo test :4
echo test :5
date

$ awk 'BEGIN{for(i=1;i<=5;i++)print "echo test :"i; print "date"}'  | bash
test :1
test :2
test :3
test :4
test :5
Tue Jan 24 12:31:43 IST 2017

【讨论】:

    【解决方案2】:

    该脚本的目的是使用 top 查看正在运行的 R 进程,并在它们使用超过 50% 的系统内存时终止它们。

    为此,我不会使用pgreptop,也不会在awk之前使用任何无用的grep

    ps aux | awk '$11 ~/R/ && $4 > 50 { system("kill " $2) }'
    

    ps aux | awk '$11 ~/R/ && $4 > 50 { print $2 }' | xargs kill
    

    这已经在 Linux 上进行了测试。根据系统中ps 输出的特定格式,美元参数的编号可能不同(您可能还希望通过提供不同于aux 的参数来指示ps 使用另一种输出格式或进程选择.) 另外,也许匹配 ~/R/ 可能应该被改进,但它与您使用的相同。 xargs 只调用一次kill,在一个命令行中收集 PID 之后,除非它们太多,在这种情况下,xargs 将 PID 拆分为适当数量的 kill 调用(在这种情况下是不可能的,假设您不能拥有数十个进程,每个进程消耗超过 50% 的系统内存...)

    【讨论】:

    • 很好的解决方案;谢谢你。你知道是什么导致我的系统调用失败吗?
    • 事实上,没有。我无法重现该错误,我怀疑它是由一些偶然的错字引起的,例如不平衡的报价等。但是如果你简化你的命令行,你也会减少这种模糊错误的机会。如果您喜欢,请不要忘记接受答案...
    【解决方案3】:
    #!/bin/bash
    
    eval "$( 
       top -n 1 -p $(pgrep -d',' -f R) \
        | awk '
            /R/ && $10 >= 51 && $2 != "PID" { L = L " " $1 } 
            END { if ( L !~ /^$/) print "kill" L }
            '
        )"
    
    • eval 只调用一次系统通过子shell 杀死所有 PID(kill 允许杀死几个作为参数传递的 pid
    • 不需要 grep R 后跟 awk,awk 可以使用 /R/ 过滤
    • 简单的测试通常可以作为过滤器而不是 if 内部结构
    • 可能会添加一个级别的信号(最终通过传递给 awk 的变量)用于杀死级别

    【讨论】:

      猜你喜欢
      • 2017-06-26
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 2012-09-08
      • 1970-01-01
      • 2018-08-20
      • 1970-01-01
      相关资源
      最近更新 更多