Search code examples
node.jsstdiospawnlzma

How to make spawned process know it's not writing to a terminal (nodejs)


I'm writing a little wrapper to the lzma command in Linux but the program refuses to write to stdout because it believes to be in an interactive terminal: lzma: Compressed data cannot be written to a terminal

This is my code in js

// Compress a given string using the lzma program, and return the compressed contents.

const { spawn } = require('child_process')


const compress = str => new Promise((resolve, reject) => {
    
    const lzma = spawn('lzma', ["-z", "-c", "-9"],
        { stdio: [process.stdin, process.stdout, process.stderr] })

    lzma.on('error', err => {
        // console.log(`Failed to start lzma: ${err}`)
        reject(err)
    })

    lzma.on('exit', (code, signal) => {
        if (code) {
            // console.log(`lzma process exited with code ${code}`)
            reject(code)
        }
        else if (signal) {
            // console.log(`lzma process exited with signal ${signal}`)
            reject(signal)
        }
        else {
            // console.log(`lzma process exited successfully`)
            resolve(compressed)
        }
    })

    lzma.stdin.write(str)
    lzma.stdin.end()

    let compressed = ''
    lzma.stdout.on('data', data => { compressed += data })

})

module.exports = compress

How do I override this behavior?


Solution

  • Try changing line 9 to:

    { stdio: ["pipe", "pipe", "inherit"] })
    

    lzma.stdin and lzma.stdout won't do anything unless they're connected to a pipe. "inherit" means that if lzma writes to stderr, you'll see it on the calling process's stderr.

    See the node docs for more info.