From 8a6f398af563b3ef29c09fe4755fdc57d8f43b1a Mon Sep 17 00:00:00 2001 From: sorcier Date: Mon, 2 Nov 2026 14:03:52 +0100 Subject: [PATCH] Fix: install ffmpeg, rsync, sox and add fallback copy in BackupManager for sound extraction --- install.sh | 5 +++- scripts/fix.sh | 4 +-- src/BackupManager.php | 57 +++++++++++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/install.sh b/install.sh index fe39281..5aae516 100755 --- a/install.sh +++ b/install.sh @@ -58,7 +58,10 @@ apt-get install -y --no-install-recommends \ ca-certificates \ iptables \ iptables-persistent \ - acl + acl \ + ffmpeg \ + rsync \ + sox # Vérification et installation d'Asterisk echo -e "${C_GREEN} -> Installation du moteur Asterisk PBX...${C_RESET}" diff --git a/scripts/fix.sh b/scripts/fix.sh index 9997852..63a8531 100755 --- a/scripts/fix.sh +++ b/scripts/fix.sh @@ -16,8 +16,8 @@ cd /var/www/nexus-pbx git fetch origin main git reset --hard origin/main -echo "-> Installation des outils de droits (ACL)..." -which setfacl >/dev/null 2>&1 || (apt-get update -y && apt-get install -y acl) +echo "-> Installation des dépendances système indispensables (ACL, ffmpeg, rsync, sox)..." +which ffmpeg >/dev/null 2>&1 && which rsync >/dev/null 2>&1 && which setfacl >/dev/null 2>&1 || (apt-get update -y && apt-get install -y --no-install-recommends acl ffmpeg rsync sox) echo "-> Création des dossiers et des fichiers de journalisation..." mkdir -p /etc/fail2ban/filter.d /etc/asterisk /var/log/asterisk /var/log/nexus-pbx /var/www/nexus-pbx/storage/backups diff --git a/src/BackupManager.php b/src/BackupManager.php index 86efad4..e90b808 100644 --- a/src/BackupManager.php +++ b/src/BackupManager.php @@ -211,7 +211,7 @@ class BackupManager if (is_dir($storageSounds)) { $destSounds = $stageDir . '/storage_sounds'; mkdir($destSounds, 0755, true); - exec("rsync -a " . escapeshellarg($storageSounds . '/') . " " . escapeshellarg($destSounds . '/')); + self::copyDirectoryRecursive($storageSounds, $destSounds); $manifestFiles['storage_sounds'] = ['count' => count(glob($destSounds . '/*'))]; } @@ -220,7 +220,7 @@ class BackupManager if (is_dir($astSoundsCustom)) { $destAstSounds = $stageDir . '/asterisk_sounds_custom'; mkdir($destAstSounds, 0755, true); - exec("rsync -a " . escapeshellarg($astSoundsCustom . '/') . " " . escapeshellarg($destAstSounds . '/')); + self::copyDirectoryRecursive($astSoundsCustom, $destAstSounds); $manifestFiles['asterisk_sounds_custom'] = ['count' => count(glob($destAstSounds . '/*'))]; } @@ -229,7 +229,7 @@ class BackupManager if (is_dir($voicemailSpool)) { $destVm = $stageDir . '/voicemail_default'; mkdir($destVm, 0755, true); - exec("rsync -a " . escapeshellarg($voicemailSpool . '/') . " " . escapeshellarg($destVm . '/')); + self::copyDirectoryRecursive($voicemailSpool, $destVm); $manifestFiles['voicemail_default'] = ['count' => count(glob($destVm . '/*'))]; } @@ -238,14 +238,14 @@ class BackupManager if (is_dir($storageCerts)) { $destCerts = $stageDir . '/storage_certs'; mkdir($destCerts, 0700, true); - exec("rsync -a " . escapeshellarg($storageCerts . '/') . " " . escapeshellarg($destCerts . '/')); + self::copyDirectoryRecursive($storageCerts, $destCerts); $manifestFiles['storage_certs'] = ['count' => count(glob($destCerts . '/*'))]; } $astKeys = '/etc/asterisk/keys'; if (is_dir($astKeys)) { $destAstKeys = $stageDir . '/asterisk_keys'; mkdir($destAstKeys, 0700, true); - exec("rsync -a " . escapeshellarg($astKeys . '/') . " " . escapeshellarg($destAstKeys . '/')); + self::copyDirectoryRecursive($astKeys, $destAstKeys); $manifestFiles['asterisk_keys'] = ['count' => count(glob($destAstKeys . '/*'))]; } @@ -529,8 +529,7 @@ class BackupManager // 6. Restauration des fichiers sons (NexusPBX & Asterisk) if (is_dir($stageDir . '/storage_sounds')) { $destSounds = '/var/www/nexus-pbx/storage/sounds'; - @mkdir($destSounds, 0775, true); - exec("rsync -a --delete " . escapeshellarg($stageDir . '/storage_sounds/') . " " . escapeshellarg($destSounds . '/')); + self::copyDirectoryRecursive($stageDir . '/storage_sounds', $destSounds, true); @chown($destSounds, 'www-data'); @chgrp($destSounds, 'asterisk'); exec("chown -R www-data:asterisk " . escapeshellarg($destSounds)); @@ -539,8 +538,7 @@ class BackupManager if (is_dir($stageDir . '/asterisk_sounds_custom')) { $destAstSounds = '/var/lib/asterisk/sounds/custom'; - @mkdir($destAstSounds, 0775, true); - exec("rsync -a " . escapeshellarg($stageDir . '/asterisk_sounds_custom/') . " " . escapeshellarg($destAstSounds . '/')); + self::copyDirectoryRecursive($stageDir . '/asterisk_sounds_custom', $destAstSounds); exec("chown -R asterisk:asterisk " . escapeshellarg($destAstSounds)); exec("chmod -R 775 " . escapeshellarg($destAstSounds)); } @@ -548,8 +546,7 @@ class BackupManager // 7. Restauration de la boîte vocale (Voicemail Spool & Greetings) if (is_dir($stageDir . '/voicemail_default')) { $destVm = '/var/spool/asterisk/voicemail/default'; - @mkdir($destVm, 0775, true); - exec("rsync -a " . escapeshellarg($stageDir . '/voicemail_default/') . " " . escapeshellarg($destVm . '/')); + self::copyDirectoryRecursive($stageDir . '/voicemail_default', $destVm); exec("chown -R asterisk:asterisk /var/spool/asterisk/voicemail"); exec("chmod -R g+rwX /var/spool/asterisk/voicemail"); } @@ -557,14 +554,12 @@ class BackupManager // 8. Restauration des certificats TLS if (is_dir($stageDir . '/storage_certs')) { $destCerts = '/var/www/nexus-pbx/storage/certs'; - @mkdir($destCerts, 0750, true); - exec("rsync -a " . escapeshellarg($stageDir . '/storage_certs/') . " " . escapeshellarg($destCerts . '/')); + self::copyDirectoryRecursive($stageDir . '/storage_certs', $destCerts); exec("chown -R www-data:asterisk " . escapeshellarg($destCerts)); } if (is_dir($stageDir . '/asterisk_keys')) { $destKeys = '/etc/asterisk/keys'; - @mkdir($destKeys, 0750, true); - exec("rsync -a " . escapeshellarg($stageDir . '/asterisk_keys/') . " " . escapeshellarg($destKeys . '/')); + self::copyDirectoryRecursive($stageDir . '/asterisk_keys', $destKeys); exec("chown -R asterisk:asterisk " . escapeshellarg($destKeys)); } @@ -854,6 +849,38 @@ class BackupManager return $bytes . ' B'; } + private static function copyDirectoryRecursive(string $src, string $dest, bool $delete = false): void + { + if (!is_dir($src)) { + return; + } + @mkdir($dest, 0775, true); + + // Si rsync est présent, l'utiliser en priorité + static $hasRsync = null; + if ($hasRsync === null) { + $hasRsync = !empty(shell_exec('which rsync 2>/dev/null')); + } + + if ($hasRsync) { + $delFlag = $delete ? '--delete ' : ''; + exec("rsync -a {$delFlag}" . escapeshellarg($src . '/') . " " . escapeshellarg($dest . '/')); + return; + } + + // Sinon fallback cp -a natif Linux + if ($delete) { + foreach (glob($dest . '/*') as $f) { + if (is_dir($f)) { + self::removeDirRecursive($f); + } else { + @unlink($f); + } + } + } + exec("cp -a " . escapeshellarg($src . '/.') . " " . escapeshellarg($dest . '/')); + } + private static function removeDirRecursive(string $dir): void { if (!is_dir($dir)) {