Javascript 如何在Node js中终止异步子进程?
我想从节点运行一个简单的shell脚本,并对输出进行处理。然而,child_进程似乎永远不会退出,每次我都必须控制我的程序。我已经处理了很多,我认为问题在于回调,因为当我删除它时,程序成功退出Javascript 如何在Node js中终止异步子进程?,javascript,node.js,node-async,Javascript,Node.js,Node Async,我想从节点运行一个简单的shell脚本,并对输出进行处理。然而,child_进程似乎永远不会退出,每次我都必须控制我的程序。我已经处理了很多,我认为问题在于回调,因为当我删除它时,程序成功退出 sys = require('sys') exec = require('child_process').exec p = exec "./script.sh", (error, stdout, stderr) -> doStuff stdout, -> console.log
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");
});
});
编辑:
这是一个相当痛苦的隔离问题。DoStuff正在获取一个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"
这是两个测试。test1.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调用donefetch,然后调用callbackDone
我不知所措。谢谢你的帮助
编辑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)
您是看到输出在挂起之后完成,还是只是挂起而没有输出?在我看来,doStuff并没有调用它的回调。你能发布那个函数吗?我正在做一个async.each。我正试图用一些简单的代码重新创建错误。啊,我明白了。只需将整个函数粘贴到那里,这可能是最简单的。清理并消除不必要的内容需要一段时间。但它在那里。我还是不明白!实际上是启用SSL的-我想这可能与此有关。尝试将其更改为https://并查看会发生什么。您的CURL库可能没有遵循http->https重定向。
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)