Completed
Push — master ( 130f0c...84b420 )
by Hu
02:48
created

TailReader::info()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Jenner
5
 * Date: 2015/10/14
6
 * Time: 9:52
7
 */
8
9
namespace Jenner\LogMonitor\Reader;
10
11
12
class TailReader implements ReaderInterface
13
{
14
    protected $file;
15
    protected $error_file;
16
    protected $handle;
17
    protected $pipes;
18
    protected $process;
19
20 6
    public function configure($file)
21
    {
22 6
        if (!file_exists($file)) {
23 3
            throw new \RuntimeException("log file is not exists. file:" . $file);
24
        }
25 3
        $this->file = $file;
26 3
    }
27
28
    /**
29
     * open stream
30
     */
31 3
    public function open()
32
    {
33 3
        $command = "tail -F {$this->file}";
34
        $descriptors = array(
35 3
            0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
36 3
            1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
37 3
            2 => array("file", "/dev/null", "a") // stderr is a file to write to
38 3
        );
39
40 3
        $cwd = '/tmp';
41 3
        $this->process = proc_open($command, $descriptors, $this->pipes, $cwd);
42 3
        $this->handle = $this->pipes[1];
43 3
    }
44
45
    public function info()
46
    {
47
        return $this->file;
48
    }
49
50
    /**
51
     * read from stream
52
     * @param null $length
53
     * @return bool|string If there is no more data to read, the process will be blocked
54
     */
55 3
    public function read($length = null)
56
    {
57 3
        return fgets($this->handle);
58
    }
59
60
    /**
61
     * close stream
62
     * @return mixed
63
     */
64 6
    public function close()
65
    {
66 6
        if(!is_resource($this->process)) {
67 3
            return;
68
        }
69 3
        $status = proc_get_status($this->process);
70 3
        if ($status['running'] == true) { //process ran too long, kill it
71
            //close all pipes that are still open
72 3
            @fclose($this->pipes[0]); //stdin
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
73 3
            @fclose($this->pipes[1]); //stdout
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
74 3
            @fclose($this->pipes[2]); //stderr
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
75
            //get the parent pid of the process we want to kill
76 3
            $parent_pid = $status['pid'];
77
            //use ps to get all the children of this process, and kill them
78 3
            $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $parent_pid`);
79 3
            foreach ($pids as $pid) {
80 3
                if (is_numeric($pid)) {
81 3
                    posix_kill($pid, 9); //9 is the SIGKILL signal
82 3
                }
83 3
            }
84
85 3
            proc_close($this->process);
86 3
        }
87 3
    }
88
89 6
    public function __destruct()
90
    {
91 6
        $this->close();
92
    }
93
}