-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathShell.php
98 lines (89 loc) · 3.42 KB
/
Shell.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php
namespace ArtSkills\Lib;
use ArtSkills\Traits\Library;
/**
* Запуск команд в командной строке
* Просто обёртка над exec() с небольшими удобствами
*/
class Shell
{
use Library;
/**
* Выполнить команду в консоли
*
* @param string|string[] $commands
* @param bool $withErrors перенаправлять stderr в stdout
* @param bool $stopOnFail если передан список команд, то останавливаться ли на ошибке (склеивать команды через && или ;)
* @return array [успех, вывод, результирующая команда, код возврата]
*/
public static function exec($commands, $withErrors = true, $stopOnFail = true)
{
$resultCommand = self::_processCommandList($commands, $withErrors, $stopOnFail);
return self::_exec($resultCommand);
}
/**
* Запустить и не ждать выполнения
*
* @param string $command
* @param string $outputRedirect
*/
public static function execInBackground($command, $outputRedirect = '/dev/null')
{
exec('nohup ' . $command . ' > ' . escapeshellarg($outputRedirect) . ' 2>&1 &');
}
/**
* Выполнить команду в консоли из определённого места
*
* @param string $directory
* @param string|string[] $commands
* @param bool $withErrors перенаправлять stderr в stdout
* @param bool $stopOnFail если передан список команд, то останавливаться ли на ошибке (склеивать команды через && или ;)
* Но если свалится смена директорий, то дальше не пойдёт независимо от этого параметра
* @return array [успех, вывод, результирующая команда, код возврата]
*/
public static function execFromDir($directory, $commands, $withErrors = true, $stopOnFail = true)
{
$resultCommand = self::_processCommandList($commands, $withErrors, $stopOnFail);
if (!empty($directory) && (getcwd() !== $directory)) {
$cdCommand = 'cd ' . escapeshellarg($directory) . ($withErrors ? ' 2>&1' : '');
$resultCommand = "$cdCommand && ($resultCommand)";
}
return self::_exec($resultCommand);
}
/**
* Обёртка вызова exec для целей мока в тесте
*
* @param string $command
* @return array [успех, вывод, результирующая команда, код возврата]
*/
private static function _exec($command)
{
exec($command, $output, $returnCode);
return [$returnCode === 0, $output, $command, $returnCode];
}
/**
* Взять список команд и склеить их в одну строку в зависимости от параметров
*
* @param string|strings $commands
* @param bool $withErrors
* @param bool $stopOnFail
* @return string
*/
private static function _processCommandList($commands, $withErrors = true, $stopOnFail = true)
{
$commands = (array)$commands;
if ($stopOnFail) {
$glue = ' && ';
} else {
$glue = ' ; ';
}
if ($withErrors) {
$errorRedirect = ' 2>&1';
$glue = $errorRedirect . $glue;
$resultCommand = implode($glue, $commands) . $errorRedirect;
} else {
$resultCommand = implode($glue, $commands);
}
return $resultCommand;
}
}