AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 775286
Accepted
k.schroeder31
k.schroeder31
Asked: 2024-04-27 00:02:31 +0800 CST2024-04-27 00:02:31 +0800 CST 2024-04-27 00:02:31 +0800 CST

为什么一个进程 ps 命令在目录周围显示空格而不是斜杠?

  • 772

我正在尝试调试一个失败的旧进程监视器,该监视器搜索正在运行的进程。我确定这是由一些神秘的 Linux 行为引起的。正在运行的进程是 /opt/my/path/directoryname/daemonname 但由于某些奇怪的原因,它在目录名周围显示空格,而不是 /。许多守护进程都从同一目录运行,并以正确的路径显示。它只是每台服务器上的一个特定守护进程。

ps -ef显示此守护程序的以下内容:

/opt/my/path directoryname daemonname --arg1 VALUE1 --arg-two VALUE.TWO --arg-three ARG.UMENT.THREE.ERR --worker daemonname --pid-role daemonname

该守护进程由 perl 脚本启动。与其他脚本相比,看起来目录路径是使用与所有其他脚本完全相同的环境变量提供的,但这些其他脚本会产生正确的路径,例如/opt/my/path/directoryname/daemonname. 相关的 perl 行看起来像这样exec => catfile( $settings->config("/directories/executables"), $daemon_name ),,我已经确认 config("/directories/executables") 的值是正确的值/opt/my/path/directoryname

由于所有有关目录名称包含空格的问题,搜索这个问题一直是一场噩梦。这不是那个。任何路径都不应包含空格。 ps 显示了我的 mkdir 命令,其中有一个空格,其中有一个斜线,这是我能找到的最接近的,但没有得到答复。

perl
  • 1 1 个回答
  • 293 Views

1 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2024-04-27T02:21:11+08:002024-04-27T02:21:11+08:00

    返回的字段之一ps -f是传递给进程(或其祖先之一)最后执行的命令执行的参数列表。您可以通过ps -o args.

    当进程执行文件时,这是通过execve()系统调用:

    execve("/path/to/executable", [arg0, arg1..., 0], [env1, env2... 0])
    

    arg0按照惯例,是可执行文件的名称。当 shell 解释:

    cmd arg
    

    命令行,它调用execve("/path/to/cmd", ["cmd", "arg", 0], ...). 当那是:

    /path/to/cmd arg
    

    它调用execve("/path/to/cmd", ["/path/to/cmd", "arg", 0], ...).

    这些字符串 ( cmd, arg) 最终位于进程堆栈的底部,以 NUL 分隔。在这个过程中,这就是argv[0], argv[1]... 所指的。

    在 Linux 上,该区域在 中公开/proc/<pid>/cmdline,这就是ps从现场获取它的地方args。

    从技术上讲,ps获取该字符串列表并打印它并用空格连接,以便最终字段args看起来像用于执行命令的 shell 命令行。

    在这里,如果ps显示:

    /opt/my/path directoryname daemonname --arg1...
    

    这些空格可能表示这些字符串中的真实空格,或者单独的字符串,或者这些字符串中的空格已被 NUL 替换。

    如果进程碰巧使用标准strtok()函数或类似的方法将argv[0]其拆分为/s ,可能会找出它所运行的可执行文件的基本名称或其路径的不同目录组件,则后者是合理的。

    例如,如果我创建:

    #include <string.h>
    #include <unistd.h>
    int main(int argc, char *argv[])
    {
      strtok(argv[0], "/");
      while (strtok(NULL, "/"));
      pause();
    }
    

    并编译并运行它:

    $ cc a.c
    $ "$PWD/a.out" &
    [1] 67758
    $ ps -fp "$!"
    UID          PID    PPID  C STIME TTY          TIME CMD
    chazelas   67758   60043  0 19:19 pts/4    00:00:00 /home chazelas a.out
    

    您会看到/s 已被空格替换。

    实际上,它们已被 NUL 取代,可以通过以下方式验证:

    $ sed -n l "/proc/$!/cmdline"
    /home\000chazelas\000a.out\000$
    

    但ps看到这些 NUL 并将它们解释为 3 个不同参数的分隔符,并用空格连接起来。

    然后假设这是正确的解释,这不是一个奇怪的 Linux 行为,它只是应用程序本身argv[0]在启动后修改它(可能通过用/NUL 替换 s,可能是为了提取一些路径组件)。

    在 Linux 上,查找进程当前正在运行的可执行文件的更可靠方法是执行readlink()on /proc/<pid>/exe,例如使用realpathorreadlink实用程序或stat内置的zsh:

    $ zmodload zsh/stat
    $ stat +link /proc/$!/exe
    /home/chazelas/a.out
    $ readlink "/proc/$!/exe"
    /home/chazelas/a.out
    $ realpath "/proc/$!/exe"
    /home/chazelas/a.out
    

    Linux 上的 procps 实现ps将其返回为ps -o exe.

    没有万无一失的方法可以确定传递给命令的参数是什么,因为/proc/<pid>/cmdline进程可以修改显示的内容。

    不过,审核日志可能包含这些信息。

    • 10

相关问题

  • zabbix_sender 错误

  • cpanm 与 apt 升级

  • 匹配 CSV 文件中的可逆对

  • Perl:可以使用变量替换吗?

  • 如果总和小于特定值,则计算每 2 行的总和并用另一个值替换它们

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve