Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

---

## [5.2.1] – branch: `fix/ansi-escape-in-ssh-output`

### Fixed

- **SSH-Verbindungstest – ANSI/OSC-Escape-Sequenzen:** Remote-Shells senden aus ihren Startup-Dateien (`.bashrc`/`.zshrc`) OSC-Sequenzen (z. B. `\e]11;#RRGGBB\a` zur Hintergrundfarbe) auch bei nicht-interaktiven SSH-Befehlen. Diese landeten bisher ungefiltert im `output`-Feld des SSH-Tests, ließen den Success-Check (`trim($output) === 'ok'`) fehlschlagen und zeigten dem Nutzer fälschlicherweise „Fehlgeschlagen" an — obwohl die Verbindung funktionierte. Neue Hilfsklasse `AnsiStripper` (CSI-, OSC- und Fe-Sequenzen) wird in `SshTestEndpoint` auf die SSH-Ausgabe angewendet.
- **Job-Output – ANSI/OSC-Escape-Sequenzen:** Dieselben Sequenzen wurden via `cron-wrapper.sh` in `execution_log.output` gespeichert und in der UI als Zeichenmüll angezeigt. `ExecutionFinishEndpoint` wendet `AnsiStripper::strip()` beim Einlesen des Outputs an, bevor er in der DB gespeichert wird.
- **Output-Anzeige – Zeilenumbrüche:** Span-Elemente in `dashboard.php`, `detail.php` und `timeline.php` verwendeten `break-all` ohne `whitespace-pre-wrap`; HTML kollabiert `\n` in Inline-Elementen zu Leerzeichen. Ersetzt durch `whitespace-pre-wrap break-words`. Die fehlenden CSS-Regeln wurden in `assets/css/tailwind.css` ergänzt (vorgebauites, gepurgtes Stylesheet enthielt `whitespace-pre-wrap` und `break-words` nicht).

---

## [5.2.0] – branch: `feature/minor-improvements`

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion agent/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.2.0
5.2.1
3 changes: 2 additions & 1 deletion agent/src/Endpoints/ExecutionFinishEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

use Cronmanager\Agent\Cron\CrontabManager;
use Cronmanager\Agent\Notification\MailNotifier;
use Cronmanager\Agent\Util\AnsiStripper;
use Cronmanager\Agent\Util\ExitCodeMatcher;
use Cronmanager\Agent\Notification\TelegramNotifier;
use Monolog\Logger;
Expand Down Expand Up @@ -146,7 +147,7 @@ public function handle(array $params): void
$executionId = (int) $body['execution_id'];
$jobId = (int) $body['job_id'];
$exitCode = (int) $body['exit_code'];
$output = isset($body['output']) ? (string) $body['output'] : '';
$output = AnsiStripper::strip(isset($body['output']) ? (string) $body['output'] : '');
$target = isset($body['target']) && is_string($body['target']) && $body['target'] !== ''
? $body['target']
: null;
Expand Down
3 changes: 2 additions & 1 deletion agent/src/Endpoints/SshTestEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
namespace Cronmanager\Agent\Endpoints;

use Cronmanager\Agent\Ssh\SshConfigParser;
use Cronmanager\Agent\Util\AnsiStripper;
use Monolog\Logger;

/**
Expand Down Expand Up @@ -124,7 +125,7 @@ public function handle(array $params): void
$exitCode = 0;
exec($command, $output, $exitCode);

$outputText = implode("\n", $output);
$outputText = AnsiStripper::strip(implode("\n", $output));
$success = ($exitCode === 0 && trim($outputText) === 'ok');

$this->logger->info('SshTestEndpoint: SSH probe completed', [
Expand Down
49 changes: 49 additions & 0 deletions agent/src/Util/AnsiStripper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

/**
* Cronmanager Host Agent – AnsiStripper
*
* @author Christian Schulz <technik@meinetechnikwelt.rocks>
* @license GNU General Public License version 3 or later
*/

namespace Cronmanager\Agent\Util;

/**
* Strips ANSI and OSC terminal escape sequences from a string.
*
* Remote shells often emit escape sequences from their startup files
* (.bashrc/.zshrc) even during non-interactive SSH commands. These
* sequences must be removed before storing or comparing command output.
*
* Handled sequence types:
* - CSI ESC [ … final-byte (colour, cursor, erase, …)
* - OSC ESC ] … BEL|ST (title, background colour, shell integration, …)
* - Fe ESC @-_ (single-character escape sequences)
*/
final class AnsiStripper
{
/**
* Regular expression that matches all three sequence families above.
*
* Groups:
* 1. CSI: ESC [ <parameter bytes> <intermediate bytes> <final byte>
* 2. OSC: ESC ] <any chars except BEL/ESC> (BEL | ESC \)
* 3. Fe: ESC followed by a single byte in 0x40–0x5F
*/
private const PATTERN = '/\x1b(?:\[[0-?]*[ -\/]*[@-~]|\][^\x07\x1b]*(?:\x07|\x1b\\\\)|[@-_])/';

/**
* Remove all ANSI/OSC escape sequences from the given string.
*
* @param string $text Raw text that may contain escape sequences.
*
* @return string Cleaned text with all escape sequences removed.
*/
public static function strip(string $text): string
{
return (string) preg_replace(self::PATTERN, '', $text);
}
}
2 changes: 1 addition & 1 deletion web/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.2.0
5.2.1
1 change: 1 addition & 0 deletions web/assets/css/tailwind.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions web/templates/cron/detail.php
Original file line number Diff line number Diff line change
Expand Up @@ -565,12 +565,12 @@ class="hidden flex items-start gap-2 rounded-lg border border-red-200 bg-red-50
<span id="<?= htmlspecialchars($outputId . '-data', ENT_QUOTES, 'UTF-8') ?>"
class="hidden"><?= htmlspecialchars($output, ENT_QUOTES, 'UTF-8') ?></span>
<span id="<?= htmlspecialchars($outputId . '-short', ENT_QUOTES, 'UTF-8') ?>"
class="font-mono text-xs break-all">
class="font-mono text-xs whitespace-pre-wrap break-words">
<?= htmlspecialchars($outputTrunc, ENT_QUOTES, 'UTF-8') ?>
</span>
<?php if (mb_strlen($output) > 200): ?>
<span id="<?= htmlspecialchars($outputId . '-full', ENT_QUOTES, 'UTF-8') ?>"
class="font-mono text-xs break-all hidden">
class="font-mono text-xs whitespace-pre-wrap break-words hidden">
<?= htmlspecialchars($output, ENT_QUOTES, 'UTF-8') ?>
</span>
<button type="button"
Expand Down
4 changes: 2 additions & 2 deletions web/templates/timeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -436,12 +436,12 @@ class="text-blue-600 hover:underline font-medium">
<span id="tl-output-<?= $idx ?>-data"
class="hidden"><?= htmlspecialchars($output, ENT_QUOTES, 'UTF-8') ?></span>
<span id="tl-output-<?= $idx ?>-short"
class="font-mono text-xs break-all">
class="font-mono text-xs whitespace-pre-wrap break-words">
<?= htmlspecialchars($outputTrunc, ENT_QUOTES, 'UTF-8') ?>
</span>
<?php if ($isTruncated): ?>
<span id="tl-output-<?= $idx ?>-full"
class="font-mono text-xs break-all hidden">
class="font-mono text-xs whitespace-pre-wrap break-words hidden">
<?= htmlspecialchars($output, ENT_QUOTES, 'UTF-8') ?>
</span>
<button type="button"
Expand Down
Loading