0

我想从节点运行一个简单的 shell 脚本并对输出做一些事情。但是,child_process 似乎永远不会退出,我每次都必须控制-c 我的程序。我已经摆弄了一堆,我认为问题出在回调上,因为当我删除它时,程序成功退出..

sys = require('sys')
exec = require('child_process').exec

p = exec "./script.sh", (error, stdout, stderr) ->
  doStuff stdout, ->
    console.log "finished"

对于那些讨厌咖啡脚本的人:

sys = require('sys');
exec = require('child_process').exec;

p = exec("./script.sh", function(error, stdout, stderr) {
  return doStuff(stdout, function() {
    return console.log("finished");
  });
});

编辑:

隔离问题是相当痛苦的。Do stuff 正在获取一个 url,而这个挂断问题似乎只在出现错误时发生。这是我正在使用的代码。

#!/usr/bin/env coffee

path = require 'path'
fs = require 'fs'
program = require 'commander'
urllib = require 'url'
async = require 'async'
nedb = require 'nedb'
sys = require 'sys'
exec = require('child_process').exec

db = new nedb()

fetchUrl = (url, callbackErrHtml) ->
  urlBits = urllib.parse(url)
  protolib = (if urlBits.protocol is "https:" then "https" else "http")
  response = (r) ->
    if r.statusCode isnt 200
      callbackErrHtml('status code isnt 200')
    else if not r.headers['content-type']?
      callbackErrHtml('no content type')
    else if r.headers['content-type'].indexOf('html') is -1
      callbackErrHtml('no html')
    else
      html = ''
      r.on 'data', (chunk) -> html += chunk
      r.on 'end', ->
        callbackErrHtml(null, html)

  httpError = (err) ->
    callbackErrHtml(err)

  require(protolib).get(url, response).on('error', httpError)


indexUrls = (urls, callbackDone) ->
  errorUrls = []

  fetchEach = (url, callbackFetch) ->
    console.log url
    db.count {url:url}, (err, count) ->
      if count isnt 0
        console.log "1 - done", url
        callbackFetch()
      else
        fetchUrl url, (err, html) ->
          if err
            console.log "2 - done", url, err
            errorUrls.push(url)
            callbackFetch()
          else
            db.insert {url:url, html:html, createdAt: Date.now()}, (err, doc) ->
              if err
                console.log "3 - done", url
                callbackFetch()
              else
                console.log "4 - done", url
                callbackFetch()


  doneFetching = (err) ->
    if err then console.log err
    callbackDone()

  async.each urls, fetchEach, doneFetching


p = exec "./test1.sh", (err, stdout, stderr) ->
  if err
    console.log err
  else
    bookmarks = stdout.split('\n')[..-2]
    console.log 'bookmarks:', bookmarks

    indexUrls bookmarks, (err) ->
      if err then console.log err
      console.log "finished import safari bookmarks"

这是两个测试。测试1.sh:

#!/usr/bin/env bash

echo "http://hackerexperience.com/"

和 test2.sh

#!/usr/bin/env bash

echo "http://www.allaboutcircuits.com/
http://sandwichvideo.com/
http://www.allaboutcircuits.com/
http://onethingwell.org/
http://saastr.quora.com/How-to-Figure-Out-Your-Competitors%E2%80%99-Revenues-in-About-70-Seconds
https://maebert.github.io/jrnl/usage.html"

当我使用 test2.sh 运行时,我在控制台中得到这些结果并且程序成功退出。

bookmarks: [ 'http://www.allaboutcircuits.com/',
  'http://sandwichvideo.com/',
  'http://www.allaboutcircuits.com/',
  'http://onethingwell.org/',
  'http://saastr.quora.com/How-to-Figure-Out-Your-Competitors%E2%80%99-Revenues-in-About-70-Seconds',
  'https://maebert.github.io/jrnl/usage.html' ]
http://www.allaboutcircuits.com/
http://sandwichvideo.com/
http://www.allaboutcircuits.com/
http://onethingwell.org/
http://saastr.quora.com/How-to-Figure-Out-Your-Competitors%E2%80%99-Revenues-in-About-70-Seconds
https://maebert.github.io/jrnl/usage.html
4 - done http://sandwichvideo.com/
4 - done http://www.allaboutcircuits.com/
4 - done http://www.allaboutcircuits.com/
4 - done http://saastr.quora.com/How-to-Figure-Out-Your-Competitors%E2%80%99-Revenues-in-About-70-Seconds
4 - done http://onethingwell.org/
4 - done https://maebert.github.io/jrnl/usage.html
finished import safari bookmarks

当我运行 test1.sh 时,url 获取失败并出现错误。这是我得到的控制台日志,程序仍然挂起,即使callbackFetch似乎被称为调用doneFetching然后callbackDone.

bookmarks: [ 'http://hackerexperience.com/' ]
http://hackerexperience.com/
2 - done http://hackerexperience.com/
finished import safari bookmarks

我很茫然。谢谢您的帮助。

编辑2:

所以我在这里有更多的见解。如果我让 test1 运行足够长的时间,它最终会退出。但是,如果我让它继续运行,它最终会存在。但是,我注意到当我将 url 更改为'http://break.com/'并让它继续运行时,我收到回调发生太多次的错误...

bookmarks: [ 'http://break.com/' ]
http://break.com/
2 - done http://break.com/ status code isnt 200
finished import safari bookmarks
2 - done http://break.com/ { [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }

/Users/chetcorcos/node_modules/async/lib/async.js:30
            if (called) throw new Error("Callback was already called.");
                              ^
Error: Callback was already called.
  at /Users/chetcorcos/node_modules/async/lib/async.js:30:31
  at /Users/chetcorcos/Projects/bookmarks/test.coffee:53:13
  at ClientRequest.httpError (/Users/chetcorcos/Projects/bookmarks/test.coffee:34:5)
  at ClientRequest.EventEmitter.emit (events.js:95:17)
  at Socket.socketErrorListener (http.js:1548:9)
  at Socket.EventEmitter.emit (events.js:95:17)
  at net.js:441:14
  at process._tickCallback (node.js:415:13)
4

0 回答 0