/proc/pid/cmdline采坑

news/2024/5/17 18:22:21 标签: 运维, 操作系统, python

在Linux系统中,根据进程号得到进程的命令行参数,常规的做法是读取/proc/{PID}/cmdline,并用'\0'分割其中的字符串得到进程的args[],例如下面这个例子:

# xxd /proc/7771/cmdline
0000000: 2f69 746f 612f 6170 702f 6d61 7665 2f62  /itoa/app/mave/b
0000010: 696e 2f6d 6176 6500 2d70 002f 6974 6f61  in/mave.-p./itoa
0000020: 2f61 7070 2f6d 6176 6500                 /app/mave.

通过分割其中的0x00(C语言字符串结束符),可以把这个进程args[],解析出来:

args[0]=/itoa/app/mave/bin/mave
args[1]=-p
args[2]=/itoa/app/mave

但是有的时候,我们会看到这样的进程cmdline:

# xxd /proc/7276/cmdline
00000000: 6e67 696e 783a 2077 6f72 6b65 7220 7072  nginx: worker pr
00000010: 6f63 6573 7300 0000 0000 0000 0000 0000  ocess...........
00000020: 0000 0000 0000 0000 00                   .........
# xxd /proc/3334/cmdline
00000000: 6e67 696e 783a 206d 6173 7465 7220 7072  nginx: master pr
00000010: 6f63 6573 7320 2f75 7372 2f73 6269 6e2f  ocess /usr/sbin/
00000020: 6e67 696e 7820 2d63 202f 6574 632f 6e67  nginx -c /etc/ng
00000030: 696e 782f 6e67 696e 782e 636f 6e66       inx/nginx.conf

感觉完全不按套路出牌啊,原本看起来应该是0x00的地方,却用0x20(空格字符),而且有时,最后还弄了一堆的0x00。如果还按照上面的正规套路解析必然无法达到“满意”的结果。那么这究竟是怎么回事呢?

原来,cmdline中的内容实际上是进程main函数的参数args的内容,正常情况下,进程的args是进程的启动参数。但是,有些进程却偏偏复写了args里面的内容。由于可以随意的改动,所以就会出现各种“自定义”的参数形式,比如上面nginx的做法。

因此,如果试图通过0x00来分割参数,针对一些特殊的进程是不可靠的。不过由于ps程序显示的内容其实就是cmdline中的东西,遇到0x00是当成空格显示的,并且末尾的连续0x00会被忽略。因此,上面nginx的例子,用ps看会是这样:

root      3334     1  0 2月23 ?       00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
root      7276  3334  0 2月26 ?       00:00:01 nginx: worker process

如果按照ps的解构方式来做,倒也并不困难。

setproctitle

Python有一个第三方库叫setproctitle,作用就是通过修改args来设置process title。为什么一个看似很简单的事情,需要一个专门的库来做呢,其实这里面另有玄机。

在Linux中,程序的参数存储空间的后面紧跟的就是环境变量的存储位置:因此,过长的title也会损坏环境变量environ的值。安全的做法是,先将环境变量复制到其他地方,然后修改environ[x]的指向,接着,复写整个args[]。示例代码可参考nginx 设置进程title

clipboard.png

更多关于cmdline的问题可参考:

  • How to parse /proc/pid/cmdline
  • Finding the command for a specific PID in Linux from Python

http://www.niftyadmin.cn/n/972036.html

相关文章

PythonNote021---python格式化输出format和%

算是python的基础操作了,还是记点笔记,不然每次都要百度~ import sys sys.version3.7.0 (default, Jun 28 2018, 08:04:48) [MSC v.1912 64 bit (AMD64)]%用法 整数输出 %o —— oct 八进制%d —— dec 十进制%x —— hex 十六进制 十进制用的比较多…

JAVA和ORACLE中的日期格式

报表中同时用到了从JAVA中取得的日期和从ORACLE中取得的日期,日期格式必须统一。1、JAVA中,我用SimpleDateFormat()格式化日期,语法如下:SimpleDateFormat("dd-MMM-yy",Locale.US).format(new Date())其中,第…

嵌入式系统的不同方向及优化策略

当涉及到嵌入式系统开发时,可以根据具体的应用需求选择不同的方向进行优化。以下是一些常见的嵌入式系统方向及其特点: 单片机方向:这个方向主要针对使用单片机作为核心的嵌入式系统开发。单片机资源有限,适用于简单的控制任务&am…

Hive05---操作分区表

记录常用的分区表操作: 查看分区删除分区插入分区数据 查看分区 show partitions tmp.order;删除分区 ALTER TABLE tmp.order DROP IF EXISTS PARTITION (dt20200520);复写分区 INSERT overwrite TABLE tmp.order partition (dt) SELECT * FROM tmp.order_tes…

sql server 2005 T-SQL $PARTITION (Transact-SQL)

为任何指定的分区函数返回分区号,一组分区列值将映射到该分区号中。 Transact-SQL 语法约定 语法 [ database_name. ] $PARTITION.partition_function_name(expression) 参数 database_name 包含分区函数的数据库的名称。 partition_function_name 对其应用一组…

Scala005-DataFrame中使用UDF

在处理spark.DataFrame时,经常会用到udf,简单做些总结和笔记。 构造数据 import org.apache.spark.sql.functions._ import spark.implicits._ import org.apache.spark.ml.feature.VectorAssembler import org.apache.spark.ml.linalg.{Vector, Vecto…

关闭端口

每一项服务都对应相应的端口,比如众如周知的WWW服务的端口是80,smtp是25,ftp是21,win2000安装中默认的都是这些服务开启的。对于个人用户来说确实没有必要,关掉端口也就是关闭无用的服务。 “控制面板”的“管理工具”…

PyPackage02---Numpy01_flatten用法

Intro 对于numpy中的多维数组,需要将其转换成1维。此时可以用flatten方法。 相关环境和package信息: import sys import pandas as pd import numpy as np print("Python版本:",sys.version) print("numpy版本:&…