Desanexe um processo filho spawn após o início

9

Eu inicio um processo filho spawn desta maneira:

let process = spawn(apiPath, {
  detached: true
})

process.unref()

process.stdout.on('data', data => { /* do something */ })

Quando inicio o processo, preciso mantê-lo anexado, porque quero ler sua saída. Mas, pouco antes de fechar meu processo Node (o pai), quero desanexar todos os processos filhos não concluídos para mantê-los em execução em segundo plano, mas como a documentação diz:

Ao usar a opção desanexada para iniciar um processo de longa execução, o processo não continuará sendo executado em segundo plano após a saída do pai, a menos que seja fornecida uma configuração stdio que não esteja conectada ao pai.

Mas com a opção stdio: 'ignore'não consigo ler o stdoutque é um problema.

Tentei fechar manualmente os pipes antes para fechar o processo pai, mas não obtive êxito:

// Trigger just before the main process end
process.stdin.end()
process.stderr.unpipe()
process.stdout.unpipe()
Opsse
fonte
11
Estou um pouco confuso por que você esperaria poder ler stdout / stderr de um processo independente do Node. Você precisa capturar a saída, porque o processo está executando tarefas que fazem parte do seu programa (apenas executando em paralelo); nesse caso, o Node deve ser o pai; ou você está iniciando um programa verdadeiramente independente; nesse caso, a saída padrão não é da sua conta do programa Node e você deve compartilhá-los de uma maneira que faça sentido para dois programas independentes (por exemplo, um banco de dados, monitor de arquivo, servidor de API) , tanto faz).
Mike 'Pomax' Kamermans 10/01
Talvez eu não tenha sido claro o suficiente, quando inicio o processo, preciso mantê-lo anexado porque quero ler sua saída. Mas, pouco antes de fechar meu processo Node (o pai), quero desanexar todos os processos filhos não concluídos para mantê-los em execução em segundo plano.
Opsse 10/01
Por que não ter processos / programas diferentes e compartilhar dados entre eles usando um arquivo ou algum outro meio.
Ma'moun othman 10/01
Não é o que um cachimbo faz? Então você sugere lidar com a comunicação entre processos sozinho?
Opsse 10/01
Mas por que você destacaria o processo? Ou ele está fazendo algo a serviço do seu programa; nesse caso, o seu programa deve esperar até terminar, ou deve sinalizar ao processo que está sem tempo e precisa concluir o que está fazendo, porque está prestes a ser destruído - Basicamente : qual é o caso de uso real? Porque isso soa como um candidato principal para um problema XY em que você está tentando fazer algo, e pensou em uma maneira de fazer isso, e está perguntando sobre essa maneira de fazer as coisas, em vez de perguntar sobre o problema original
Mike 'Pomax' Kamermans 10/01

Respostas:

1

Depois de muitos testes, encontrei pelo menos uma maneira de resolver esse problema: destruir todos os canos antes de sair do processo principal.

Um ponto complicado é que o processo filho precisa manipular corretamente os canos destruidores; caso contrário, pode haver um erro e fechar de qualquer maneira. Neste exemplo, o processo filho do nó parece não ter problemas com isso, mas pode ser diferente com outro cenário.

main.js

const { spawn } = require('child_process')

console.log('Start Main')

let child = spawn('node', ['child.js'], { detached: true })
child.unref() // With this the main process end after fully disconnect the child

child.stdout.on('data', data => {
  console.log(`Got data : ${data}`)
})

// In real case should be triggered just before the end of the main process
setTimeout(() => {
  console.log('Disconnect the child')

  child.stderr.unpipe()
  child.stderr.destroy()
  child.stdout.unpipe()
  child.stdout.destroy()
  child.stdin.end()
  child.stdin.destroy()
}, 5000)

child.js

console.log('Start Child')

setInterval(function() {
   process.stdout.write('hello from child')
}, 1000)

resultado

Start Main
Dados obtidos: Start Child

Obteve dados: Olá da criança
Obteve dados: Olá da criança
Obteve dados: Olá da criança
Obteve dados: Olá da criança
Desconecte a criança

Opsse
fonte