Как получить PID из функции PHP exec () в Windows?
Но я использую виртуальную машину XP для разработки веб-приложения, и я понятия не имею, как получить pid в Windows. Я пробовал это на cmd:
C:\\wamp\\bin\\php\\php5.2.9-2\\php.exe "file.php args" > NUL & echo $!
И файл запускается, но на выходе получается «$!» Как я могу вставить pid в var $ pid? (используя php)
Я проголосовал за то, чтобы переместить этот вопрос на serverfault.com, поскольку в основном его можно свернуть до Как мне получить идентификатор процесса в командной строке Windows. Может быть, superuser.com подходит даже лучше? — person Tomalak   schedule 09.09.2010
Ответы (4)
Вам нужно будет установить дополнительное расширение, но решение найдено на вики-странице Uniformserver. ОБНОВЛЕНИЕ После некоторого поиска вы можете заглянуть в tasklist , который, по совпадению, вы сможете использовать с командой PHP exec , чтобы получить то, что вам нужно.
Спасибо, в любом случае, я думаю, что просто настрою сервер на виртуальном ящике Linux, мне просто не нравится, когда в моей основной ОС есть веб-сервер, и единственный, который у меня был, был в выигрыше. — person jarkam; 09.09.2010
Обновился, нашел встроенную в xp программу под названием tasklist , которая может делать то, что вы хотите. — person Jimithus; 09.09.2010
// use psexec to start in background, pipe stderr to stdout to capture pid exec("psexec -d $command 2>&1", $output); // capture pid on the 6th line preg_match('/ID (\d+)/', $output[5], $matches); $pid = $matches[1];
Это сработало для меня, однако по какой-то причине появилось дополнительное окно консоли. — person relipse; 27.05.2014
Я приземлился здесь благодаря Google и решил, что этому посту десятилетней давности нужна дополнительная информация на основе Как вызвать / запустить процесс в PHP и убить его, используя идентификатор процесса . Представьте, что вы хотите выполнить команду (в этом примере используется ffmpeg для потоковой передачи файла в системе Windows на сервер rtmp). Вы можете дать команду примерно так:
ffmpeg -re -i D:\wicked_video.mkv -c:v libx264 -preset veryfast -b:v 200k -maxrate 400k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp:///superawesomestreamkey > d:\demo.txt 2> d:\demoerr.txt
Первая часть объясняется здесь, а последняя часть этой команды выводится в файлы с таким именем для цели регистрации:
Итак, предположим, что эта команда работает. Вы это тестировали. Чтобы запустить эту команду с помощью php, вы можете выполнить ее с помощью exec, но это займет время (другая тема, проверьте set_time_limit), это видео обрабатывается ffmpeg через php. Не лучший вариант, но в данном случае это происходит. Вы можете запустить команду в фоновом режиме, но каков идентификатор этого процесса? По какой-то причине мы хотим его убить, а psexec выдает только идентификатор процесса, запущенного пользователем. И в этом случае есть только один пользователь. Нам нужно, чтобы у одного пользователя было несколько процессов. Вот пример получения pid запущенного процесса на php:
// the command could be anything: // $cmd = 'whoami'; // This is a f* one, The point is: exec is nasty. // $cmd = 'shutdown -r -t 0'; // // but this is the ffmpeg example that outputs seperate files for sake $cmd = 'ffmpeg -re -i D:\wicked_video.mkv -c:v libx264 -preset veryfast -b:v 200k -maxrate 400k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp://10.237.1.8/show/streamkey1 > d:\demo.txt 2> d:\demoerr.txt'; // we assume the os is windows, pipe read and write $descriptorspec = [ 0 => ["pipe", "r"], 1 => ["pipe", "w"], ]; // start task in background, when its a recource, you can get Parent process id if ( $prog = is_resource( proc_open("start /b " . $cmd, $descriptorspec, $pipes ) ) ) < // Get Parent process Id $ppid = proc_get_status($prog); // this is the 'child' pid $pid = $ppid['pid']; // use wmic to get the PID $output = array_filter( explode(" ", shell_exec("wmic process get parentprocessid,processid | find \"$pid\"" ) ) ); array_pop($output); // if pid exitst this will not be empty $pid = end($output); // outputs the PID of the process echo $pid; >
Приведенный выше код должен отображать pid запущенного процесса inBackground. Обратите внимание, что вам нужно сохранить pid, чтобы убить его позже, если он все еще работает. Теперь вы можете сделать это, чтобы убить процесс: (представьте, что pid равен 1234)
//'F' to Force kill a process exec("taskkill /pid 1234 /F");
Вот мой первый пост на stackoverflow, надеюсь, это кому-то поможет. Удачного и не одинокого Рождества ♪♪
Это адский обходной путь, но он работает. Спасибо. Однако проверка is_resource должна быть отделена от назначения $ prog. — person Slawa; 07.02.2021
Да, читая комментарии, хе-хе. Я заметил это позже. Теперь я делаю это с помощью NodeJS. Рад, что это помогло тебе! — person Carlo Hendrikx; 10.02.2021
Вот несколько менее «хакерская» версия ответа Шона Дауни. PsExec возвращает PID порожденного процесса в качестве целочисленного кода выхода. Итак, все, что вам нужно, это:
&1', $output, $pid); return $pid; > // spawn echo spawn('phpinfo.php'); ?>
Аргумент -accepteula необходим только при первом запуске PsExec, но если вы распространяете свою программу, каждый пользователь будет запускать ее в первый раз, и ничего не мешает оставлять ее для каждого последующего выполнения. PSTools — это быстрая и простая установка (просто распакуйте где-нибудь PSTools и добавьте его папку в свой путь), поэтому нет веских причин не использовать этот метод.
exec
If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n , is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec() .
If the result_code argument is present along with the output argument, then the return status of the executed command will be written to this variable.
Return Values
The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.
Returns false on failure.
To get the output of the executed command, be sure to set and use the output parameter.
Errors/Exceptions
Emits an E_WARNING if exec() is unable to execute the command .
Throws a ValueError if command is empty or contains null bytes.
Changelog
Version | Description |
---|---|
8.0.0 | If command is empty or contains null bytes, exec() now throws a ValueError . Previously it emitted an E_WARNING and returned false . |
Examples
Example #1 An exec() example
// outputs the username that owns the running php/httpd process
// (on a system with the «whoami» executable in the path)
$output = null ;
$retval = null ;
exec ( ‘whoami’ , $output , $retval );
echo «Returned with status $retval and output:\n» ;
print_r ( $output );
?>?php
The above example will output something similar to:
Returned with status 0 and output: Array ( [0] => cmb )
Notes
When allowing user-supplied data to be passed to this function, use escapeshellarg() or escapeshellcmd() to ensure that users cannot trick the system into executing arbitrary commands.
Note:
If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.
Note:
On Windows exec() will first start cmd.exe to launch the command. If you want to start an external program without starting cmd.exe use proc_open() with the bypass_shell option set.
See Also
- system() — Execute an external program and display the output
- passthru() — Execute an external program and display raw output
- escapeshellcmd() — Escape shell metacharacters
- pcntl_exec() — Executes specified program in current process space
- backtick operator
User Contributed Notes 20 notes
This will execute $cmd in the background (no cmd window) without PHP waiting for it to finish, on both Windows and Unix.
function execInBackground ( $cmd ) <
if ( substr ( php_uname (), 0 , 7 ) == «Windows» ) <
pclose ( popen ( «start /B » . $cmd , «r» ));
>
else <
exec ( $cmd . » > /dev/null &» );
>
>
?>
(This is for linux users only).
We know now how we can fork a process in linux with the & operator.
And by using command: nohup MY_COMMAND > /dev/null 2>&1 & echo $! we can return the pid of the process.
This small class is made so you can keep in track of your created processes ( meaning start/stop/status ).
You may use it to start a process or join an exisiting PID process.
// You may use status(), start(), and stop(). notice that start() method gets called automatically one time.
$process = new Process ( ‘ls -al’ );
// or if you got the pid, however here only the status() metod will work.
$process = new Process ();
$process . setPid ( my_pid );
?>
// Then you can start/stop/ check status of the job.
$process . stop ();
$process . start ();
if ( $process . status ()) echo «The process is currently running» ;
>else echo «The process is not running.» ;
>
?>
/* An easy way to keep in track of external processes.
* Ever wanted to execute a process in php, but you still wanted to have somewhat controll of the process ? Well.. This is a way of doing it.
* @compability: Linux only. (Windows does not work).
* @author: Peec
*/
class Process private $pid ;
private $command ;
public function __construct ( $cl = false ) if ( $cl != false ) $this -> command = $cl ;
$this -> runCom ();
>
>
private function runCom () $command = ‘nohup ‘ . $this -> command . ‘ > /dev/null 2>&1 & echo $!’ ;
exec ( $command , $op );
$this -> pid = (int) $op [ 0 ];
>
public function setPid ( $pid ) $this -> pid = $pid ;
>
public function getPid () return $this -> pid ;
>
public function status () $command = ‘ps -p ‘ . $this -> pid ;
exec ( $command , $op );
if (!isset( $op [ 1 ]))return false ;
else return true ;
>
public function start () if ( $this -> command != » ) $this -> runCom ();
else return true ;
>
public function stop () $command = ‘kill ‘ . $this -> pid ;
exec ( $command );
if ( $this -> status () == false )return true ;
else return false ;
>
>
?>
How to get PID from PHP function exec() in Windows?
You will have to install an extra extension, but found the solution located at Uniformserver’s Wiki.
After some searching you might look into tasklist which coincidently, you may be able to use with the PHP exec command to get what you are after.
Solution 2
I’m using Pstools which allows you to create a process in the background and capture it’s pid:
// use psexec to start in background, pipe stderr to stdout to capture pid exec("psexec -d $command 2>&1", $output); // capture pid on the 6th line preg_match('/ID (\d+)/', $output[5], $matches); $pid = $matches[1];
It’s a little hacky, but it gets the job done
Solution 3
I landed here thanks to google and decided that this ten years old post needs more info based on How to invoke/start a Process in PHP and kill it using Process ID.
Imagine that you want to execute a command (this example uses ffmpeg to stream a file on a windows system to a rtmp server). You could command something like this:
ffmpeg -re -i D:\wicked_video.mkv -c:v libx264 -preset veryfast -b:v 200k -maxrate 400k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp:///superawesomestreamkey > d:\demo.txt 2> d:\demoerr.txt
The first part is explained here and the last part of that command outputs to files with that name for logging purposes:
So lets assume that that command works. You tested it. To run that command with php you can execute it with exec but it will take time (another subject, check set_time_limit), its a video handled by ffmpeg via php. Not the way to go but it is happening in this case.
You can run the command in background but what is the pid of that Process? We want to kill it for some reason and psexec gives only the ‘process ID» runned by a user. And there is only one user in this case. We want multiple processes on the same user.
Here is a example to get the pid of a runned process in php:
// the command could be anything: // $cmd = 'whoami'; // This is a f* one, The point is: exec is nasty. // $cmd = 'shutdown -r -t 0'; // // but this is the ffmpeg example that outputs seperate files for sake $cmd = 'ffmpeg -re -i D:\wicked_video.mkv -c:v libx264 -preset veryfast -b:v 200k -maxrate 400k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp://10.237.1.8/show/streamkey1 > d:\demo.txt 2> d:\demoerr.txt'; // we assume the os is windows, pipe read and write $descriptorspec = [ 0 => ["pipe", "r"], 1 => ["pipe", "w"], ]; // start task in background, when its a recource, you can get Parent process id if ( $prog = is_resource( proc_open("start /b " . $cmd, $descriptorspec, $pipes ) ) ) < // Get Parent process Id $ppid = proc_get_status($prog); // this is the 'child' pid $pid = $ppid['pid']; // use wmic to get the PID $output = array_filter( explode(" ", shell_exec("wmic process get parentprocessid,processid | find \"$pid\"" ) ) ); array_pop($output); // if pid exitst this will not be empty $pid = end($output); // outputs the PID of the process echo $pid; >
The code above should echo the pid of the ‘inBackground’ runned process.
Note that you need to save the pid to kill it later if it is still running.
Now you can do this to kill the process: (imagine the pid is 1234)
//'F' to Force kill a process exec("taskkill /pid 1234 /F");
Here is my first post ever here on stackoverflow, I hope this will help someone. Have a awesome and not lonely christmas ♪♪