Completed
Pull Request — master (#29)
by Frank
01:40
created

BackgroundProcess::isRunning()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.25

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 6
cts 8
cp 0.75
rs 9.7666
c 0
b 0
f 0
cc 4
nc 4
nop 0
crap 4.25
1
<?php
2
3
/**
4
 * This file is part of cocur/background-process.
5
 *
6
 * (c) 2013-2015 Florian Eckerstorfer
7
 */
8
9
namespace Cocur\BackgroundProcess;
10
11
use Exception;
12
use RuntimeException;
13
14
/**
15
 * BackgroundProcess.
16
 *
17
 * Runs a process in the background.
18
 *
19
 * @author    Florian Eckerstorfer <[email protected]>
20
 * @copyright 2013-2015 Florian Eckerstorfer
21
 * @license   http://opensource.org/licenses/MIT The MIT License
22
 * @link      https://florian.ec/articles/running-background-processes-in-php/ Running background processes in PHP
23
 */
24
class BackgroundProcess
25
{
26
    const OS_WINDOWS = 1;
27
    const OS_NIX     = 2;
28
    const OS_OTHER   = 3;
29
30
    /**
31
     * @var string
32
     */
33
    private $command;
34
35
    /**
36
     * @var int
37
     */
38
    private $pid;
39
40
    /**
41
     * @var int
42
     */
43
    protected $serverOS;
44
45
    /**
46
     * @param string $command The command to execute
0 ignored issues
show
Documentation introduced by
Should the type for parameter $command not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
47
     *
48
     * @codeCoverageIgnore
49
     */
50
    public function __construct($command = null)
51
    {
52
        $this->command  = $command;
53
        $this->serverOS = $this->getOS();
54
    }
55
56
    /**
57
     * Runs the command in a background process.
58
     *
59
     * @param string $outputFile File to write the output of the process to; defaults to /dev/null
60
     *                           currently $outputFile has no effect when used in conjunction with a Windows server
61
     * @param bool $append - set to true if output should be appended to $outputfile
62
     */
63 2
    public function run($outputFile = '/dev/null', $append = false)
64
    {
65 2
        if($this->command === null) {
66
            return;
67
        }
68
69 2
        switch ($this->getOS()) {
70 2
            case self::OS_WINDOWS:
71
                shell_exec(sprintf('%s &', $this->command, $outputFile));
72
                break;
73 2
            case self::OS_NIX:
74 2
                $this->pid = (int)shell_exec(sprintf('%s %s %s 2>&1 & echo $!', $this->command, ($append) ? '>>' : '>', $outputFile));
75 2
                break;
76
            default:
77
                throw new RuntimeException(sprintf(
78
                    'Could not execute command "%s" because operating system "%s" is not supported by '.
79
                    'Cocur\BackgroundProcess.',
80
                    $this->command,
81
                    PHP_OS
82
                ));
83 2
        }
84 2
    }
85
86
    /**
87
     * Returns if the process is currently running.
88
     *
89
     * @return bool TRUE if the process is running, FALSE if not.
90
     */
91 1
    public function isRunning()
92
    {
93 1
        $this->checkSupportingOS('Cocur\BackgroundProcess can only check if a process is running on *nix-based '.
94 1
                                 'systems, such as Unix, Linux or Mac OS X. You are running "%s".');
95
96
        try {
97 1
            $result = shell_exec(sprintf('ps %d 2>&1', $this->pid));
98 1
            if (count(preg_split("/\n/", $result)) > 2 && !preg_match('/ERROR: Process ID out of range/', $result)) {
99 1
                return true;
100
            }
101
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
102
        }
103
104
        return false;
105
    }
106
107
    /**
108
     * Stops the process.
109
     *
110
     * @return bool `true` if the processes was stopped, `false` otherwise.
111
     */
112 1
    public function stop()
0 ignored issues
show
Coding Style introduced by
function stop() does not seem to conform to the naming convention (^(?:is|has|should|may|supports|filter)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
113
    {
114 1
        $this->checkSupportingOS('Cocur\BackgroundProcess can only stop a process on *nix-based systems, such as '.
115 1
                                 'Unix, Linux or Mac OS X. You are running "%s".');
116
117
        try {
118 1
            $result = shell_exec(sprintf('kill %d 2>&1', $this->pid));
119 1
            if (!preg_match('/No such process/', $result)) {
120 1
                return true;
121
            }
122
        } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
123
        }
124
125
        return false;
126
    }
127
128
    /**
129
     * Returns the ID of the process.
130
     *
131
     * @return int The ID of the process
132
     */
133 1
    public function getPid()
134
    {
135 1
        $this->checkSupportingOS('Cocur\BackgroundProcess can only return the PID of a process on *nix-based systems, '.
136 1
                                 'such as Unix, Linux or Mac OS X. You are running "%s".');
137
138 1
        return $this->pid;
139
    }
140
141
    /**
142
     * Set the process id.
143
     *
144
     * @param $pid
145
     */
146
    public function setPid($pid)
147
    {
148
        $this->pid = $pid;
149
        return $this;
150
    }
151
152
    /**
153
     * @return int
154
     */
155 5
    protected function getOS()
156
    {
157 5
        $os = strtoupper(PHP_OS);
158
159 5
        if (substr($os, 0, 3) === 'WIN') {
160
            return self::OS_WINDOWS;
161 5
        } else if ($os === 'LINUX' || $os === 'FREEBSD' || $os === 'DARWIN') {
162 5
            return self::OS_NIX;
163
        }
164
165
        return self::OS_OTHER;
166
    }
167
168
    /**
169
     * @param string $message Exception message if the OS is not supported
170
     *
171
     * @throws RuntimeException if the operating system is not supported by Cocur\BackgroundProcess
172
     *
173
     * @codeCoverageIgnore
174
     */
175
    protected function checkSupportingOS($message)
176
    {
177
        if ($this->getOS() !== self::OS_NIX) {
178
            throw new RuntimeException(sprintf($message, PHP_OS));
179
        }
180
    }
181
182
    /**
183
     * @param int $pid PID of process to resume
184
     *
185
     * @return Cocur\BackgroundProcess\BackgroundProcess
0 ignored issues
show
Documentation introduced by
Should the return type not be BackgroundProcess?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
186
     */
187 1
    static public function createFromPID($pid) {
188 1
        $process = new self();
189 1
        $process->setPid($pid);
190
191 1
        return $process;
192
    }
193
}
194