Bash 中的 AWK 问题

Bash 中的 AWK 问题

你好,长话短说:我正在尝试创建一个脚本,通过 CI 服务器运行来终止特定的进程。

因此通过互联网搜索我发现了这个命令:

myuser@server:/home/myuser# ps -ef | grep someUniqueText | grep -v grep | awk '{print $2}'
5263

当我在控制台中运行它时,它返回我所需要的内容(5263),所以我创建了这个 bash:

#!/bin/bash

PROCESSNAME=$1
PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | awk '{print $2}');

echo $PID;

当我按如下方式执行它时:

myuser@server:/home/myuser# ./killProcess.sh somename
5263 4587 1236

bash 脚本返回 3 个数字,第一个是我需要的进程,我不知道另外两个是什么,为什么?oO

PS:我echo先用来测试一下,以后我会改成kill -9

答案1

运行时./killProcess.sh somename,类似于

/bin/bash ./killProcess.sh somename

存在,并且ps | grep | grep | awk-line 也找到了这个,因为它包含文本somename。我不太清楚为什么你会得到两个额外的 PID(而不仅仅是一个),但我认为这是bash和之间的一些父/子关系killProcess.sh。在一行中,PID 显示为 PID,在另一行中显示为 PPID。

您可以通过根据脚本名称 grep 来避免这些 PID。它存储在 中$0,因此

PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | grep -v $0 | awk '{print $2}');

或(使用更少的程序调用):

PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $0 | awk '{print $2}');

另一种(更安全)的方法是 grep 掉脚本的 PID。它存储在$$

PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $$ | awk '{print $2}');

或者全部执行awk

PID=$(ps -ef | awk "/$PROCESSNAME/ && !/awk/ && !/$$/ {print \$2}");

我们需要\$2在此处转义,以便它不被 shell 解释,而是由 解释awk。该命令的意思是:

如果该行包含$PROCESSNAME且不awk包含我们自己的 PID,则打印第二列。

优点是(理论上)运行速度更快,因为只awk需要一个附加命令(),而不是 3 个 greps 和一个 awk。

但:

所有这些grepsawks并不完美,你总会发现我们没有想到的情况(例如部分匹配等)。因此,我建议使用已经写好的工具之一:

答案2

我曾经实现过类似的想法,作为一个 shell 函数,我称之为psg(“ps|grep”)

psg() {
    local -a patterns=()
    (( $# == 0 )) && set -- $USER
    for arg do 
        patterns+=( "-e" "[${arg:0:1}]${arg:1}" )
    done
    ps -ef | grep "${patterns[@]}"
}

这使用了一个技巧,将模式的第一个字符放在括号中,这样你就可以得到

ps -ef | grep "[s]omename"

这使您可以删除grep -v grep管道的一部分。

如果您不传递任何参数,它会使用您的用户名来搜索您的进程。

相关内容