Synology Création d'un script pour automatiser USBCopy

Fonzie73

Nouveau membre
29 Août 2024
27
3
8
Bonjour à tous
J'utilise USBCopy pour faire une sauvegarde sur un disque externe
J'ai créé plusieurs taches, tout fonctionne
Je voulais créer un script afin de lancer ces taches les unes à la suite des autres
Comme mon niveau en script est nul, j'ai demandé à Gemini :)
Voila ce qu'il m'a proposé:
JavaScript:
#!/bin/bash

# --- CONFIGURATION ---
# Entrez ici les noms exacts de vos tâches USB Copy, dans l'ordre d'exécution
TACHES=("Sauve Domotique" "Sauve Photos" "Sauve Mag")
# ---------------------

for TACHE in "${TACHES[@]}"; do
    echo "--------------------------------------------------"
    echo "Lancement de la tâche USB Copy : $TACHE"
    echo "--------------------------------------------------"
   
    # Commande API pour lancer la tâche
    /usr/syno/bin/synowebapi --exec api=SYNO.USBCopy.Task method=start version=1 task_name="$TACHE"
   
    # Pause de 10 secondes pour laisser le processus démarrer
    sleep 10
   
    # Boucle de vérification du statut
    while true; do
        # On récupère le statut de la tâche via l'API
        STATUT=$(/usr/syno/bin/synowebapi --exec api=SYNO.USBCopy.Task method=get version=1 task_name="$TACHE" 2>/dev/null)
       
        # Si le statut contient "status=0" (ou "idle"), c'est que la tâche ne tourne plus
        # Si elle tourne, l'API renvoie généralement un statut de progression (ex: "copying" ou un code de statut)
        if echo "$STATUT" | grep -q '"status":0'; then
            echo "La tâche $TACHE est terminée avec succès (ou est au repos)."
            break
        elif echo "$STATUT" | grep -q '"status":1'; then
            # "status":1 correspond généralement à "en cours" (copying / indexing)
            echo "Statut : Copie en cours pour $TACHE... (vérification dans 20s)"
            sleep 20
        else
            # Sécurité si le format de réponse change : on attend un peu
            sleep 20
        fi
    done
done

echo "=================================================="
echo "Toutes les tâches de sauvegarde sont terminées !"
echo "=================================================="
exit 0

j'ai créé le script avec l'éditeur de fichier Synology sinon j'ai des erreurs avec les caractères invisibles \r\n
Je lance le script en tant que root
Mais rien ne se passe. Je ne reçois même pas le mail avec les erreurs comme si la tache était bloquée
Si vous avez des idées... Merci
script.png
 
Dernière édition par un modérateur:
Bonjour. Désolé. Oui avec plaisir sauf que je ne trouve pas comment l'éditer
ha oui, tu es assez nouveau du coup tu ne dois pas avoir encore le droit d’éditer tes messages.
Donne dans le prochain message ton code avec la balise appropriée et je copie/collerais dans ton premier message 😇
 
JavaScript:
#!/bin/bash

# --- CONFIGURATION ---
# Entrez ici les noms exacts de vos tâches USB Copy, dans l'ordre d'exécution
TACHES=("Sauve Domotique" "Sauve Photos" "Sauve Mag")
# ---------------------

for TACHE in "${TACHES[@]}"; do
    echo "--------------------------------------------------"
    echo "Lancement de la tâche USB Copy : $TACHE"
    echo "--------------------------------------------------"
    
    # Commande API pour lancer la tâche
    /usr/syno/bin/synowebapi --exec api=SYNO.USBCopy.Task method=start version=1 task_name="$TACHE"
    
    # Pause de 10 secondes pour laisser le processus démarrer
    sleep 10
    
    # Boucle de vérification du statut
    while true; do
        # On récupère le statut de la tâche via l'API
        STATUT=$(/usr/syno/bin/synowebapi --exec api=SYNO.USBCopy.Task method=get version=1 task_name="$TACHE" 2>/dev/null)
        
        # Si le statut contient "status=0" (ou "idle"), c'est que la tâche ne tourne plus
        # Si elle tourne, l'API renvoie généralement un statut de progression (ex: "copying" ou un code de statut)
        if echo "$STATUT" | grep -q '"status":0'; then
            echo "La tâche $TACHE est terminée avec succès (ou est au repos)."
            break
        elif echo "$STATUT" | grep -q '"status":1'; then
            # "status":1 correspond généralement à "en cours" (copying / indexing)
            echo "Statut : Copie en cours pour $TACHE... (vérification dans 20s)"
            sleep 20
        else
            # Sécurité si le format de réponse change : on attend un peu
            sleep 20
        fi
    done
done

echo "=================================================="
echo "Toutes les tâches de sauvegarde sont terminées !"
echo "=================================================="
exit 0
 
Gemini ne connais pas l'API concernée à priori, il a supposé.
si tu lances cette commande en SSH: grep -Ri "USBCopy" /usr/syno/synoman/webapi
tu verras que l'API déclarée est "SYNO.USBCopy" et pas "SYNO.USBCopy.Task"
1- si tu creuses un peu plus, "status" n'est pas 0 ou 1 mais "successful" dans le json de retour
2- ceci avec id=1 va lancer la tache 1: /usr/syno/bin/synowebapi --exec api=SYNO.USBCopy method=run version=1 id=1
3- pour connaitre l'id attribué au nom de la tache tu fais avant: /usr/syno/bin/synowebapi --exec api=SYNO.USBCopy method=list version=1
ce qui te donne ce json (exemple pour expliquer):

JSON:
{
   "data" : {
      "tasks" : [
         {
            "conflict_policy" : "rename",
            "copy_file_path" : "",
            "copy_strategy" : "versioning",
            "default_device_port" : "NA",
            "destination_path" : "/usbshare2/test",
            "eject_when_task_done" : false,
            "enable_rotation" : true,
            "error_code" : 0,
            "id" : 1,
            "is_default_task" : false,
            "is_ds_mounted" : true,
            "is_task_runnable" : true,
            "is_usb_mounted" : true,
            "latest_finish_time" : 1781175524,
            "max_version_count" : 5,
            "name" : "test",
            "next_run_time" : "N/A",
            "not_keep_dir_structure" : false,
            "remove_src_file" : false,
            "rename_photo_video" : false,
            "rotation_policy" : "smart_recycle",
            "run_when_plug_in" : false,
            "schedule_id" : 13,
            "smart_create_date_dir" : false,
            "source_path" : "/script_ext",
            "status" : "successful",
            "type" : "export_general"
         }
      ]
   },
   "httpd_restart" : false,
   "success" : true
}

dans l'exemple:
id= 1
tache name= 'test'
chemin de sauvegarde = "/usbshare2/test"
et toutes les options que tu as indiqué dans ta tache de sauvegarde, ici dans l'exemple, strategy versionning, 5 version max, ejecter le lecteur false, etc.

Pour les API, SH n'est pas le langage adapté. C'est beaucoup plus simple en PHP (que j'utilise), PHP gère très simplement les json.
en reprenant la logique de ton script SH, j'ai fait ce PHP.
Je n'ai pas fait de tests complets, je n'ai pas les mêmes dossiers, mais cette version PHP devrait fonctionner.
Sur un exemple simple, ca fonctionne, sur 3 sauvegardes de suite probablement.


PHP:
<?php

$tasksToRun = ['Sauve Domotique','Sauve Photos','Sauve Mag']; // ajoute tes 3 tâches et plus si besoin ici
$logFile = '/volume1/homes/Fred/Scripts/Sauvegarde_USB.log';

/* =========================
   1. Récupération des taches
========================= */
$list = json_decode(shell_exec('/usr/syno/bin/synowebapi --exec api=SYNO.USBCopy method=list version=1'), true);

if (!isset($list['data']['tasks'])) {
    logMsg('ERREUR: impossible de récupérer la liste USB Copy', $logFile);
    exit;
}

$tasks = $list['data']['tasks'];

/* =========================
   2. Boucle sur les tâches
========================= */
foreach ($tasksToRun as $taskName) {
    $taskId = null;
    foreach ($tasks as $t) {
        if ($t['name'] === $taskName) {
            $taskId = $t['id'];
            break;
        }
    }

    if ($taskId === null) {
        logMsg('Tâche introuvable: '.$taskName, $logFile);
        continue;
    }

    logMsg('Démarrage tâche: '.$taskName.' (ID='.$taskId.')', $logFile);

    /* =========================
       3. Lancement tâche
    ========================= */
    $run = json_decode(shell_exec('/usr/syno/bin/synowebapi --exec api=SYNO.USBCopy method=run version=1 id='.$taskId), true);

    if (!isset($run['success']) || $run['success'] !== true) {
        logMsg('Erreur lancement tâche '.$taskName, $logFile);
        continue;
    }

    /* =========================
       4. Monitoring
    ========================= */
    $done = false;
    while (true) {

        sleep(5);

        $list = json_decode(shell_exec('/usr/syno/bin/synowebapi --exec api=SYNO.USBCopy method=list version=1'), true);

        if (!isset($list['data']['tasks'])) {
            logMsg('Erreur lecture status', $logFile);
            continue;
        }

        foreach ($list['data']['tasks'] as $t) {
            if ($t['id'] != $taskId) {
                continue;
            }

            $status = $t['status'] ?? 'unknown';
            logMsg('['.$taskName.'] status = '.$status, $logFile);

            /* =========================
               5. États terminaux
            ========================= */
            if ($status === 'successful') {
                logMsg('['.$taskName.'] TERMINÉ OK', $logFile);
                $done = true;
            }
            elseif (in_array($status, ['error', 'failed'])) {
                logMsg('['.$taskName.'] TERMINÉ EN ERREUR ('.$status.')', $logFile);
                $done = true;
            }
            break;
        }
        if ($done) break;
    }
}

logMsg('Toutes les tâches terminées', $logFile);

function logMsg($msg, $logFile) {
    $line = '['.date('Y-m-d H:i:s').'] '.$msg.PHP_EOL;
    echo $line;
}

?>

Tu lances via une taches planifées définie comme ceci:
php /volume1/homes/Fred/Scripts/usbcopy.php >> /volume1/homes/Fred/Scripts/usbcopy.log

usbcopy.log est un fichier texte qui va logger les étapes et des erreurs si il y en a.
vérifie les chemins, j'ai repris tes chemins, sauf erreur

si tout se passe bien, ton log ressemblera à ça:

[2026-06-11 14:28:01] Tâche trouvée: Sauve Domotique (ID=1)
[2026-06-11 14:28:01] Tâche démarrée
[2026-06-11 14:28:06] status = copying
[2026-06-11 14:28:11] status = successful
[2026-06-11 14:28:01] Tâche trouvée: Sauve Photos (ID=2)
[2026-06-11 14:28:01] Tâche démarrée
[2026-06-11 14:28:06] status = copying
[2026-06-11 14:28:11] status = successful
[2026-06-11 14:28:01] Tâche trouvée: Sauve Mag (ID=3)
[2026-06-11 14:28:01] Tâche démarrée
[2026-06-11 14:28:06] status = copying
[2026-06-11 14:28:11] status = successful
[2026-06-11 14:28:11] FIN OK
 
Deja de retour. Je ne sais pas quoi dire si ce n'est que tu es trop fort !!!!!

Voila les logs:
[2026-06-11 16:22:43] Démarrage tâche: Sauve Domotique (ID=8)
[2026-06-11 16:22:48] [Sauve Domotique] status = copying
[2026-06-11 16:22:53] [Sauve Domotique] status = successful
[2026-06-11 16:22:53] [Sauve Domotique] TERMINÉ OK
[2026-06-11 16:22:53] Démarrage tâche: Sauve Photos (ID=9)
[2026-06-11 16:23:01] [Sauve Photos] status = successful
[2026-06-11 16:23:01] [Sauve Photos] TERMINÉ OK
[2026-06-11 16:23:01] Démarrage tâche: Sauve Mag (ID=7)
[2026-06-11 16:23:06] [Sauve Mag] status = copying
[2026-06-11 16:23:11] [Sauve Mag] status = copying
[2026-06-11 16:23:16] [Sauve Mag] status = copying
[2026-06-11 16:23:21] [Sauve Mag] status = copying
[2026-06-11 16:23:26] [Sauve Mag] status = copying
[2026-06-11 16:23:31] [Sauve Mag] status = copying
[2026-06-11 16:23:36] [Sauve Mag] status = copying
[2026-06-11 16:23:41] [Sauve Mag] status = copying
[2026-06-11 16:23:46] [Sauve Mag] status = copying
[2026-06-11 16:23:51] [Sauve Mag] status = copying
[2026-06-11 16:23:56] [Sauve Mag] status = copying
[2026-06-11 16:24:01] [Sauve Mag] status = copying
[2026-06-11 16:24:06] [Sauve Mag] status = copying
[2026-06-11 16:24:11] [Sauve Mag] status = copying
[2026-06-11 16:24:16] [Sauve Mag] status = copying
[2026-06-11 16:24:21] [Sauve Mag] status = copying
[2026-06-11 16:24:27] [Sauve Mag] status = copying
[2026-06-11 16:24:32] [Sauve Mag] status = copying
[2026-06-11 16:24:37] [Sauve Mag] status = copying
[2026-06-11 16:24:42] [Sauve Mag] status = copying
[2026-06-11 16:24:47] [Sauve Mag] status = copying
[2026-06-11 16:24:52] [Sauve Mag] status = copying
[2026-06-11 16:24:57] [Sauve Mag] status = copying
[2026-06-11 16:25:02] [Sauve Mag] status = copying
[2026-06-11 16:25:07] [Sauve Mag] status = copying
[2026-06-11 16:25:12] [Sauve Mag] status = copying
[2026-06-11 16:25:17] [Sauve Mag] status = successful
[2026-06-11 16:25:17] [Sauve Mag] TERMINÉ OK
[2026-06-11 16:25:17] Toutes les tâches terminées

Y'a moyen d'avoir une seule ligne par tache ? (c'est un détail, je suis trop content!)
 
c'est à dire que trois lignes du coup ?
si ça fonctionne, tu entends le bip du syno, sauf si tu as retiré le bip.
Le mieux je pense c'est aucun log et le jour ou ça fonctionne pas tu les réactives pour tester?
Si la solution te convient tu fis cette modification:
avant:
PHP:
function logMsg($msg, $logFile) {
    $line = '['.date('Y-m-d H:i:s').'] '.$msg.PHP_EOL;
    echo $line;
}

après:
Code:
function logMsg($msg, $logFile) {
    $line = '['.date('Y-m-d H:i:s').'] '.$msg.PHP_EOL;
    // echo $line; // décommenter la ligne pour avoir les logs dans Sauvegarde_USB.log
}

Tu peux supprimer le fichier Sauvegarde_USB.log, il sera écrit quand tu valideras les log
 
Dernière édition:
ce dont je ne suis pas sûr, cette ligne:
elseif (in_array($status, ['error', 'failed'])) {
je ne connais pas les messages d'erreurs du json sans tomber sur une erreur. Ce n'est pas documenté par Synology. Je suppose qu'on y trouve 'error' ou 'failed'.
Tu avais aussi l'option 'basique' d'utiliser les 3 taches qui ont été créées automatiqueent par USB Copy dans ton planificateur de taches, et de modifier les calendriers des taches respectives.
USB Copy 'est fait pour celui qui veut pas s'embeter, tout est 'clé en main', y compris l'option 'je connecte le lecteur USB et les sauvegardes démarrent'.
Mais c'est moins fun ;)