Strange behavior of node js spawn/exec with unzipped content

374 views Asked by At

I'm trying to write a client which installs and updates packages using nodejs with mqtt. I tested all functionalities of data transfer and archiving but when I came to windows environment and actualy tried to run some scripts I came to some strange errors.

I will add some code so anyone can see exacly how I write downloaded content to disk but first I will explain behaviour.

Steps taken for each itteration:

  • download content from mqtt (works)
  • create buffer and stream from it (works)
  • unzip stream to disk (works)
  • run batch job in downloaded content (strange things happen)
  • run another batch job (even stranger)

Strange things: At first try spawn/exec respoonses with: error spawn cmd.exe ENOENT, but at second try (triggered by topic subscription) it goes over that stage. But the next itteration when first batch job passes second job returns Error: EBUSY: resource busy or locked, open C:\[email protected]\nssm.exe' where nssm.exe is file called from batch job

Code for downloading and extraction:

const debug = require('debug')('service-manager:functions:download')
const serviceBus = require('../helpers/mqtt-helper.js')
const stream = require('stream')
const unzip = require('unzip-stream')

module.exports = (service, to, from) => {
  debug(`Downloading ${service}@${to}`)
  return serviceBus.getFromBus(`service_manager/${service}/${to}`)
    .then(data => {
      debug(`Downloaded ${service}@${to}`)
      return new Promise((resolve, reject) => {
        debug(`Unzipping ${service}@${to}`)
        const buffer = Buffer.from(data)
        const bufferStream = new stream.PassThrough()
        bufferStream.end(buffer)
        bufferStream.pipe(unzip.Extract({
          path: `${__dirname}/../../services/active/${service}@${to}`
        })).on('finish', resolve)
      }).then(() => {
        debug(`Unzipped ${service}@${to}`)
      })
    })
}

Code used to run batch jobs:

const debug = require('debug')('service-manager:functions:runner')
const { exec } = require('child_process')
const { resolve } = require('path')
module.exports = (type, reverse) => (service, to, from) => {
  return new Promise((resolve, reject) => {
    debug(`Running ${type} for ${service}@${reverse ? from : to}`)
    const batchFile = resolve(
      `../../services/active/${service}@${reverse ? from : to}/${type}.sh`
    )
    exec(batchFile, (error, stdout, stderr) => {
      if (error) {
        return reject(error)
      }
      debug(`Gotten STDOUT on ${type} for ${service}@${reverse ? from : to}: ${stdout}`)
      debug(`Gotten STDERR on ${type} for ${service}@${reverse ? from : to}: ${stderr}`)
      return resolve()
    })
  })
}
1

There are 1 answers

0
klemen676 On BEST ANSWER

It turns out that unzip-stream called finish and close event before files were written on dist which resulted in files not being accessible to run with batch script. I swaped libraries and it worked.