日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

node.js require 自动执行脚本 并生成html,nodejs 执行脚本并实时输出

發布時間:2023/12/4 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 node.js require 自动执行脚本 并生成html,nodejs 执行脚本并实时输出 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

接到需求

需要一個服務來執行shell腳本,要求可以實時打印shell腳本執行的過程,并看到腳本執行的結果。

明確任務目標:

這是一個web服務,需要執行shell腳本

當一個腳本執行的時候,再次發送請求需要等待當前腳本執行完畢,再自動執行這次請求

使用長連接而不是socket

添加腳本不需要重啟服務器

這里采用的是express框架

開始

首先搭好express基本框架

新建app.js文件, npm install express

const express = require('express');

const app = express();

app.get('/:id', (req, res) => {

const { id } = req.params;

if (id === 'favicon.ico') {

res.sendStatus(200);

return;

}

// 執行腳本

});

app.set('port', 3018);

app.listen(app.get('port'), () => console.log(`server listening at ${app.get('port')}`));

新建文件

新建config.json用于配置id和腳本名的對應關系,新建scripts目錄用于存放腳本。

這里定義一個函數execute參數為id和response對象,代碼如下:

const pidDict = {};

async function execute(id, res) {

delete require.cache[require.resolve('./config.json')];

const config = require('./config.json');

const filePath = config[id];

if (!filePath) {

res.sendStatus(404);

return;

}

console.log(`The script:${filePath} with ${id} begin execute`);

const readable = new Readable();

readable._read = () => {};

readable.pipe(res);

while (pidDict[id]) {

readable.push('\nWaiting for another script request.');

await wait(5000);

}

const handle = spawn('sh', [`./scripts/${filePath}`]);

pidDict[id] = handle.pid;

handle.stdout.on('data', (data) => {

readable.push(`\n${data}`);

getLogger(filePath).log(`\n${data}`);

});

handle.stderr.on('data', (data) => {

getLogger(filePath).warn(`\n${data}`);

readable.push(`\n${data}`);

});

handle.on('error', (code) => {

getLogger(filePath).error(`child process error with information: \n${code}`);

readable.push(`child process error with information: \n${code}`);

delete pidDict[id];

readable.push(null);

});

handle.on('close', (code) => {

getLogger(filePath).log(`child process close with code ${code}`);

delete pidDict[id];

readable.push(null);

});

}

解釋:

首先要加載config.json,需要注意的是,因為是需要動態引入,所以這里不能直接使用require('config.json'),在這之前,需要先刪除引入的緩存:delete require.cache[require.resolve('./config.json')];

獲取文件路徑 const filePath = config[id];

新建讀寫流,可以直接發送到前端。

再執行腳本前,需要判斷當前有無腳本執行,這里在外部定義了一個pidDict,文件對應的id直接指向文件執行的handle的pid

緊接著就是輸入輸出流了

handle.stdout是標準輸出

handle.stderr是錯誤輸出,這里指的是輸出的警告

handle的error事件指的是腳本執行中遇到的錯誤,也就是腳本執行不成功報的錯誤信息

這里定義了兩個外部函數,一個是自定義的日志打印,另一個是遇到有腳本執行時的等待

新建utility.js const fs = require('fs');

/**

* time wait

*

* @param time {number} time(ms) to wait

*/

/* eslint-disable compat/compat */

const wait = async (time = 1000) => {

return new Promise((resolve) => {

setTimeout(resolve, time);

});

};

/**

* set log

*

* getLogger(path).level

* level:

* log

* trace

* debug

* info

* warn

* error

* @param path

*/

function getLogger(path) {

return require('tracer').console({

transport: (data) => {

console.log(data.output);

fs.appendFile(`./logs/${path}.log`, `${data.rawoutput} \n`, () => {});

},

});

}

module.exports = {

wait,

getLogger,

};

新建腳本

現在,新建scripts/hello-world.sh

#!/bin/sh

echo 'hello...'

sleep 5

echo 'world!'

config.json中注冊該腳本

{

"hello-world": "hello-world.sh"

}

執行node app.js,通過curl http://localhost:3018/hello-world即可觀察到運行結果。

這里放上app.js的完整代碼

const express = require('express');

const { spawn } = require('child_process');

const { Readable } = require('stream');

const { wait, getLogger } = require('./utility');

const app = express();

app.get('/:id', (req, res) => {

// 執行腳本

const { id } = req.params;

if (id === 'favicon.ico') {

res.sendStatus(200);

return;

}

execute(id, res).then();

});

const pidDict = {};

/**

* 執行sh腳本

*

* @param id 腳本id

* @param res response object

*/

/* eslint-disable no-underscore-dangle, no-await-in-loop */

async function execute(id, res) {

delete require.cache[require.resolve('./config.json')];

const config = require('./config.json');

const filePath = config[id];

if (!filePath) {

res.sendStatus(404);

return;

}

console.log(`The script:${filePath} with ${id} begin execute`);

const readable = new Readable();

readable._read = () => {};

readable.pipe(res);

while (pidDict[id]) {

readable.push('\nWaiting for another script request.');

await wait(5000);

}

const handle = spawn('sh', [`./scripts/${filePath}`]);

pidDict[id] = handle.pid;

handle.stdout.on('data', (data) => {

readable.push(`\n${data}`);

getLogger(filePath).log(`\n${data}`);

});

handle.stderr.on('data', (data) => {

getLogger(filePath).warn(`\n${data}`);

readable.push(`\n${data}`);

});

handle.on('error', (code) => {

getLogger(filePath).error(`child process error with information: \n${code}`);

readable.push(`child process error with information: \n${code}`);

delete pidDict[id];

readable.push(null);

});

handle.on('close', (code) => {

getLogger(filePath).log(`child process close with code ${code}`);

delete pidDict[id];

readable.push(null);

});

}

app.set('port', 3018);

app.listen(app.get('port'), () => console.log(`server listening at ${app.get('port')}`));

總結

以上是生活随笔為你收集整理的node.js require 自动执行脚本 并生成html,nodejs 执行脚本并实时输出的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。