Subversion Repositories php-qbpwcf

Rev

Rev 140 | Rev 162 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
/*
4
 
5
	QBPWCF, Quick Build PHP website Component base on Fedora Linux.
6
    Copyright (C) 2015~2024 Min-Jhin,Chen
7
 
8
    This file is part of QBPWCF.
9
 
10
    QBPWCF is free software: you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
12
    the Free Software Foundation, either version 3 of the License, or
13
    (at your option) any later version.
14
 
15
    QBPWCF is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
19
 
20
    You should have received a copy of the GNU General Public License
21
    along with QBPWCF.  If not, see <http://www.gnu.org/licenses/>.
22
 
23
*/
24
namespace qbpwcf;
25
 
26
/*
27
類別說明:
28
提供多執行序應用的類別.
29
參考資料:
30
https://www.php.net/manual/en/book.parallel.php
31
備註:
32
建構中
33
*/
34
class threads{
35
 
36
	/*
37
	#函式說明:
38
	#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.
39
	#回傳結果:
40
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
41
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
42
	#$result["function"],當前執行的函式名稱.
43
	#必填參數:
44
	#$method,物件,為物件實體或類別名稱,會自動置入該參數.
45
	#$arguments,陣列,為呼叫方法時所用的參數.
46
	#可省略參數:
47
	#無.
48
	#參考資料:
49
	#__call=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic
50
	#備註:
51
	#無.
52
	*/
53
	public function __call($method,$arguments){
54
 
55
		#取得當前執行的函式
56
		$result["function"]=__FUNCTION__;
57
 
58
		#設置執行不正常
59
		$result["status"]="false";
60
 
61
		#設置執行錯誤
62
		$result["error"][]=__NAMESPACE__ ."/".$method."() 不存在!";
63
 
64
		#設置所丟入的參數
65
		$result["error"][]=$arguments;
66
 
67
		#回傳結果
68
		return $result;
69
 
70
		}#function __call end
71
 
72
	/*
73
	#函式說明:
74
	#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.
75
	#回傳結果:
76
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
77
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
78
	#$result["function"],當前執行的函式名稱.
79
	#必填參數:
80
	#$method,物件,為物件實體或類別名稱,會自動置入該參數.
81
	#$arguments,陣列,為呼叫方法時所用的參數.
82
	#可省略參數:
83
	#無.
84
	#參考資料:
85
	#__call=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic
86
	#備註:
87
	#無.
88
	*/
89
	public static function __callStatic($method,$arguments){
90
 
91
		#取得當前執行的函式
92
		$result["function"]=__FUNCTION__;
93
 
94
		#設置執行不正常
95
		$result["status"]="false";
96
 
97
		#設置執行錯誤
98
		$result["error"][]="欲呼叫的". __NAMESPACE__ ."/".$method."() 不存在!";
99
 
100
		#設置所丟入的參數
101
		$result["error"][]=$arguments;
102
 
103
		#回傳結果
104
		return $result;
105
 
106
		}#function __callStatic end
107
 
108
	/*
109
	#函式說明:
110
	#展示多執行序運作.
111
	#回傳結果:
112
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
113
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
114
	#$result["function"],當前執行的函式名稱.
115
	#必填參數:
116
	#無.
117
	#可省略參數:
118
	#無.
119
	#參考資料:
120
	#無.
121
	#備註:
122
	#無.
123
	改用 proc 試試 https://www.php.net/manual/en/function.proc-open.php
124
	*/
125
	public static function demo(){
126
 
127
		#執行demo
128
		var_dump(self::proc_demo());
129
 
130
		}#function demo end
131
 
132
	/*
133
	#函式說明:
134
	#透過proc展示多執行序運作.
135
	#回傳結果:
136
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
137
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
138
	#$result["function"],當前執行的函式名稱.
139
	#必填參數:
140
	#無.
141
	#可省略參數:
142
	#無.
143
	#參考資料:
144
	#https://www.php.net/manual/en/function.proc-open.php
145
	#備註:
146
	#無.
147
	*/
148
	public static function proc_demo(){
149
 
150
		#初始化 descriptorspec
151
		$descriptorspec = array();
152
 
153
		#stdin is a pipe that the child will read from
154
		$descriptorspec[]=array("pipe", "r");
155
 
156
		#stdout is a pipe that the child will write to
157
		$descriptorspec[]=array("pipe", "w");
158
 
159
		#stderr is a pipe that the child will write to
160
		$descriptorspec[]=array("pipe", "w");
161
 
162
		#The initial working dir for the command. This must be an absolute directory path, or null if you want to use the default value (the working dir of the current PHP process) 
163
		$cwd = null;
164
 
165
		#An array with the environment variables for the command that will be run, or null to use the same environment as the current PHP process 
166
		$env = array("QBPWCF" => "Quick Build PHP Website Componment base on Fedora Linux");
167
 
168
		#初始化儲存要多執行序執行的程式
169
		$codes=array();
170
 
171
		#初始化要demo用的url
172
		$demoUrl="https://qbpwc.sourceforge.io/";
173
 
174
		#要多執行序執行的程式1
175
		$codes[]=array("bash","curl -v -L --ssl-reqd ".$demoUrl);
176
 
177
		#要多執行序執行的程式2
178
		$codes[]=array("bash","curl -v -L --ssl-reqd ".$demoUrl);
179
 
180
		#要多執行序執行的程式3
181
		$codes[]=array("bash","curl -v -L --ssl-reqd ".$demoUrl);
182
 
183
		#debug
184
		#var_dump(__LINE__,$codes);
185
 
186
		#儲存每個要執行的程式資訊
187
		$process=array();
188
 
189
		#針對每個要執行的程式內容
190
		foreach($codes as $index=>$code){
191
 
192
			#取得要用什麼程式執行
193
			$executeBy=$code[0];
194
 
195
			#取得要執行的程式內容
196
			$code=$code[1];
197
 
198
			#運行 php 程式,並儲存 resource
199
			$process[$index]["resource"] = proc_open($executeBy, $descriptorspec, $pipes, $cwd, $env);
200
 
201
			#儲存對應的 pipes
202
			$process[$index]["pipes"]=$pipes;
203
 
204
			#debug
205
			#var_dump(__LINE__,$process[$index]);
206
 
207
			#如果有成功執行
208
			if(is_resource($process[$index]["resource"])){
209
 
210
				#$pipes now looks like this:
211
				#0 => writeable handle connected to child stdin
212
				#1 => readable handle connected to child stdout
213
				#2 => readable handle connected to child stdin
214
 
215
				#寫入內容作為 $executeBy 的輸入
216
				$bytes2write=fwrite($process[$index]["pipes"][0], $code);
217
 
218
				#debug
219
				#var_dump(__LINE__,$bytes2write);
220
 
221
				#結束輸入
222
				fclose($process[$index]["pipes"][0]);
223
 
224
				}#if end
225
 
226
			#反之,代表運行 php 失敗
227
			else{
228
 
229
				#初始化暫存執行結果的變數
230
				$cmdRes=array();
231
 
232
				#設置執行失敗
233
				$cmdRes["status"]="false";
234
 
235
				#設置執行錯誤訊息
236
				$cmdRes["error"]="execute program by \"".$executeBy."\" failed!";
237
 
238
				#設置執行結果
239
				$result["content"][]=$cmdRes;
240
 
241
				}#else end
242
 
243
			}#foreach end
244
 
245
		#debug
246
		#var_dump(__LINE__,$process);
247
 
248
		#針對每個回饋
249
		foreach($process as $index => $ps){
250
 
251
			#取得 proc resource
252
			$resource=$ps["resource"];
253
 
254
			#取得標準輸出
255
			$stdout=stream_get_contents($process[$index]["pipes"][1]);
256
 
257
			#取得錯誤輸出
258
			$stderr=stream_get_contents($process[$index]["pipes"][2]);
259
 
260
			#debug
261
			#var_dump($stdout);
262
 
263
			#初始化暫存執行狀況的變數
264
			$cmdRes=array();
265
 
266
			#設置執行失敗訊息
267
			$cmdRes["error"]=$stderr;
268
 
269
			#設置執行結果
270
			$cmdRes["content"]=$stdout;
271
 
272
			#debug
273
			#var_dump($cmdRes);
274
 
275
			#結束讀取標準輸出
276
			fclose($process[$index]["pipes"][1]);
277
 
278
			#結束讀取錯誤輸出
279
			fclose($process[$index]["pipes"][2]);
280
 
281
			#It is important that you close any pipes before calling proc_close in order to avoid a deadlock
282
			$cmdRes["statusCode"] = proc_close($resource);
283
 
284
			#debug
285
			#var_dump($cmdRes["statusCode"]);
286
 
287
			#預設執行不正常
288
			$cmdRes["status"]="false";
289
 
290
			#如果執行正常
291
			if($cmdRes["statusCode"]===0){
292
 
293
				#設置執行正常
294
				$cmdRes["status"]="true";
295
 
296
				}#if end
297
 
298
			#保存結果
299
			$result["content"][]=$cmdRes;
300
 
301
			#debug
302
			#var_dump($result);
303
 
304
			}#foreach end
305
 
306
		#設置執行正常
307
		$result["status"]="true";
308
 
309
		#debug
310
		#var_dump($result);
311
 
312
		#回傳結果
313
		return $result;
314
 
315
		}#function proc_demo end
316
 
317
	/*
318
	#函式說明:
319
	#透過proc來多執行序運作.
320
	#回傳結果:
321
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
322
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
323
	#$result["function"],當前執行的函式名稱.
324
	#$result["argu"],使用的參數.
66 liveuser 325
	#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值,若為"?"則代表程序尚未結束,可透過proc_update函式進行資訊的更新與取得;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.
3 liveuser 326
	#必填參數:
66 liveuser 327
	#$conf["cmds"],字串陣列,每個元素代表單一程序要執行的指令與參數.
3 liveuser 328
	#$conf["cmds"]=array();
329
	#可省略參數:
330
	#$conf["wait"],字串,是否需要等待所有程序結束,預設為"true"要等待;反之為"false"不要等待.
331
	#$conf["wait"]="false";
140 liveuser 332
	#$conf["timeout"],字串陣列,每個元素代表單一程序執行的最大等待秒數,超過後將會強迫停止執行,僅當wait參數為"true"時生效.
333
	#$conf["timeout"]=array("10");
3 liveuser 334
	#$conf["workingDir"],字串陣列,個別程式執行時的家目錄,預設不指定.
335
	#$conf["workingDir"]=array("path");
336
	#$conf["envs"],2維字串陣列,每個元素代表個別程式執行時的指定環境變數,key變數名稱;value為變數內容.預設為array("QBPWCF" => "Quick Build PHP Website Componment base on Fedora Linux");
337
	#$conf["envs"]=array(array("key"=>"value"));
338
	#$conf["executeBy"],字串陣列,每個元素代表個別指令要用什麼程式執行,預設為"bash".
339
	#$conf["executeBy"]=array("bash");
340
	#參考資料:
341
	#https://www.php.net/manual/en/function.proc-open.php
342
	#https://www.php.net/manual/en/function.proc-get-status.php
140 liveuser 343
	#https://www.php.net/manual/en/function.proc-terminate.php
3 liveuser 344
	#備註:
345
	#若需要取得當下的執行狀況,請使用 self::proc_update 來更新.
346
	*/
347
	public static function proc(&$conf){
348
 
349
		#初始化要回傳的變數
350
		$result=array();
351
 
352
		#初始化當前執行的函數名稱
353
		$result["function"]=__FUNCTION__;
354
 
355
		#如果 $conf 不為陣列
66 liveuser 356
		if(gettype($conf)!=="array"){
3 liveuser 357
 
358
			#設置執行失敗
359
			$result["status"]="false";
360
 
361
			#設置執行錯誤訊息
362
			$result["error"][]="\$conf變數須為陣列形態";
363
 
364
			#如果傳入的參數為 null
66 liveuser 365
			if($conf===null){
3 liveuser 366
 
367
				#設置執行錯誤訊息
368
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
369
 
370
				}#if end
371
 
372
			#回傳結果
373
			return $result;
374
 
375
			}#if end
376
 
377
		#取得使用的參數
378
		$result["argu"]=$conf;
379
 
380
		#函式說明:
381
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
382
		#回傳結果:
383
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
384
		#$result["error"],執行不正常結束的錯訊息陣列.
385
		#$result["simpleError"],簡單表示的錯誤訊息.
386
		#$result["function"],當前執行的函式名稱.
387
		#$result["argu"],設置給予的參數.
388
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
389
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
390
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
391
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
392
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
393
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
394
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
395
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
396
		#必填參數:
397
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
398
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
399
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
400
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
401
		#可省略參數:
402
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
403
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("cmds");
404
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
405
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("array");
406
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
407
		#$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
408
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
409
		#$conf["canNotBeEmpty"]=array();
410
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
411
		#$conf["canBeEmpty"]=array();
412
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
140 liveuser 413
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wait","workingDir","envs","executeBy","timeout");
3 liveuser 414
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
140 liveuser 415
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wait","workingDir","envs","executeBy","timeout");
3 liveuser 416
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
140 liveuser 417
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array","array","array","array");
3 liveuser 418
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
140 liveuser 419
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",null,null,null,null);
3 liveuser 420
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
421
		#$conf["disallowAllSkipableVarIsEmpty"]="";
422
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
423
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
424
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
425
		#$conf["disallowAllSkipableVarNotExist"]="";
426
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
427
		#$conf["variableCheck::checkArguments"]["arrayCountEqualCheck"][]=array("");
428
		#參考資料:
429
		#array_keys=>http://php.net/manual/en/function.array-keys.php
430
		#備註:
431
		#無.
432
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
433
		unset($conf["variableCheck::checkArguments"]);
434
 
435
		#如果 $checkArguments["status"] 等於 "false"
436
		if($checkArguments["status"]==="false"){
437
 
438
			#設置錯誤識別
439
			$result["status"]="false";
440
 
441
			#設置錯誤訊息
442
			$result["error"]=$checkArguments;
443
 
444
			#回傳結果
445
			return $result;
446
 
447
			}#if end
448
 
449
		#如果 $checkArguments["passed"] 等於 "false"
450
		if($checkArguments["passed"]==="false"){
451
 
452
			#設置錯誤識別
453
			$result["status"]="false";
454
 
455
			#設置錯誤訊息
456
			$result["error"]=$checkArguments;
457
 
458
			#回傳結果
459
			return $result;
460
 
461
			}#if end
140 liveuser 462
 
3 liveuser 463
		#初始化 descriptorspec
464
		$descriptorspec = array();
465
 
466
		#stdin is a pipe that the child will read from
467
		$descriptorspec[]=array("pipe", "r");
468
 
469
		#stdout is a pipe that the child will write to
470
		$descriptorspec[]=array("pipe", "w");
471
 
472
		#stderr is a pipe that the child will write to
473
		$descriptorspec[]=array("pipe", "w");
140 liveuser 474
 
3 liveuser 475
		#The initial working dir for the command. This must be an absolute directory path, or null if you want to use the default value (the working dir of the current PHP process) 
476
		$defaultCWD = null;
477
 
478
		#初始化儲存每個指令的working dir.
479
		$cwds=array();
480
 
481
		#有幾個指令就執行幾次
482
		for($i=0;$i<count($conf["cmds"]);$i++){
483
 
484
			#設置預設working dir
485
			$cwds[]=$defaultCWD;
486
 
487
			}#for end
488
 
489
		#如果有設置 workingDir
490
		if(isset($conf["workingDir"])){
491
 
492
			#如果數量符合
493
			if(count($conf["cmds"])===count($conf["workingDir"])){
494
 
495
				#有幾個指令就執行幾次
496
				for($i=0;$i<count($conf["cmds"]);$i++){
497
 
498
					#預設為指定數值
499
					$cwds[]=$conf["workingDir"][$i];
500
 
501
					}#for end
502
 
503
				}#if end
504
 
505
			}#if end
506
 
507
		#An array with the environment variables for the command that will be run, or null to use the same environment as the current PHP process 
508
		$defaultENV = array("QBPWCF" => "Quick Build PHP Website Componment base on Fedora Linux");
509
 
510
		#初始化儲存每個指令的環境變數.
511
		$envs=array();
512
 
513
		#有幾個指令就執行幾次
514
		for($i=0;$i<count($conf["cmds"]);$i++){
515
 
516
			#設置預設環境變數
517
			$envs[]=$defaultENV;
518
 
519
			}#for end
520
 
521
		#如果有設置 envs
522
		if(isset($conf["envs"])){
523
 
524
			#如果數量符合
525
			if(count($conf["cmds"])===count($conf["envs"])){
526
 
527
				#有幾個指令就執行幾次
528
				for($i=0;$i<count($conf["cmds"]);$i++){
529
 
530
					#預設為指定數值
531
					$envs[]=$conf["envs"][$i];
532
 
533
					}#for end
534
 
535
				}#if end
536
 
537
			}#if end
538
 
539
		#預設程式都透過 bash 來執行
540
		$defaultExecBy="bash";
541
 
542
		#初始化儲存每個指令要透過什麼程式執行
543
		$executeBys=array();
544
 
545
		#有幾個指令就執行幾次
546
		for($i=0;$i<count($conf["cmds"]);$i++){
547
 
548
			#設置預設環境變數
549
			$executeBys[]=$defaultExecBy;
550
 
551
			}#for end
552
 
553
		#如果有設置 executeBy
554
		if(isset($conf["executeBy"])){
555
 
556
			#如果數量符合
557
			if(count($conf["cmds"])===count($conf["executeBy"])){
558
 
559
				#初始化儲存每個指令要透過什麼程式執行
560
				$executeBys=array();
561
 
562
				#有幾個指令就執行幾次
563
				for($i=0;$i<count($conf["cmds"]);$i++){
564
 
565
					#預設為指定數值
566
					$executeBys[]=$conf["executeBy"][$i];
567
 
568
					}#for end
569
 
570
				}#if end
571
 
572
			}#if end
573
 
574
		#儲存每個要執行的程式資訊
575
		$process=array();
576
 
577
		#debug
578
		#var_dump(__LINE__,$executeBys);
579
 
580
		#針對每個指令與參數字串
581
		foreach($conf["cmds"] as $index=>$cmdAndArguStr){
582
 
583
			#debug
584
			#var_dump(__LINE__,$executeBys[$index]);
585
 
586
			#運行 php 程式,並儲存 resource
587
			$process[$index]["resource"] = proc_open($executeBys[$index], $descriptorspec, $pipes, $cwds[$index], $envs[$index]);
66 liveuser 588
 
3 liveuser 589
			#儲存對應的 pipes
590
			$process[$index]["pipes"]=$pipes;
66 liveuser 591
 
3 liveuser 592
			#如果有成功執行
593
			if(is_resource($process[$index]["resource"])){
594
 
595
				#$pipes now looks like this:
596
				#0 => writeable handle connected to child stdin
597
				#1 => readable handle connected to child stdout
598
				#2 => readable handle connected to child stdin
599
 
600
				#寫入內容作為 $executeBy 的輸入
601
				$bytes2write=fwrite($process[$index]["pipes"][0], $cmdAndArguStr);
602
 
603
				#結束輸入
604
				fclose($process[$index]["pipes"][0]);
605
 
606
				#如果有完整寫入指令
607
				if($bytes2write===strlen($cmdAndArguStr)){
608
 
609
					#記錄輸入的指令
610
					$process[$index]["input"]=$cmdAndArguStr;
611
 
612
					}#if end
613
 
614
				#反之
615
				else{
616
 
617
					#設置錯誤識別
618
					$result["status"]="false";
619
 
620
					#設置錯誤訊息
621
					$result["error"][]="將指令(".$cmdAndArguStr.")輸入(".$executeBys[$index].")失敗";
622
 
623
					#回傳結果
624
					return $result;
625
 
626
					}#else end
627
 
628
				}#if end
629
 
630
			#反之,代表運行 $executeBys[$index] 失敗
631
			else{
632
 
633
				#初始化暫存執行結果的變數
634
				$cmdRes=array();
635
 
636
				#設置執行失敗
637
				$cmdRes["status"]="false";
638
 
639
				#設置執行錯誤訊息
640
				$cmdRes["error"]="execute program by \"".$executeBys[$index]."\" failed!";
641
 
642
				#設置執行結果
643
				$result["content"][]=$cmdRes;
644
 
645
				}#else end
646
 
647
			}#foreach end
648
 
649
		#針對每個回饋
650
		foreach($process as $index => $ps){
651
 
652
			#取得 proc resource
653
			$resource=&$ps["resource"];
654
 
655
			#取得標準輸出的pipe
656
			$stdout=$process[$index]["pipes"][1];
657
 
658
			#取得非標準輸出的pipe
659
			$stderr=$process[$index]["pipes"][2];
660
 
661
			#如果需要等待程序執行完
662
			if($conf["wait"]==="true"){
663
 
140 liveuser 664
				#如果有設置  timeout
665
				if(isset($conf["timeout"])){
666
 
667
					#如果有設置該程序的 timeout
668
					if(isset($conf["timeout"][$index])){
669
 
670
						#避免 timeout 仍然會等待程序結束 - start
671
 
672
						#不讓標準輸出會阻擋程式執行
673
						stream_set_blocking($stdout,false);
674
 
675
						#不讓錯誤輸出會阻擋程式執行
676
						stream_set_blocking($stderr,false);
677
 
678
						#避免 timeout 仍然會等待程序結束 - end
679
 
680
						}#if end
681
 
682
					}#if end
683
 
3 liveuser 684
				}#if end
685
 
686
			#反之
687
			else{
688
 
689
				#不讓標準輸出會阻擋程式執行
690
				stream_set_blocking($stdout,false);
691
 
692
				#不讓錯誤輸出會阻擋程式執行
693
				stream_set_blocking($stderr,false);
694
 
695
				}#else end
696
 
697
			#初始化暫存執行狀況的變數
698
			$cmdRes=array();
699
 
700
			#取得 proc_open 後的 process resource
701
			$cmdRes["process"]=$resource;
702
 
703
			#取得 process 的狀態,包含 pid 等資訊,若程式已經結束,則會自動將pipes關閉,再proc_close.
704
			$cmdRes["proc_get_status"]=proc_get_status($resource);
705
 
706
			#預設 statusCode 為 "?" 代表尚未 proc_close
707
			$cmdRes["statusCode"]="?";
708
 
709
			#如果執行已經結束,有回傳exitcode
710
			if($cmdRes["proc_get_status"]["exitcode"]!==-1){
711
 
712
				#設置 statusCode
713
				$cmdRes["statusCode"]=&$cmdRes["proc_get_status"]["exitcode"];
714
 
715
				}#if end
716
 
717
			#反之未執行完畢,且需要等待程序執行完
718
			else if($conf["wait"]==="true"){
719
 
140 liveuser 720
				#預設已經執行0秒
721
				$runtime=0;
722
 
3 liveuser 723
				#無窮迴圈
724
				while(true){
725
 
140 liveuser 726
					#debug
727
					#var_dump(__LINE__,$runtime,$conf["timeout"]);
728
 
729
					#如果有設置  timeout
730
					if(isset($conf["timeout"])){
731
 
732
						#如果有設置該程序的 timeout
733
						if(isset($conf["timeout"][$index])){
734
 
735
							#如果執行秒數逾時了
736
							if( $runtime > (int)($conf["timeout"][$index]) ){
737
 
738
								#debug
739
								#var_dump(__LINE__,"timeout!");
740
 
741
								#關閉標準輸出的pipe
742
								fclose($stdout);
743
 
744
								#關閉標準錯誤的pipe
745
								fclose($stderr);
746
 
747
								#強制結束程序
748
								proc_terminate($resource);
749
 
750
								#結束proc.
751
								proc_close($resource);
752
 
159 liveuser 753
								#結束無窮迴圈
754
								break;
140 liveuser 755
 
756
								}#if end
757
 
758
							}#if end
759
 
760
						}#if end
761
 
3 liveuser 762
					#取得 process 的狀態,包含 pid 等資訊,若程式已經結束,則會自動將pipes關閉,再proc_close.
763
					$cmdRes["proc_get_status"]=proc_get_status($resource);
764
 
765
					#如果執行已經結束,有回傳exitcode
766
					if($cmdRes["proc_get_status"]["exitcode"]!==-1){
767
 
768
						#設置 statusCode
769
						$cmdRes["statusCode"]=&$cmdRes["proc_get_status"]["exitcode"];
770
 
159 liveuser 771
						#結束無窮迴圈
3 liveuser 772
						break;
773
 
774
						}#if end
775
 
776
					#等待1秒鐘
777
					sleep(1);
140 liveuser 778
 
779
					#執行秒數+1
780
					$runtime++;
3 liveuser 781
 
782
					}#while end
783
 
784
				}#if end
785
 
786
			#設置執行失敗訊息
787
			$cmdRes["error"]=$stderr;
788
 
789
			#設置執行結果
790
			$cmdRes["content"]=$stdout;
791
 
792
			#如果有成功輸入指令
793
			if(isset($process[$index]["input"])){
794
 
795
				#設置有輸入的指令
796
				$cmdRes["input"]=$process[$index]["input"];
797
 
798
				}#if end
799
 
800
			#預設執行不正常
801
			$cmdRes["status"]="false";
802
 
803
			#如果執行正常 或 等於"?"(代表尚未 proc_close)
804
			if($cmdRes["statusCode"]===0 || $cmdRes["statusCode"]==="?"){
805
 
806
				#設置執行正常
807
				$cmdRes["status"]="true";
808
 
809
				}#if end
810
 
811
			#保存結果
812
			$result["content"][]=$cmdRes;
813
 
814
			}#foreach end
815
 
816
		#設置執行正常
817
		$result["status"]="true";
818
 
819
		#回傳結果
820
		return $result;
821
 
822
		}#function proc end
823
 
824
	/*
825
	#函式說明:
826
	#更新透過proc執行的多程序資訊.
827
	#回傳結果:
828
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
829
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
830
	#$result["function"],當前執行的函式名稱.
831
	#$result["argu"],使用的參數.
66 liveuser 832
	#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值,若為"?"則代表程序尚未結束,可透過proc_update函式進行資訊的更新與取得;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.
3 liveuser 833
	#必填參數:
834
	#$conf["procs"],陣列,運行self::proc後回傳的content.
835
	$conf["procs"]=$procs;
836
	#可省略參數:
837
	#無.
838
	#參考資料:
839
	#無.
840
	#備註:
841
	#無.
842
	*/
843
	public static function proc_update(&$conf){
844
 
845
		#初始化要回傳的變數
846
		$result=array();
847
 
848
		#初始化當前執行的函數名稱
849
		$result["function"]=__FUNCTION__;
850
 
851
		#如果 $conf 不為陣列
852
		if(gettype($conf)!="array"){
853
 
854
			#設置執行失敗
855
			$result["status"]="false";
856
 
857
			#設置執行錯誤訊息
858
			$result["error"][]="\$conf變數須為陣列形態";
859
 
860
			#如果傳入的參數為 null
861
			if($conf==null){
862
 
863
				#設置執行錯誤訊息
864
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
865
 
866
				}#if end
867
 
868
			#回傳結果
869
			return $result;
870
 
871
			}#if end
872
 
873
		#取得使用的參數
874
		$result["argu"]=$conf;
875
 
876
		#函式說明:
877
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
878
		#回傳結果:
879
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
880
		#$result["error"],執行不正常結束的錯訊息陣列.
881
		#$result["simpleError"],簡單表示的錯誤訊息.
882
		#$result["function"],當前執行的函式名稱.
883
		#$result["argu"],設置給予的參數.
884
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
885
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
886
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
887
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
888
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
889
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
890
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
891
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
892
		#必填參數:
893
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
894
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
895
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
896
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
897
		#可省略參數:
898
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
899
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("procs");
900
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
901
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("array");
902
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
903
		#$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
904
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
905
		$conf["variableCheck::checkArguments"]["canNotBeEmpty"]=array("procs");
906
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
907
		#$conf["canBeEmpty"]=array();
908
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
909
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wait","workingDir","envs","executeBy");
910
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
911
		#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wait","workingDir","envs","executeBy");
912
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
913
		#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array","array","array");
914
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
915
		#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",null,null,null);
916
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
917
		#$conf["disallowAllSkipableVarIsEmpty"]="";
918
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
919
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
920
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
921
		#$conf["disallowAllSkipableVarNotExist"]="";
922
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
923
		#$conf["variableCheck::checkArguments"]["arrayCountEqualCheck"][]=array("");
924
		#參考資料:
925
		#array_keys=>http://php.net/manual/en/function.array-keys.php
926
		#備註:
927
		#無.
928
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
929
		unset($conf["variableCheck::checkArguments"]);
930
 
931
		#如果 $checkArguments["status"] 等於 "false"
932
		if($checkArguments["status"]==="false"){
933
 
934
			#設置錯誤識別
935
			$result["status"]="false";
936
 
937
			#設置錯誤訊息
938
			$result["error"]=$checkArguments;
939
 
940
			#回傳結果
941
			return $result;
942
 
943
			}#if end
944
 
945
		#如果 $checkArguments["passed"] 等於 "false"
946
		if($checkArguments["passed"]==="false"){
947
 
948
			#設置錯誤識別
949
			$result["status"]="false";
950
 
951
			#設置錯誤訊息
952
			$result["error"]=$checkArguments;
953
 
954
			#回傳結果
955
			return $result;
956
 
957
			}#if end
958
 
959
		#檢查 content
960
		/*
961
		#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.
962
		*/
963
 
964
		#針對每個程序
965
		foreach($conf["procs"] as $index => $proc){
966
 
967
			#函式說明:
968
			#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
969
			#回傳結果:
970
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
971
			#$result["error"],執行不正常結束的錯訊息陣列.
972
			#$result["simpleError"],簡單表示的錯誤訊息.
973
			#$result["function"],當前執行的函式名稱.
974
			#$result["argu"],設置給予的參數.
975
			#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
976
			#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
977
			#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
978
			#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
979
			#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
980
			#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
981
			#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
982
			#$result["notNeedVar"],字串陣列,多餘的參數名稱.
983
			#必填參數:
984
			#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
985
			$conf["variableCheck::checkArguments"]["varInput"]=&$proc;
986
			#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
987
			$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
988
			#可省略參數:
989
			#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
990
			$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("status","statusCode","content","error","input","process","proc_get_status");
991
			#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
992
			$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string",null,null,null,"string","resource","array");
993
			#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
994
			#$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
995
			#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
996
			#$conf["variableCheck::checkArguments"]["canNotBeEmpty"]=array("procs");
997
			#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
998
			#$conf["variableCheck::checkArguments"]["canBeEmpty"]=array();
999
			#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
1000
			#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wait","workingDir","envs","executeBy");
1001
			#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
1002
			#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("error");
1003
			#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
1004
			#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("array");
1005
			#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
1006
			#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",null,null,null);
1007
			#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
1008
			#$conf["disallowAllSkipableVarIsEmpty"]="";
1009
			#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
1010
			#$conf["disallowAllSkipableVarIsEmptyArray"]="";
1011
			#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
1012
			#$conf["disallowAllSkipableVarNotExist"]="";
1013
			#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
1014
			#$conf["variableCheck::checkArguments"]["arrayCountEqualCheck"][]=array("");
1015
			#參考資料:
1016
			#array_keys=>http://php.net/manual/en/function.array-keys.php
1017
			#備註:
1018
			#無.
1019
			$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
1020
			unset($conf["variableCheck::checkArguments"]);
1021
 
1022
			#如果 $checkArguments["status"] 等於 "false"
1023
			if($checkArguments["status"]==="false"){
1024
 
1025
				#設置錯誤識別
1026
				$result["status"]="false";
1027
 
1028
				#設置錯誤訊息
1029
				$result["error"]=$checkArguments;
1030
 
1031
				#回傳結果
1032
				return $result;
1033
 
1034
				}#if end
1035
 
1036
			#如果 $checkArguments["passed"] 等於 "false"
1037
			if($checkArguments["passed"]==="false"){
1038
 
1039
				#設置錯誤識別
1040
				$result["status"]="false";
1041
 
1042
				#設置錯誤訊息
1043
				$result["error"]=$checkArguments;
1044
 
1045
				#回傳結果
1046
				return $result;
1047
 
1048
				}#if end
1049
 
1050
			#如果可能尚在執行中
1051
			if($proc["statusCode"]==="?"){
1052
 
1053
				#取得當下的狀態
1054
				$proc_get_status=proc_get_status($proc["process"]);
1055
 
1056
				#如果執行已經結束,有回傳exitcode
1057
				if($proc_get_status["exitcode"]!==-1){
1058
 
1059
					#設置 statusCode
1060
					$conf["procs"][$index]["statusCode"]=$proc_get_status["exitcode"];
1061
 
1062
					#取得標準輸出
1063
					$stdout=stream_get_contents($proc["content"]);
1064
 
1065
					#取得錯誤輸出
1066
					$stderr=stream_get_contents($proc["error"]);
1067
 
1068
					#設置執行失敗訊息
1069
					$conf["procs"][$index]["error"]=$stderr;
1070
 
1071
					#設置執行結果
1072
					$conf["procs"][$index]["content"]=$stdout;
1073
 
1074
					}#if end
1075
 
1076
				}#if end
1077
 
1078
			}#foreach end
1079
 
1080
		#設置要回傳的結果
1081
		$result["content"]=$conf["procs"];
1082
 
1083
		#設置執行正常
1084
		$result["status"]="true";
1085
 
1086
		#回傳結果
1087
		return $result;
1088
 
1089
		}#function proc_update end
1090
 
1091
	/*
1092
	#函式說明:
1093
	#透過parallel展示多執行序運作.
1094
	#回傳結果:
1095
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
1096
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
1097
	#$result["function"],當前執行的函式名稱.
1098
	#必填參數:
1099
	#無.
1100
	#可省略參數:
1101
	#無.
1102
	#參考資料:
1103
	#https://www.php.net/manual/en/class.parallel-runtime.php
1104
	#備註:
1105
	#需要於編譯PHP時啟用該套件	
1106
	*/
1107
	public static function parallel_demo(){
1108
 
1109
		#初始化要回傳的結果
1110
		$result=array();
1111
 
1112
		#取得當前執行的函數名稱
1113
		$result["function"]=__FUNCTION__;
1114
 
1115
		#新增程序r1
1116
		$r1=new \parallel\Runtime();
1117
 
1118
		#r1要執行的函式
1119
		$thread_r1_function=function($conf){
1120
 
1121
			#提示開始
1122
			echo $conf["id"]." start".PHP_EOL;
1123
 
1124
			#跑 $conf["i"] 次
1125
			for($i=0;$i<$conf["i"];$i++){
1126
 
1127
				#題書$i數值
1128
				echo "\$i=".$i.PHP_EOL;
1129
 
1130
				}#for end
1131
 
1132
			#提示結束
1133
			echo $conf["id"]." end".PHP_EOL;
1134
 
1135
			};#function end
1136
 
1137
		#r1的參數
1138
		$args_r1=array();
1139
		$args_r1["id"]="r1";
1140
		$args_r1["i"]=10;
1141
 
1142
		#運行程序r1
1143
		#程序函式為 $thread_r1_function
1144
		#參數陣列為 $args_r1
1145
		$future_r1=$r1->run($thread_r1_function, $args_r1);
1146
 
1147
		#新增程序r2
1148
		$r2=new \parallel\Runtime();
1149
 
1150
		#r2要執行的函式
1151
		$thread_r2_function=function($conf){
1152
 
1153
			#提示開始
1154
			echo $conf["id"]." start".PHP_EOL;
1155
 
1156
			#跑 $conf["i"] 次
1157
			for($i=$conf["i"];$i>0;$i--){
1158
 
1159
				#題書$i數值
1160
				echo "\$i=".$i.PHP_EOL;
1161
 
1162
				}#for end
1163
 
1164
			#提示結束
1165
			echo $conf["id"]." end".PHP_EOL;
1166
 
1167
			};#function end
1168
 
1169
		#r2的參數
1170
		$args_r2=array();
1171
		$args_r2["id"]="r2";
1172
		$args_r2["i"]=10;
1173
 
1174
		#運行程序r2
1175
		#程序函式為 $thread__r2_function
1176
		#參數陣列為 $args_r2
1177
		$future_r2=$r2->run($thread_r2_function, $args_r2);
1178
 
1179
		#存放有多少在執行的程序
1180
		$futureArray=array();
1181
		$futureArray[]=$future_r1;
1182
		$futureArray[]=$future_r2;
1183
 
1184
		#當有程序尚未結束時
1185
		while(!empty($futureArray)){
1186
 
1187
			#針對每個 Future
1188
			foreach($futureArray as $index => $Future){
1189
 
1190
				#如果執行完成了
1191
				if($Future->done()){
1192
 
1193
					#移除之
1194
					unset($futureArray[$index]);
1195
 
1196
					}#if end
1197
 
1198
				}#foreach end
1199
 
1200
			}#while end
1201
 
1202
		#提示所有程序都執行結束了
1203
		echo "all done!".PHP_EOL;
1204
 
1205
		#設置執行正常
1206
		$result["status"]="true";
1207
 
1208
		#回傳結果
1209
		return $result;
1210
 
1211
		}#function parallel_demo end
1212
 
1213
	/*
1214
	#函式說明:
1215
	#透過 unix socket 來多執行序運作.
1216
	#回傳結果:
1217
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
1218
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
1219
	#$result["function"],當前執行的函式名稱.
1220
	#$result["argu"],使用的參數.
1221
	#$result["content"],陣列,每個元素為cmds參數中個別元素其指令傳送後得到的uuid,可透過sock::getProcInfo來查詢結果.
1222
	#必填參數:
1223
	#$conf["cmds"],字串陣列,每個元素代表要執行的指令與參數.
1224
	#$conf["cmds"]=array();
1225
	#可省略參數:
1226
	#$conf["sock"],字串,要連線的 usr/bin/qbpwcf-sock.php 所產生的 unix domain socket 路徑與名稱,預設為 qbpwcf_usock_path.
1227
	#$conf["sock"]=qbpwcf_usock_path;
1228
	#參考資料:
1229
	#無
1230
	#備註:
1231
	#需要透過sock::unixDomainSockServer來運行.
1232
	*/
1233
	public static function socket(&$conf){
1234
 
1235
		#初始化要回傳的變數
1236
		$result=array();
1237
 
1238
		#初始化當前執行的函數名稱
1239
		$result["function"]=__FUNCTION__;
1240
 
1241
		#如果 $conf 不為陣列
1242
		if(gettype($conf)!="array"){
1243
 
1244
			#設置執行失敗
1245
			$result["status"]="false";
1246
 
1247
			#設置執行錯誤訊息
1248
			$result["error"][]="\$conf變數須為陣列形態";
1249
 
1250
			#如果傳入的參數為 null
1251
			if($conf==null){
1252
 
1253
				#設置執行錯誤訊息
1254
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
1255
 
1256
				}#if end
1257
 
1258
			#回傳結果
1259
			return $result;
1260
 
1261
			}#if end
1262
 
1263
		#取得使用的參數
1264
		$result["argu"]=$conf;
1265
 
1266
		#函式說明:
1267
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
1268
		#回傳結果:
1269
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
1270
		#$result["error"],執行不正常結束的錯訊息陣列.
1271
		#$result["simpleError"],簡單表示的錯誤訊息.
1272
		#$result["function"],當前執行的函式名稱.
1273
		#$result["argu"],設置給予的參數.
1274
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
1275
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
1276
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
1277
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
1278
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
1279
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
1280
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
1281
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
1282
		#必填參數:
1283
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
1284
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
1285
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
1286
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
1287
		#可省略參數:
1288
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
1289
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("cmds");
1290
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
1291
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("array");
1292
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
1293
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
1294
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
1295
		#$conf["canNotBeEmpty"]=array();
1296
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
1297
		#$conf["canBeEmpty"]=array();
1298
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
1299
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("sock");
1300
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
1301
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("sock");
1302
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
1303
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
1304
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
1305
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null);
1306
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
1307
		#$conf["disallowAllSkipableVarIsEmpty"]="";
1308
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
1309
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
1310
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
1311
		#$conf["disallowAllSkipableVarNotExist"]="";
1312
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
1313
		#$conf["variableCheck::checkArguments"]["arrayCountEqualCheck"][]=array("");
1314
		#參考資料:
1315
		#array_keys=>http://php.net/manual/en/function.array-keys.php
1316
		#備註:
1317
		#無.
1318
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
1319
		unset($conf["variableCheck::checkArguments"]);
1320
 
1321
		#如果 $checkArguments["status"] 等於 "false"
1322
		if($checkArguments["status"]==="false"){
1323
 
1324
			#設置錯誤識別
1325
			$result["status"]="false";
1326
 
1327
			#設置錯誤訊息
1328
			$result["error"]=$checkArguments;
1329
 
1330
			#回傳結果
1331
			return $result;
1332
 
1333
			}#if end
1334
 
1335
		#如果 $checkArguments["passed"] 等於 "false"
1336
		if($checkArguments["passed"]==="false"){
1337
 
1338
			#設置錯誤識別
1339
			$result["status"]="false";
1340
 
1341
			#設置錯誤訊息
1342
			$result["error"]=$checkArguments;
1343
 
1344
			#回傳結果
1345
			return $result;
1346
 
1347
			}#if end
1348
 
1349
		#針對每個指令
1350
		foreach($conf["cmds"] as $cmd){
1351
 
1352
			#連線到 usr/bin/qbpwcf-usock.php 產生的  unix domain socket,運行指定的指令.
1353
			#回傳結果:
1354
			#$result["status"],"true"代表執行正常;"false"代表執行不正常.
1355
			#$result["error"],錯誤訊息陣列.
1356
			#$result["function"],當前執行的函式名稱.
1357
			#$result["argu"],使用的參數.
1358
			#$result["content"],執行完指令的結果.
1359
			#必填參數:
1360
			#$conf["fileArgu"],字串,變數__FILE__的內容.
1361
			$conf["sock::execAnyCmdByQBPWCFunixSocket"]["fileArgu"]=__FILE__;
1362
			#$conf["command"],字串,要執行的指令名稱.
1363
			$conf["sock::execAnyCmdByQBPWCFunixSocket"]["command"]=$cmd;
1364
			#可省略參數:
1365
 
1366
			#如果有設置 sock 參數
1367
			if(isset($conf["sock"])){
1368
 
1369
				#$conf["sock"],字串,要連線的 usr/bin/qbpwcf-sock.php 所產生的 unix domain socket 路徑與名稱,預設為 qbpwcf_usock_path.
1370
				$conf["sock::execAnyCmdByQBPWCFunixSocket"]["sock"]=$conf["sock"];
1371
 
1372
				}#if end
1373
 
1374
			#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
1375
			#$conf["sock::execAnyCmdByQBPWCFunixSocket"]["argu"]=$conf["argu"];
1376
			#$conf["commandIncludeArgu"],字串,是否command含有參數,預設為"false"代表沒有;反之為"true".
1377
			$conf["sock::execAnyCmdByQBPWCFunixSocket"]["commandIncludeArgu"]="true";
1378
			#$conf["commandInBg"],字串,是否要將程序放在背景執行,再取得相關資訊,預設為"false"代表不要;反之為"true".
1379
			$conf["sock::execAnyCmdByQBPWCFunixSocket"]["commandInBg"]="true";
1380
			#參考資料:
1381
			#無.
1382
			#備註:
1383
			#無.
1384
			$execAnyCmdByQBPWCFunixSocket=sock::execAnyCmdByQBPWCFunixSocket($conf["sock::execAnyCmdByQBPWCFunixSocket"]);
1385
			unset($conf["sock::execAnyCmdByQBPWCFunixSocket"]);
1386
 
1387
			#如果執行失敗
1388
			if($execAnyCmdByQBPWCFunixSocket["status"]==="false"){
1389
 
1390
				#設置錯誤識別
1391
				$result["status"]="false";
1392
 
1393
				#設置錯誤訊息
1394
				$result["error"]=$execAnyCmdByQBPWCFunixSocket;
1395
 
1396
				#回傳結果
1397
				return $result;
1398
 
1399
				}#if end
1400
 
1401
			#debug
1402
			#var_dump(__LINE__,$execAnyCmdByQBPWCFunixSocket);
1403
 
1404
			#儲存收到的回應
1405
			$result["content"][]=$execAnyCmdByQBPWCFunixSocket["content"];
1406
 
1407
			}#foreach end
1408
 
1409
		#設置執行正常
1410
		$result["status"]="true";
1411
 
1412
		#回傳結果
1413
		return $result;
1414
 
1415
		}#function socket end
1416
 
1417
	}#class threads end