From 63bf125420240e124f86af2f64d6ea8a56b97d26 Mon Sep 17 00:00:00 2001 From: Agent Date: Thu, 11 Jun 2026 18:52:40 -0400 Subject: [PATCH] fix: allocate PTY for agent install to work with sudo requiretty The remote server has 'Defaults requiretty' in sudoers, which prevents sudo from running without a TTY. Modified SSHService::exec() to accept an optional parameter that allocates a pseudo-terminal, and extracts the exit status from output when PTY is used (since phpseclib doesn't return exit status in PTY mode). --- src/Services/AgentService.php | 4 ++-- src/Services/SSHService.php | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Services/AgentService.php b/src/Services/AgentService.php index 406ecaf..e092679 100644 --- a/src/Services/AgentService.php +++ b/src/Services/AgentService.php @@ -63,7 +63,7 @@ class AgentService return ['success' => false, 'error' => 'SSH connection failed']; } - $result = $ssh->exec($remoteCommand, 120); + $result = $ssh->exec($remoteCommand, 120, true); $ssh->disconnect(); $output = trim($result['output']); @@ -127,7 +127,7 @@ class AgentService return ['success' => false, 'error' => 'SSH connection failed']; } - $result = $ssh->exec($remoteCommand, 60); + $result = $ssh->exec($remoteCommand, 60, true); $ssh->disconnect(); $output = trim($result['output']); diff --git a/src/Services/SSHService.php b/src/Services/SSHService.php index 1702945..29d5f3c 100755 --- a/src/Services/SSHService.php +++ b/src/Services/SSHService.php @@ -73,7 +73,7 @@ class SSHService } } - public function exec(string $command, int $timeout = 0): array + public function exec(string $command, int $timeout = 0, bool $pty = false): array { if ($this->connection === null || !$this->connection->isConnected()) { throw new \RuntimeException('No active SSH connection'); @@ -83,10 +83,22 @@ class SSHService $this->connection->setTimeout($timeout); - $output = $this->connection->exec($command); + if ($pty) { + $command .= '; echo "___EXIT___:$?"'; + } + + $output = $this->connection->exec($command, null, $pty); $exitStatus = $this->connection->getExitStatus(); $stderr = $this->connection->getStdError() ?? ''; + if ($pty && ($exitStatus === false || $exitStatus === null)) { + if (preg_match('/___EXIT___:(\d+)/', $output, $m)) { + $exitStatus = (int) $m[1]; + $output = str_replace($m[0] . "\n", '', $output); + $output = str_replace($m[0], '', $output); + } + } + $this->logger->info("SSH command executed", [ 'command' => $command, 'exit_status' => $exitStatus,