linux - 解析命令输出

标签 linux string bash parsing extract

我正在尝试提取命令输出的参数。目前,我有这个:

ps -eaf | grep javaagent


输出是这样的:

-Dweblogic.system.BootIdentityFile=/u06/app/oracle/admin/domains/omservices/servers/profiling03/data/nodemanager/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=false -Dweblogic.ReverseDNSAllowed=false -javaagent:/u01/home/app/appdyn/AppDynamics/AppServerAgent/ver4.3.1.5/javaagent.jar -Dappdynamics.agent.applicationName=BFL_PE_Omnichannel -Dappdynamics.agent.tierName=CDLV_Profiling -Dappdynamics.agent.nodeName=profiling03 -Xms3g -Xmx3g -XX:MaxPermSize=756m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:/u06/app/oracle/admin/logs/omservices/profiling03/gc.log -XX:-DisableExplicitGC -Djava.net.preferIPv4Stack=true -Dweblogic.MuxerClass=weblogic.socket.NIOSocketMuxer -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/u06/app/oracle/admin/logs/omservices/profiling03/dump -Dweblogic.Stdout=/u06/app/oracle/admin/logs/omservices/profiling03/profiling03.out -Dprofiling-services.configPath=/cyberbank/profiling/v2/config/ -Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger -Dprofiling-services.logPath=/u06/app/oracle/admin/logs/omservices/profiling03 -Duser.timezone=GMT-5 -Dweblogic.management.server=t3://ba410018-priv:4065 weblogic.Server


我想提取参数(我对此路径感兴趣):

-javaagent:/u01/home/app/appdyn/AppDynamics/AppServerAgent/ver4.3.1.5/javaagent.jar


我使用以下命令进行了此操作:

ps -eaf | grep javaagent | cut -d " " -f XX


其中“ XX”是XX所在的列。该命令的问题在于进程将始终不同。但是,javaagent将始终处于该过程中。

简而言之,是一条允许我在进程X中提取参数javaagent的命令。

最佳答案

通常,回答外壳程序形式为“如何解析...的输出?”的第一步。是要问另一个问题:“如何在不解析命令输出的情况下获取[此信息]?”。

当然,几乎总是需要某种类型的解析,但是如果您可以将其简化为在某些定界符字符串上的可靠拆分,那么您就可以解决问题,因为有很多方法可以在定界符处拆分字符串。 (请参阅下面的其中一项。)

注意:此答案的其余部分假定使用软件包procps-ng中的bash,Gnu awkps进行合理标准的Linux安装。它可以很容易地适应其他环境,但是细节会使叙述变得过于复杂。

ps命令带有一组不错的输出选项,使自定义命令的输出非常容易。例如,如果您想查看正在运行的进程的所有命令行,而没有任何其他令人困惑的数据,则可以尝试以下操作:

ps -e -ops=,cmd=


这将打印系统上所有进程的pid和命令行。 (如果愿意,可以使用-ea,很多人都可以使用。使用ps的procps-ng版本,没有任何区别。)

输出规范-o由逗号分隔的字段列表组成(其名称在标有“标准格式规范”的man ps中记录)。每个字段名称后面都可以有一个=和一些文本(不能包含逗号);文本用于标题行,即第一行输出。使用just =不带文本表示该列没有标题,并且如果没有列具有标题,则不打印标题行。这使“解析”更加容易。

ps可以打印的许多字段很容易解析,因为它们不能包含空格。实际上,手册页列出了一些可以包含空格的字段:


  以下用户定义的格式说明符可能包含空格:args,cmd,comm,命令,fname,ucmd,ucomm,lstart,bsdstart,start


并且该列表实际上比不同说明符的实际数量大得多,因为argscommandcmd的别名(显示整个命令行),而ucmducomm是< cc>-显示可执行文件的名称。

这些字段可能包含空格甚至是换行符,这一事实无疑使解析变得复杂。对于命令行参数,它实际上使解析变得不可能,因为无法区分包含空格的命令行参数和两个连续的命令行参数之间的空格。理想情况下,我们需要一种确定的方法来为每个进程提取命令行参数。

虽然我们无法从comm获取此信息,但是我们可以转到ps使用的信息源:ps文件系统。特别是,对于任何pid,“文件” /proc包含命令行组件,每个组件以NUL字节终止。例如,我的/proc/PID/cmdline流程如下所示:

$ hd /proc/1/cmdline
00000000  2f 6c 69 62 2f 73 79 73  74 65 6d 64 2f 73 79 73  |/lib/systemd/sys|
00000010  74 65 6d 64 00 2d 2d 73  79 73 74 65 6d 00 2d 2d  |temd.--system.--|
00000020  64 65 73 65 72 69 61 6c  69 7a 65 00 31 38 00     |deserialize.18.|
0000002f


由于命令行选项不能包含NUL字节,因此这是完全明确的。

我们可以通过简单地遍历init目录来提取所有正在运行的进程的所有命令行:

cat /proc/[1-9]*/cmdline


(我使用了/proc而不是[1-9]*,因为*文件系统中还有其他子目录。)

但这会产生以NUL分隔的记录的换行分隔的行,对于大多数实用程序而言,这不是最方便的格式。 (此外,它还引入了歧义,因为换行符可能是参数的一部分。)幸运的是,Gnu /proc很乐意将NUL用作记录分隔符,并具有正则表达式匹配功能。因此,要查找以awk开头的所有正在运行的进程的所有参数,我们可以使用以下一种代码:

awk -v RS='\0' '/^-javaagent:/' /proc/[1-9]*/cmdline


注意:

在上面的描述中,我跳过了几个细节。其中一个是-javaagent:仅包含命令行的前4k。由于Java调用通常很长,因此命令行的一部分可能会丢失。但是,由于/proc/PID/cmdline使用ps文件系统来获取其显示的信息,因此会遇到相同的问题。我不知道有什么容易的方法。

另一个问题是,如果要以某种方式隐藏或重新处理自己的命令行,则正在运行的进程可以修改/proc中显示的数据。例如,如果查看-ocmd=进程的条目,则会看到参数用空格而不是NUL分隔。

关于linux - 解析命令输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50352475/

相关文章:

linux - Jenkins :Appium:找不到命令

linux - 某些 Linux 浏览器中的字体样式和大小差异

c# - C#中的字符串操作优化

bash - 每次提交的提交中的所有文件的列表

bash - 如何限制目录以在其中保留一定数量的文件

regex - "partial grep"加快grep速度?

linux - 在(ubuntu)linux 中捕获第二个键盘输入

linux - 削减 Linux 变量个数的空格

python - 如何将字符串方法应用于数据框的多列

python - Pandas 数据框 : Split mixed float-string column into separate float and string columns