如何使用高级报告功能编写可维护的JavaScript ala'Bash脚本?

问题描述 投票:1回答:1

我想编写一个脚本来为办公室中的多台计算机执行备份过程。我怎样才能以一种可以简单控制执行路径的方式编写,并且易于阅读和修改?我需要OOP和SOLID吗?

该脚本应确保计算机处于活动状态,如果不是,则备份后将其保留为初始状态。

此外,脚本应该执行一些基本的运行状况检查,例如smartctl -H,然后执行rsync ...brtbk ...命令来执行实际备份。

我希望脚本生成一个单页报告,发送到一个电子邮件地址,标题清晰,表明我应该调查,或者我可以忽略该电子邮件。

我已经尝试使用async / await在vanilla JS中编写这个,但由于我想出了一个复杂的配置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,
}
javascript linux oop system-administration
1个回答
0
投票

我想我成功了。

有两个关键概念需要:

  1. 永远不会抛出错误,总是返回包含错误和值的结果
  2. 使用发电机 - 产生魔力

这是TypeScript中写入的localhost的概念证明。我也可以使用JavaScript。

import { WakeUp, Config as WakeUpConfig, Result as WakeUpResult } from './WakeUp';
import { SmartCheck, Config as SmartCheckConfig } from './SmartCheck';
import { Command, Config as CommandConfig, Result as CommandResult } from './Command';
import * as I from './interfaces';

async function* localhost() {
    var wakeUpResult = (yield WakeUp({ host: 'localhost', mac: 'e0:d5:5e:ee:de:3d', timeout: 5, tries: 20 })) as WakeUpResult;
    if (wakeUpResult.error) { return; }

    var echoResult = (yield Command({ command: `echo test` })) as CommandResult;
    if (echoResult.error) { return; }

    if (!wakeUpResult.value) {
        yield Command({ command: 'echo shutdown' });
    }
}

(async function () {
    var iterator = localhost();

    var lastResult: IteratorResult<any> = { value: undefined, done: false };
    do {
        lastResult = await iterator.next(lastResult.value);
    } while (!lastResult.done);
})()

我认为核心localhost()易于阅读,并允许轻松修改。

© www.soinside.com 2019 - 2024. All rights reserved.