繁体   English   中英

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

[英]How to write maintainable JavaScript ala' Bash scripts with advanced reporting features?

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

该脚本应确保计算机处于活动状态,如果不是,请运行该计算机,并在备份后使其保持初始状态。

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

我希望脚本生成一页报告,该报告发送到带有清晰标题的电子邮件地址,指示我应该进行调查还是可以忽略该电子邮件。

我已经尝试使用async / await在普通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,
}

我想我做到了。

有两个关键概念是必需的:

  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()易于阅读,并且可以轻松修改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM