mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-02 14:36:17 +00:00
headless console
This commit is contained in:
@ -12,7 +12,7 @@
|
||||
* @method static init(Server $server, string $asUser = null)
|
||||
* @method static setLog(string $logType, int $siteId = null)
|
||||
* @method static connect()
|
||||
* @method static string exec(string $command, string $log = '', int $siteId = null)
|
||||
* @method static string exec(string $command, string $log = '', int $siteId = null, ?bool $stream = false)
|
||||
* @method static string assertExecuted(array|string $commands)
|
||||
* @method static string assertExecutedContains(string $command)
|
||||
* @method static disconnect()
|
||||
|
@ -96,7 +96,7 @@ public function connect(bool $sftp = false): void
|
||||
* @throws SSHCommandError
|
||||
* @throws SSHConnectionError
|
||||
*/
|
||||
public function exec(string|array $commands, string $log = '', ?int $siteId = null): string
|
||||
public function exec(string $command, string $log = '', ?int $siteId = null, ?bool $stream = false): string
|
||||
{
|
||||
if ($log) {
|
||||
$this->setLog($log, $siteId);
|
||||
@ -112,18 +112,34 @@ public function exec(string|array $commands, string $log = '', ?int $siteId = nu
|
||||
throw new SSHConnectionError($e->getMessage());
|
||||
}
|
||||
|
||||
if (! is_array($commands)) {
|
||||
$commands = [$commands];
|
||||
}
|
||||
|
||||
try {
|
||||
$result = '';
|
||||
foreach ($commands as $command) {
|
||||
$result .= $this->executeCommand($command);
|
||||
if ($this->asUser) {
|
||||
$command = 'sudo su - '.$this->asUser.' -c '.'"'.addslashes($command).'"';
|
||||
}
|
||||
|
||||
return $result;
|
||||
$this->connection->setTimeout(0);
|
||||
if ($stream) {
|
||||
$this->connection->exec($command, function ($output) {
|
||||
$this->log?->write($output);
|
||||
echo $output;
|
||||
ob_flush();
|
||||
flush();
|
||||
});
|
||||
|
||||
return '';
|
||||
} else {
|
||||
$output = $this->connection->exec($command);
|
||||
|
||||
$this->log?->write($output);
|
||||
|
||||
if (Str::contains($output, 'VITO_SSH_ERROR')) {
|
||||
throw new Exception('SSH command failed with an error');
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
throw $e;
|
||||
throw new SSHCommandError($e->getMessage());
|
||||
}
|
||||
}
|
||||
@ -141,28 +157,6 @@ public function upload(string $local, string $remote): void
|
||||
$this->connection->put($remote, $local, SFTP::SOURCE_LOCAL_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function executeCommand(string $command): string
|
||||
{
|
||||
if ($this->asUser) {
|
||||
$command = 'sudo su - '.$this->asUser.' -c '.'"'.addslashes($command).'"';
|
||||
}
|
||||
|
||||
$this->connection->setTimeout(0);
|
||||
|
||||
$output = $this->connection->exec($command);
|
||||
|
||||
$this->log?->write($output);
|
||||
|
||||
if (Str::contains($output, 'VITO_SSH_ERROR')) {
|
||||
throw new Exception('SSH command failed with an error');
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
|
43
app/Http/Controllers/ConsoleController.php
Normal file
43
app/Http/Controllers/ConsoleController.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class ConsoleController extends Controller
|
||||
{
|
||||
public function index(Server $server): View
|
||||
{
|
||||
return view('console.index', [
|
||||
'server' => $server,
|
||||
]);
|
||||
}
|
||||
|
||||
public function run(Server $server, Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'user' => [
|
||||
'required',
|
||||
Rule::in(['root', $server->ssh_user]),
|
||||
],
|
||||
'command' => 'required|string',
|
||||
]);
|
||||
|
||||
return response()->stream(
|
||||
function () use ($server, $request) {
|
||||
$ssh = $server->ssh($request->user);
|
||||
$log = 'console-'.time();
|
||||
$ssh->exec(command: $request->command, log: $log, stream: true);
|
||||
},
|
||||
200,
|
||||
[
|
||||
'Cache-Control' => 'no-cache',
|
||||
'X-Accel-Buffering' => 'no',
|
||||
'Content-Type' => 'text/event-stream',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
@ -7,13 +7,14 @@
|
||||
use App\Facades\Toast;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class HandleSSHErrors
|
||||
{
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$res = $next($request);
|
||||
if ($res->exception) {
|
||||
if ($res instanceof Response && $res->exception) {
|
||||
if ($res->exception instanceof SSHConnectionError || $res->exception instanceof SSHCommandError) {
|
||||
Toast::error($res->exception->getMessage());
|
||||
|
||||
|
@ -34,7 +34,7 @@ public function connect(bool $sftp = false): void
|
||||
}
|
||||
}
|
||||
|
||||
public function exec(string|array $commands, string $log = '', ?int $siteId = null): string
|
||||
public function exec(string|array $commands, string $log = '', ?int $siteId = null, ?bool $stream = false): string
|
||||
{
|
||||
if ($log) {
|
||||
$this->setLog($log, $siteId);
|
||||
|
Reference in New Issue
Block a user