如何从进程中获取整个命令行?

如何从进程中获取整个命令行?

如何使用进程名称从正在运行的进程获取命令参数或整个命令行?

例如这个过程:

# ps
PID   USER     TIME   COMMAND
 1452 root       0:00 /sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid

我想要的是/sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid争论。我知道进程名称并想要它的参数。我在 SliTaz 上使用 Busybox。

答案1

您可以使用-o开关来指定输出格式:

$ ps -eo args

手册页:

命令及其所有参数均为字符串。可能会显示对参数的修改。 [...]

您还可以使用-p开关选择特定的 PID:

$ ps -p [PID] -o args

pidof也可用于从进程名称切换到 PID,因此允许使用-p名称:

$ ps -p $(pidof dhcpcd) -o args

当然,你也可以使用grep这个(在这种情况下,你必须添加开关-e):

$ ps -eo args | grep dhcpcd | head -n -1

GNU ps 还允许您删除标头(当然,使用 时这是不必要的grep):

$ ps -p $(pidof dhcpcd) -o args --no-headers

在其他系统上,您可以通过管道连接到 AWK 或 sed:

$ ps -p $(pidof dhcpcd) -o args | awk 'NR > 1'
$ ps -p $(pidof dhcpcd) -o args | sed 1d

编辑:如果您想将此行捕获到变量中,只需$(...)照常使用:

$ CMDLINE=$(ps -p $(pidof dhcpcd) -o args --no-headers)

或者,与grep

$ CMDLINE=$(ps -eo args | grep dhcpcd | head -n -1)

答案2

方法#1 - 使用 ps

你可以使用ps -eaf | grep 1234.

例子

$ ps -eaf | grep 28865
saml     28865  9661  0 03:06 pts/2    00:00:00 bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done
saml     28866 28865  0 03:06 pts/2    00:00:00 sleep 10000

笔记:Busyboxps不包括大多数 Linux 中包含的-eaf典型开关(如上所示) ,但是 Busybox显示的输出看起来与我提供的示例非常相似。您可以在大多数 Linux 上安装 Busybox 并像这样运行它:psps

$ busybox ps
  852 root       0:00 /sbin/auditd -n
  855 root       0:01 /sbin/audispd
  857 root       0:00 /usr/sbin/sedispatch
  866 root       0:00 /usr/sbin/alsactl -s -n 19 -c -E ALSA_CONFIG_PATH=/etc/alsa/alsactl.conf --initfile=/lib/alsa/init/00main rdaemon
  867 root       0:00 /usr/libexec/bluetooth/bluetoothd
  869 root       0:01 {firewalld} /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid
  871 root       0:32 /usr/libexec/accounts-daemon
  873 rtkit      0:05 /usr/libexec/rtkit-daemon
  875 root       0:00 /usr/sbin/ModemManager
  876 avahi      0:03 avahi-daemon: running [dufresne.local]
  878 root       0:54 /usr/sbin/irqbalance --foreground
  884 root       0:00 /usr/sbin/smartd -n -q never
  886 avahi      0:00 avahi-daemon: chroot helper
  891 chrony     0:01 /usr/sbin/chronyd
  892 root       0:01 /usr/lib/systemd/systemd-logind
  893 dbus       1:28 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

方法 #2 - 使用 /proc

您还可以查看cmdline每个 PID 下的文件/proc/<pid>

$ cat /proc/28865/cmdline 
bash-csleep 10000; while [ 1 ];do echo hi;sleep 10;done

但请注意,它缺少间距。这是因为该文件中使用 NUL 字符来分隔命令行参数。不过不用担心,这些可以被删除。

$ tr '\0' ' ' </proc/28865/cmdline
bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done

参考

答案3

尝试这样的事情:

(我的一台路由器上 OpenWrt 上的 busybox 的输出示例)

root@ap8:~# xargs -0 printf '%s\n' </proc/991/cmdline
/usr/sbin/uhttpd
-f
-h
/www
-r
ap8
-x
/cgi-bin
-u
/ubus
-t
60
-T
30
-k
20
-A
1
-n
3
-N
100
-R
-p
0.0.0.0:80
-p
[::]:80

/proc/$PID/cmdline包含进程的参数$PID,就像一个接一个的 C 语言字符串。每个字符串都以零结尾。

一些参数或选项周围的引号是 shell 的东西。您必须仔细查看显示的行以及使用空格或其他对 shell 具有特殊含义的字符的位置。当再次将这些行连接到命令行时,您将需要以某种方式引用该字符或完整的参数。

答案4

如果您喜欢简短的命令并且可以使用 pgrep,我建议pgrep -fl <process_name>.

ps -o args被截断

相关内容