【问题标题】:How can I get the PID of a PHP script run as the first command in a pipeline?如何让 PHP 脚本的 PID 作为管道中的第一个命令运行?
【发布时间】:2016-05-02 10:41:20
【问题描述】:

我有这样一个命令:

php myscript.php |
curl -X POST --data-binary @- "http://localhost/webservice.php/$$/output/"

我使用|myscript.php 的输出发送到curl 命令。我使用$$ 来获取PID,但这会返回curl 命令的PID,而不是php 命令。

事实上,我会在我所有的 crontab 工作中使用这个命令行。我不想接收数千封邮件,而是想将所有信息发送到我的网络服务。

所以在 myscript.php 中,我调用(1 是 cronjob ID):

file_get_contents('http://localhost/webservice.php/1/' . getmypid() . '/start/');
...
file_get_contents('http://localhost/webservice.php/1/' . getmypid() . '/end/');

我尝试将 myscript.php 的输出发送到我正在创建的网络服务。

所以我向我的网络服务发送开始/结束命令。我只想念一件事:如果有警告或一些“回声”,PHP 的输出。

目标是使用 PHP 命令的 PID(我用它来识别我的 web 服务中的进程)将脚本(也可以是 bash 脚本)的输出重定向到 web 服务。

如何获取 PHP 命令的 PID?我尝试了在 Stackoverflow 中找到的 $$,但正如您所回答的,它似乎是当前的 shell PID...

提前致谢!

【问题讨论】:

  • $$ 不是 curl 的 PID。这是 bash 的 PID。
  • 我建议您找到一种不同的机制来选择唯一的文件(目录)名称。如果您打算实际创建一个唯一命名的目录,请考虑使用mktemp 命令,然后将该名称作为参数传递给您的脚本并将其插入到 URL 中。众所周知,使用进程 ID 作为文件名是不安全的,而且对您来说也不容易工作。
  • 看来您的脚本的意图是使用$$ 将随机整数传递到URL,我建议传递$RANDOM
  • @Paulpro 更准确地说,它是运行管道的 Bash shell 的 PID,或者调用了当前子 shell。 $$$BASHPID 并不总是相同的。

标签: php linux bash pipeline pid


【解决方案1】:

TL;DR

$$ 变量是一个特殊变量。它返回调用 shell 的 PID,它可能与 $BASHPID 中存储的当前 shell 的 PID 不同。这两个变量都与管道中进程的 PID 无关。 Bash manual 说:

($$) 扩展为 shell 的进程 ID。在 () 子shell中,它扩展为调用shell的进程ID,而不是子shell。

你需要重构你的 PHP 脚本和你的管道来做一些不同的事情。

正确创建唯一目录

您还没有解释您的 PHP 脚本实际上在做什么,所以这似乎是一个 X/Y 问题。通常,您应该使用 mktemp 或其 PHP 等效项:

创建临时或唯一的文件名。由于您似乎想使用唯一目录,因此我在下面举个例子。但是,拥有一个包含保证唯一的文件名的目录可能会更干净。您的里程可能会有所不同。

您应该使用 mktemp 实用程序来创建没有竞争条件的唯一目录或文件名,而不是尝试使用 PID。如果在 Bash 中执行此操作,则可以将变量导出到环境中,然后在 PHP 脚本中使用相同的目录。例如:

#!/usr/bin/env bash

# Create a unique temp directory safely.
export DIR=$(mktemp -d)

# Create your output directory for whatever reason.
mkdir "$DIR/output"

# Ensure PHP uses $_ENV["DIR"] to do whatever it's doing. 
php myscript.php | curl -X POST --data-binary @- "file://$DIR/output/"

# Clean up the temp directory at some point.
echo "I did something with '$DIR' so clean it up later." > /dev/stderr

只使用带前缀的唯一文件

除了使用目录,您还可以考虑使用带有定义前缀的唯一文件名。例如:

# Create files like "/tmp/myscript.D6147vts"
export TEMPFILE=$(mktemp -t myscript)

然后,像以前一样,在您的 PHP 脚本中使用 $_ENV["TEMPFILE"]。这种方法的好处是您的文件名可以保证是唯一的,但它们都在一个地方并且有一个共同的前缀。这可以让以后更容易清理或找到正确的文件。

如果您确实需要独特的目录,请使用它们。但是,如果您真的不需要目录结构,请不要为自己创建额外的工作:只需使用唯一的文件名即可。

【讨论】:

  • 感谢您的所有回答!你是一个伟大的社区!我已经编辑了我的第一篇文章,以便更准确地满足我的需要。我想以最简单的方式获得 PID,因为我将为我的所有 crontab 作业重复这些命令。此 PID 将识别启动的脚本。谢谢!
【解决方案2】:

试试 ps aux | grep“进程 ID”和 pid(如果是第二列)。用 pnp_exec 解析它;意思是将其存储在一个数组中并提取PID号。

【讨论】:

    猜你喜欢
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-18
    • 2015-11-11
    • 2018-12-26
    相关资源
    最近更新 更多