31

How can I invoke an external shell script (Or alternatively an external PHP script) from PHP itself and get its process ID within the same script?

4 Answers 4

62
$command =  'yourcommand' . ' > /dev/null 2>&1 & echo $!; ';

$pid = exec($command, $output);

var_dump($pid);
Sign up to request clarification or add additional context in comments.

7 Comments

What's the meaning of " > /dev/null 2>&1 & echo $!; "
it means 'send all the output to the null device, which means that all the output will be available in the stdout, and echo $! simply echo the pid, which is captured by the script
This also means that the command will run in the background (which would be what you want if you want the pid), and so your php script will not wait for the command to finish executing
this is useless when it doesn't wait for command to finish, -1 from me
If you want to wait for the command to finish remove & as & stands for asynchronous mode
|
27

If you want to do this strictly using tools PHP gives you, rather than Unix-specific wizardry, you can do so with proc_open and proc_get_status, although the need to pass a descriptor spec into proc_open makes it unpleasantly verbose to use:

<?php

$descriptorspec = [
    0 => ['pipe', 'r'],
    1 => ['pipe', 'w'],
    2 => ['pipe', 'w']
];
$proc = proc_open('yourcommand', $descriptorspec, $pipes);
$proc_details = proc_get_status($proc);
$pid = $proc_details['pid'];

echo $pid;

2 Comments

how do I get output?
$pipes will be filled with an array with a resource for each pipe in the $descriptorspec. So you need to read from the file descriptor $pipes[1] for stdout.
3

For a cross-platform solution, check out symfony/process.

use Symfony\Component\Process\Process;
$process = new Process('sleep 100');
$process->start();
var_dump($process->getPid());

After you install symfony/process with composer (composer require symfony/process), you may need to update autoloading info with composer dump-autoload and then require the autoload with require __DIR__ . '/vendor/autoload.php';.

Notice also that you can get PID of a running process only. Refer to the documentation for API details.

Comments

0

What ended up working for me is using pgrep to get the PID of the command (or process name) executed after calling exec() in PHP.

exec($command);
$pid = exec("pgrep $command");

This will work for launching background processes too. However, you must remember to pipe the program's output to /dev/null or else PHP will hang. Also, when calling pgrep you can't include the pipe portion of the command:

$command = "bg_process -o someOption";
exec($command + " > /dev/null &"); //Separate the pipe and '&' from the command
$pid = exec("pgrep $command");

Note that if the system has multiple processes launched with the same exact command, it will return the PIDs of all processes which match the command given to pgrep. If you only pass in a process name, it will return all PIDs with that process name.

1 Comment

This is more fragile than the other solutions given here for the reason you outline (if you have multiple processes invoked with the same command string, this doesn't let you tell which one is the one you just launched) and doesn't really provide any advantage over them to make up for it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.