Я хотел бы написать скрипт для выполнения процедуры резервного копирования для нескольких компьютеров в офисе.Как я могу написать таким образом, чтобы я мог контролировать путь выполнения, а также легко читать и изменять?Нужны ли ООП и SOLID?
Сценарий должен убедиться, что компьютер жив, если нет WoL, и оставить его в исходном состоянии после резервного копирования.
Кроме того, сценарий должен выполнитьпара базовых проверок работоспособности, таких как smartctl -H
, и после этого выполните команды rsync ...
и brtbk ...
для выполнения фактического резервного копирования.
Я бы хотел, чтобы скрипт генерировал одностраничный отчет, отправляемый на адрес электронной почтыс четким заголовком, указывающим, нужно ли мне исследовать, или я могу игнорировать электронную почту.
Я уже пытался написать это в vanilla JS с помощью async / await, но не удалось из-за сложной конфигурации JSON, которую я придумал.
var task = {
type: 'main',
config: {
host: '10.5.1.158',
mac: 'e0:d5:5e:ee:de:3d',
},
task: {
type: 'ensureAlive',
task: [
{
type: 'smartCheck',
dev: '/dev/sda'
},
{
type: 'smartCheck',
dev: '/dev/sdb'
},
{
type: 'failEarly',
task: [
{
type: 'rsync',
config: {
from: `root@{{config.ip}}:/home/VirtualBox\ VMs/a15:/backups/a15/vms/a15/`,
to: '/backups/a15/',
}
},
{
type: 'btrfsSnapshot',
config: {
dir: '/backups/a15/',
},
}
]
}
]
}
};
async function run(ctx, task) {
if (!task) {
return;
}
if (Array.isArray(task)) {
for (var i = 0; i < task.length; i++) {
await run(ctx, task[i]);
}
return;
}
var config = Object.assign({}, ctx.config || {}, task.config || {});
var f = ctx.getFunction(task.type);
try {
var result = await f(config);
task.output = result;
} catch (error) {
task.output = Output({ isOk: false, errorMessage: error.message, errorStack: error.stack })
}
var newCtx = Object.assign({}, ctx, { config });
await run(newCtx, task.task);
}
Повторяющаяся функция run
стала слишком сложной для понимания и изменения / добавления функций.
Я ожидал получить что-то столь же легко читаемое, как это, независимо от того,Это JSON или настоящий JavaScript.Псевдокод ниже:
async function a15(report) {
var wasAlive = wakeUp();
try {
await smartCheck();
} catch (error) {
report.addError(error);
}
try {
await smartCheck();
} catch (error) {
report.addError(error);
}
try {
await rsync();
await btrbk();
} catch (error) {
report.addError(error);
}
if (!wasAlive) {
shutDown();
}
}
Что я делаю не так?Это вообще возможно?
Для дополнительного пояснения я хотел бы приложить дополнительные макеты конфигурации, которые я пробовал.
Другая попытка конфигурации, которая оказалась слишком сложной для программирования.Поскольку эта конфигурация плоская, основная трудность связана с передачей переменной, указывающей, что хост активен (в wakeUp
), в конец конфигурации (в shutDown
).
var a15: TaskDescription[] = [
{
type: 'wakeUp',
config: {
host: '10.5.1.252',
mac: 'e0:d5:5e:ee:de:3d'.replace(/:/g, ''),
timeout: '5',
user: 'root',
privateKey: '/Users/epi/.ssh/id_rsa',
},
},
{
type: 'smartCheck',
config: {
dev: '/dev/sda',
},
},
{
type: 'smartCheck',
config: {
dev: '/dev/sdb',
},
},
{
type: 'command',
configTemplateFromConfig: true,
config: {
command: 'rsync -a --inplace --delete -e ssh root@{{host}}:/home/santelab/VirtualBox\ VMs/a15:/mnt/samsung_m3/a15/ /backups/a15/'
},
},
{
type: 'command',
config: {
command: 'btrbk -c /mnt/samsung_m3/a15.conf run'
},
},
{
type: 'shutDown',
runIf: 'wasAlive',
config: {
host: '10.5.1.252',
mac: 'e0:d5:5e:ee:de:3d'.replace(/:/g, ''),
timeout: '5',
user: 'root',
privateKey: '/Users/epi/.ssh/id_rsa',
},
},
];
export interface TaskDescription {
type: string;
config?: TaskConfig;
configTemplateFromConfig?: boolean;
ignoreError?: boolean;
runIf?: string;
}
export type TaskConfig = {
[key: string]: string,
}