getting pid of spawned exec in phing
Asked Answered
B

4

7

I am using phing and running selenium server via ExecTask. Sometimes I need to stop running server by killing its process.

Is there a possibility in phing of getting PID of process spawned in ExecTask ?

Besotted answered 2/12, 2012 at 15:27 Comment(1)
Did you ever find a solution for this? I'd like to kill selenium server as well after the tests ran.Robena
U
3

No, ExecTask cannot give the pid of spawned processes directly. It can only return it's exit status and output.

Maybe you can modify the command that you run in ExecTask itself to save the pid of spawned process. You can use $! to get the pid of the most recent background command.

job1 &                     //start job1 and run in background, end command with &
p1=$!                      //stores the pid 
echo $p1                   //gives pid of job1

When you want to kill the selenium server you can call this in another ExecTask :

pkill pid_to_kill

I am not sure if the changes made in shell environment with ExecTask stay or not. If yes then you can use $p1. Replace pid_to_kill with $p1 to kill job1. Else you will have to echo the pid and use the value from its output.

Otherwise you will have do pgrep name_of_program. It will give all processes containing the name. Then you can kill it with pkill.

Unapproachable answered 2/6, 2013 at 19:18 Comment(0)
S
1

It is possible, you could go about the second parameter inside the exec command.

exec("Script To Run", $output);

The second variable gets the output of the current running script in an array format. So to show the full and readable text from the output I would use a foreach loop:

exec("ifconfig", $output); // Presuming you are developing for a Linux server
foreach ($output as $outputvar) {
    echo $outputvar . "<br>"; 
}

After that, I would use something like strpos to pull the information from the $outputvar for the string which you are looking for.

I hope this is something similar to what you are looking for.

Sonyasoo answered 2/12, 2012 at 15:32 Comment(0)
S
1

Instead of launching the process you want to kill from the exec task (selenium server in your case). Use the exec task to launch a script (I used bash but ruby, python etc. will work too). this script will start the desired task and echo the pid. Substitute the required path and executable you want to run in the below.

#!bin/bash

./path_to_executable/process_to_run &
echo $!

Note the "&" this sends the process to the background and allows phing to continue building your project. The last line outputs the pid which can then be captured and saved to a file by the phing exec task. To save this pid add the output option to the phing exec task:

<exec command="your_script" spawn="true" output="./pid.txt" />

the output option will save the output of the exec task to a pid.txt file in the current directory. Note you may need to chown this file (to the user running phing) to enable it to be read later.

In a separate task, you can read the pid from the file and then use an exec task to kill the process.

<loadfile property="pid" file="./pid.txt" />
<exec command="kill ${pid}" dir="./" />

Note: in the above you may need to prepend sudo to the kill command (depending on who owns the process, and how it was started.

Optional but worth considering is adding a task to remove the pid.txt file. This will prevent any possibility of killing the wrong process (based on a stale pid). You may also want to sanity check the content of the pid.txt file since in the event of an error it could contain something other than the pid.

While this may not be the most direct or optimal solution it does work.

Stunning answered 29/6, 2013 at 20:46 Comment(0)
F
0

I ended up creating a phing task that saves the pid of the launched program and it stops it when you ask it for. It uses Cocur\BackgroundProcess to start the process in background and can also return the pid.

<?php

require_once "phing/Task.php";

class BackgroundExecTask extends Task {

    protected $command = null;
    protected $executable = null;
    protected $id = null;

    protected static $pidMap = [];

    public function init() {
        if (!class_exists('\Cocur\BackgroundProcess\BackgroundProcess')) {
            throw new BuildException("This task requires the Cocur Background Process componente installed and available on the include path", $this->getLocation());
        }
    }

    public function main() {
        switch ($this->command) {
            case "start":
                return $this->start();
            case "stop":
                return $this->stop();
        }
    }

    protected function start() {
        $process = new \Cocur\BackgroundProcess\BackgroundProcess($this->executable);
        $process->run();
        // you can also return the pid
        //$this->project->setProperty($this->pidProperty, $process->getPid());
        self::$pidMap[$this->id] = $process;
    }

    protected function stop() {
        self::$pidMap[$this->id]->stop();
    }

    public function setCommand($command)
    {
        $this->command = "" . $command;
    }

    public function setExecutable($executable)
    {
        $this->executable = "" . $executable;
    }

    public function setId($id)
    {
        $this->id = "" . $id;
    }

}

Usage:

<backgroundexec id="myprogram" command="start" executable="somebinary" />
<backgroundexec id="myprogram" command="stop" />
Fong answered 25/8, 2015 at 11:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.