PBS, rclone S3, E-Mail-Report
Ich wollte meine Backups von einem Proxmox Backup Server via S3 zu einem externen Anbieter sichern. PBS wird hier genutzt, damit ich die Backups verschlüsseln kann, bevor ich sie hochlade; es würde auch direkt von Proxmox mit einem lokalen Datastore gehen, dann ist der Spaß aber nicht verschlüsselt.
Ebenfalls möchte ich bei Ende der Sicherung gerne eine E-Mail bekommen, in der die rclone-Logs sowie Usage des Datastores aufgelistet werden.
Ich weiß, dass die Sicherung von Proxmox ca. 30 Minuten dauert. Also starte ich per Crontab eine Stunde nach Sicherungsstart den rclone-Job.
Annahmen:
- Die Backups liegen in PBS im Verzeichnis /mnt/ssd
- /mnt/ssd ist /dev/sdb1
- mail ist soweit eingerichtet, dass Emails via mailx versendet werden können
- rclone ist eingerichtet, das Ziel heißt „wasabi“
Folgende Sachen installieren wir nun in dem PBS:
apt-get update
apt-get install -y nodejs mail rclone
mkdir /root/copy-logs/
Code-Sprache: JavaScript (javascript)
Falls nicht geschehen: mail und rclone durchkonfigurieren. Wenn wir direkt via mail-Command eine Mail senden können, und diese auch ankommt, ist alles chico.
Datei anlegen: /root/copy.sh
#!/bin/bash
rclone sync /mnt/ssd/ wasabi:/pbe-backup/ssd --use-json-log --log-file /root/copy-logs/latest.log -v
node /root/prepare-mail.js > /root/copy-logs/latest.html
mailx -a 'Content-Type: text/html' -s "rclone sync report" [email protected] < /root/copy-logs/latest.html
Code-Sprache: JavaScript (javascript)
Diese macht erst rclone, haut dann via node.js eine hübsche funktionierende E-Mail raus und schreibt die in eine HTML-Datei. Via mailx wird die dann per E-Mail an [email protected] gesendet.
Das node.js-Script, welches die Log-Datei nimmt und umwandelt sowie Infos zum Datastore-Usage ausliest: /root/prepare-mail.js
const fs = require('fs');
const exec = require('child_process').exec;
var html = `
<table>
<thead>
<tr>
<th>Level</th>
<th>At</th>
<th>Message</th>
</tr>
</thead>
<tbody>
`;
var data = fs.readFileSync("./copy-logs/latest.log") +"";
data = data.split('\n');
for(var i = 0; i < data.length; i++) {
try {
if(data[i].trim().length == 0) continue;
data[i] = JSON.parse(data[i]);
} catch(e) {
data[i] = null;
continue;
}
if(!data[i]) continue;
html += `
<tr>
<td>${data[i].level}</td>
<td>${data[i].time}</td>
<td>${data[i].msg.trim().replace(/\n/g, '<br />')}</td>
</tr>
`;
}
html += `
</tbody>
</table>
`;
exec('df -h', function(err, resp) {
resp = resp + "";
resp = resp.split('\n');
found = null;
for(var i = 0; i < resp.length; i++) {
resp[i] = resp[i].trim();
if(resp[i].substr(0, '/dev/sdb1'.length) != '/dev/sdb1') continue;
found = resp[i];
}
if(found != null) {
found = found.replace(/\s\s+/g, ' ').split(' ');
found = {
"Disk": found[0],
"Size": found[1],
"Used": found[2],
"Free": found[3],
"Percent": found[4],
"Mount": found[5]
};
html = "<strong>"+ found.Mount +"</strong>: "+ found.Percent +" used ("+ found.Used +" of "+ found.Size +")<br />\n"
+ "Free: "+ found.Free +"<br /><br />\n\n"
+ html;
} else {
html = "<strong>Failed to get hard disk info</strong><br /><br />\n\n"
+ html;
}
console.log(html);
});
Code-Sprache: JavaScript (javascript)
Sieht nicht hübsch aus, erfüllt aber seinen Job.
Das hinterlegen wir noch in crontab -e
10 15 * * * /root/copy.sh
Code-Sprache: JavaScript (javascript)
Und dann sind wir durch