83 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace App\Jobs;
 | |
| 
 | |
| use App\Models\Server;
 | |
| use Carbon\Carbon;
 | |
| use Illuminate\Bus\Queueable;
 | |
| use Illuminate\Contracts\Queue\ShouldQueue;
 | |
| use Illuminate\Foundation\Bus\Dispatchable;
 | |
| use Illuminate\Queue\InteractsWithQueue;
 | |
| use Illuminate\Queue\SerializesModels;
 | |
| use Illuminate\Support\Facades\Process;
 | |
| use Illuminate\Support\Facades\Storage;
 | |
| 
 | |
| class CleanupStaleMultiplexedConnections implements ShouldQueue
 | |
| {
 | |
|     use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 | |
| 
 | |
|     public function handle()
 | |
|     {
 | |
|         $this->cleanupStaleConnections();
 | |
|         $this->cleanupNonExistentServerConnections();
 | |
|     }
 | |
| 
 | |
|     private function cleanupStaleConnections()
 | |
|     {
 | |
|         $muxFiles = Storage::disk('ssh-mux')->files();
 | |
| 
 | |
|         foreach ($muxFiles as $muxFile) {
 | |
|             $serverUuid = $this->extractServerUuidFromMuxFile($muxFile);
 | |
|             $server = Server::where('uuid', $serverUuid)->first();
 | |
| 
 | |
|             if (! $server) {
 | |
|                 $this->removeMultiplexFile($muxFile);
 | |
| 
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             $muxSocket = "/var/www/html/storage/app/ssh/mux/{$muxFile}";
 | |
|             $checkCommand = "ssh -O check -o ControlPath={$muxSocket} {$server->user}@{$server->ip} 2>/dev/null";
 | |
|             $checkProcess = Process::run($checkCommand);
 | |
| 
 | |
|             if ($checkProcess->exitCode() !== 0) {
 | |
|                 $this->removeMultiplexFile($muxFile);
 | |
|             } else {
 | |
|                 $muxContent = Storage::disk('ssh-mux')->get($muxFile);
 | |
|                 $establishedAt = Carbon::parse(substr($muxContent, 37));
 | |
|                 $expirationTime = $establishedAt->addSeconds(config('constants.ssh.mux_persist_time'));
 | |
| 
 | |
|                 if (Carbon::now()->isAfter($expirationTime)) {
 | |
|                     $this->removeMultiplexFile($muxFile);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private function cleanupNonExistentServerConnections()
 | |
|     {
 | |
|         $muxFiles = Storage::disk('ssh-mux')->files();
 | |
|         $existingServerUuids = Server::pluck('uuid')->toArray();
 | |
| 
 | |
|         foreach ($muxFiles as $muxFile) {
 | |
|             $serverUuid = $this->extractServerUuidFromMuxFile($muxFile);
 | |
|             if (! in_array($serverUuid, $existingServerUuids)) {
 | |
|                 $this->removeMultiplexFile($muxFile);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private function extractServerUuidFromMuxFile($muxFile)
 | |
|     {
 | |
|         return substr($muxFile, 4);
 | |
|     }
 | |
| 
 | |
|     private function removeMultiplexFile($muxFile)
 | |
|     {
 | |
|         $muxSocket = "/var/www/html/storage/app/ssh/mux/{$muxFile}";
 | |
|         $closeCommand = "ssh -O exit -o ControlPath={$muxSocket} localhost 2>/dev/null";
 | |
|         Process::run($closeCommand);
 | |
|         Storage::disk('ssh-mux')->delete($muxFile);
 | |
|     }
 | |
| }
 | 
