【问题标题】:avoiding simultaneous execution of shell command with node.js & shelljs避免使用 node.js & shelljs 同时执行 shell 命令
【发布时间】:2018-12-12 22:21:38
【问题描述】:

在 Gnu/Linux CentOS 7 上使用 nodejs 8.12。使用内置 Web 服务器 require('https') 来构建一个简单的应用程序。

我了解 nodejs 是单线程(单进程),没有实际的代码并行执行。根据我的理解,我认为http/https服务器会处理一个http请求,并通过所有同步语句运行处理程序,并设置稍后执行的异步语句,然后再返回处理后续请求。但是,对于 http/https 库,您有一个用于组装请求正文的异步代码。所以,我们已经有一个回调,它在主体准备好('end' 事件)时执行。这个事实让我觉得有可能同时处理两个或多个请求。

作为处理请求的一部分,我需要执行一串 shell 命令,我使用 shelljs.exec 库来执行此操作。它同步运行,等待完成后再返回。因此,示例代码如下所示:

const shelljs_exec = require('shelljs.exec');
function process() {
   // bunch of shell commands in string
   var command_str = 'command1; command2; command3';
   var exec_results = shelljs_exec(command_str);
   console.log('just executed shelljs_exec command');
   var proc_results = process_results(exec_results);
   console.log(proc_results);
   // and return the response... 
}

所以 node.js 运行 shelljs_exec() 并等待完成。在等待时,是否可以处理另一个请求,从而存在两个或多个 shelljs.exec 调用同时运行的轻微风险?由于这可能是一个问题,我需要确保在给定时间只能执行一个 shelljs.exec 语句。

如果这不是一个正确的理解,那么我在想我需要对互斥锁做一些事情。像这样:

const shelljs_exec = require('shelljs.exec');
const locks = require('locks');

// Need this in global scope - so we are all dealing with the same one.
var mutex = locks.createMutex();

function await_lock(shell_commands) {
  var commands = shell_commands;
  return new Promise(getting_lock => {
    mutex.lock(got_lock_and_execute);
  });

  function got_lock_and_execute() {
    var exec_results = shelljs_exec(commands);
    console.log('just executed shelljs_exec command');
    mutex.unlock();
    return exec_results;
  }
}

async function process() {
  // bunch of shell commands in string
  var command_str = 'command1; command2; command3';
  exec_results = await await_lock(command_str);
  var proc_results = process_results(exec_results);
  console.log(proc_results);
}

【问题讨论】:

    标签: javascript node.js


    【解决方案1】:

    如果shelljs_exec 是同步的,则不需要。

    如果不是。如果需要回调,则将其包装在 Promise 构造函数中,以便可以等待它。我建议将mutex.lock 正确包装在获得锁时得到解决的承诺中。如果shelljs_exec 抛出异常,则需要try finally 来确保解锁mutex

    async function await_lock(shell_commands) {
      await (new Promise(function(resolve, reject) {
        mutex.lock(resolve);
      }));
      try {
        let exec_results = await shelljs_exec(commands);
        return exec_results;
      } finally {
        mutex.unlock();
      }
    }
    

    未经测试。但它看起来应该可以工作。

    【讨论】:

    • 你的第一句话就是答案。但是,我深入研究了您提供的 async/await 代码,但它不起作用。承诺永远不会得到解决。我进一步研究它,但没有让它完全工作。这是代码:
    • const shelljs_exec = require('shelljs.exec'); const locks = require('locks'); var mutex = locks.createMutex(); function got_lock() { console.log('got_lock: 得到了锁');互斥锁(); } function promise_cb(resolve, reject) { console.log('promise_cb: resolve = ' + resolve); mutex.lock(got_lock); console.log('promise_cb: 在 mutex.lock'); }
    • // 和... async function await_lock(cmds) { await (new Promise(promise_cb)); console.log('等待完成');尝试 { 让结果 = 等待 shelljs_exec(cmds);返回结果; } 捕捉 { mutex.unlock(); } }
    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多