You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

AWK中如何在system()函数中传入变量值以通过PID获取进程名?

解决AWK中system()调用变量的问题

你遇到的核心问题有两个:AWK不支持用+做字符串拼接,而且system()返回的是命令的退出状态码,不是命令的输出内容——这俩坑刚好你都踩了😅

先修正字符串拼接错误

AWK里的字符串拼接逻辑很简单:只要把变量和字符串直接放在一起(中间可以加空格分隔,不影响),不需要用+号。你原来的"ps -p "+names[n-1]+" -o comm="是C/Java的写法,在AWK里完全不生效,改成下面的形式就行:

"ps -p " names[n-1] " -o comm="

再解决获取命令输出的问题

system()函数只会返回命令的执行结果(0表示成功,非0表示失败),如果你想拿到ps命令输出的进程名,得用管道+getline的方式捕获输出,而不是直接打印system()的返回值。

修正后的完整代码

awk '{ 
    n=split($0,names,"/"); 
    pid=names[n-1];  # 单独存PID,代码更清晰
    cmd="ps -p " pid " -o comm=";
    # 用getline捕获命令输出
    if ((cmd | getline proc_name) > 0) {
        print proc_name;  # 打印真正的进程名
    } else {
        print "无法获取PID " pid " 的进程名";
    }
    close(cmd);  # 一定要关闭管道,避免资源泄漏
}' <<< "/usr/lib/firefox/firefox/1319/1000"

额外细节说明

  1. 关于split的索引:你的输入字符串开头是/,所以split($0,names,"/")后,数组names的第一个元素是空值,后面的元素依次是usrlib...13191000,所以names[n-1]确实能拿到目标PID1319,这部分逻辑是对的。
  2. getline的返回值:它会返回读取到的行数,>0表示成功读取到输出,0表示命令执行成功但无输出,-1表示命令执行失败。
  3. 管道关闭:每次用cmd | getline后必须调用close(cmd),否则多次执行会占用文件描述符,导致程序报错。

可选简化写法(GNU AWK适用)

如果你的环境用的是GNU AWK(绝大多数Linux系统默认都是),也可以用vsprintf构造命令字符串,写法更接近C语言的格式化输出:

cmd = vsprintf("ps -p %s -o comm=", names[n-1])

测试的时候可以先单独执行ps -p 1319 -o comm=,确认这个PID确实存在且能返回进程名,再放到AWK里运行。

内容的提问来源于stack exchange,提问作者lancaster

火山引擎 最新活动