11
11
12
12
class Shell {
13
13
14
- const STDIN = 0 ;
15
- const STDOUT = 1 ;
16
- const STDERR = 2 ;
14
+ const STDIN_DESCRIPTOR_KEY = 0 ;
15
+ const STDOUT_DESCRIPTOR_KEY = 1 ;
16
+ const STDERR_DESCRIPTOR_KEY = 2 ;
17
17
18
18
protected $ command ;
19
19
protected $ cwd ;
20
20
protected $ descriptors ;
21
21
protected $ env ;
22
+ protected $ error ;
22
23
protected $ input ;
23
24
protected $ output ;
24
25
protected $ pipes ;
25
26
protected $ process ;
27
+ protected $ startTime ;
26
28
protected $ status ;
27
- protected $ error ;
28
29
protected $ timeout ;
29
30
30
31
public function __construct (string $ command , string $ cwd = null , $ input = null , $ env = null , $ timeout = 60 )
@@ -35,29 +36,43 @@ public function __construct(string $command, string $cwd = null, $input = null,
35
36
36
37
$ this ->command = $ command ;
37
38
$ this ->cwd = $ cwd ;
38
- $ this ->descriptors = $ this ->getDescriptors ();
39
39
$ this ->env = $ env ;
40
40
$ this ->input = $ input ;
41
41
$ this ->timeout = $ timeout ;
42
42
}
43
43
44
44
public function execute ()
45
45
{
46
- $ descriptors = $ this ->getDescriptors ();
46
+ $ this ->start ();
47
+ $ this ->wait ();
48
+ }
49
+
50
+ public function start ()
51
+ {
52
+ if ($ this ->isRunning ()) {
53
+ throw new RuntimeException ('Process is already running ' );
54
+ }
47
55
48
- $ this ->process = proc_open ($ this ->command , $ descriptors , $ this ->pipes , $ this ->cwd , $ this ->env );
56
+ $ this ->descriptors = $ this ->getDescriptors ();
57
+
58
+ $ this ->process = proc_open ($ this ->command , $ this ->descriptors , $ this ->pipes , $ this ->cwd , $ this ->env );
49
59
50
60
if (!\is_resource ($ this ->process )) {
51
61
throw new RuntimeException ('Bad program could not be started. ' );
52
62
}
63
+
64
+ $ this ->setInput ();
65
+
66
+ $ this ->startTime = microtime (true );
67
+ $ this ->status = $ this ->updateStatus ();
53
68
}
54
69
55
70
public function getDescriptors ()
56
71
{
57
72
return array (
58
- self ::STDIN => array ("pipe " , "r " ),
59
- self ::STDOUT => array ("pipe " , "w " ),
60
- self ::STDERR => array ("pipe " , "r " )
73
+ self ::STDIN_DESCRIPTOR_KEY => array ("pipe " , "r " ),
74
+ self ::STDOUT_DESCRIPTOR_KEY => array ("pipe " , "w " ),
75
+ self ::STDERR_DESCRIPTOR_KEY => array ("pipe " , "r " )
61
76
);
62
77
}
63
78
@@ -70,28 +85,60 @@ public function getOutput()
70
85
{
71
86
$ this ->output = stream_get_contents ($ this ->pipes [1 ]);
72
87
73
-
74
88
return $ this ->output ;
75
89
}
76
90
77
- public function getStatus ()
91
+ public function getErrorOutput ()
92
+ {
93
+ $ this ->error = stream_get_contents ($ this ->pipes [2 ]);
94
+
95
+ return $ this ->error ;
96
+ }
97
+
98
+ public function checkTimeout ()
99
+ {
100
+ if ($ this ->timeout && $ this ->timeout < microtime (true ) - $ this ->startTime ) {
101
+ $ this ->stop ();
102
+ }
103
+
104
+ return $ this ->status ;
105
+ }
106
+
107
+ public function updateStatus ()
78
108
{
79
109
$ this ->status = proc_get_status ($ this ->process );
110
+
111
+ if (!$ this ->isRunning ()) {
112
+ $ this ->stop ();
113
+ }
114
+
80
115
return $ this ->status ;
81
116
}
82
117
83
- public function getErrorOutput ()
118
+ public function wait ()
84
119
{
85
- $ this ->error = stream_get_contents ($ this ->pipes [2 ]);
86
- return $ this ->error ;
120
+ while ($ this ->isRunning ()) {
121
+ usleep (1000 );
122
+ $ this ->checkTimeout ();
123
+ $ this ->updateStatus ();
124
+ }
125
+
126
+ return $ this ->status ;
127
+ }
128
+
129
+ public function isRunning ()
130
+ {
131
+ return $ this ->status ['running ' ];
87
132
}
88
133
89
134
public function stop ()
90
135
{
91
136
fclose ($ this ->pipes [0 ]);
92
137
fclose ($ this ->pipes [1 ]);
93
138
fclose ($ this ->pipes [2 ]);
94
- return proc_close ($ this ->process );
139
+ proc_close ($ this ->process );
140
+
141
+ return $ this ->status ;
95
142
}
96
143
97
144
public function kill ()
0 commit comments