我想从节点运行一个简单的shell脚本,并对输出做一些事情。但是,child_process似乎永远不会退出,我每次都必须控制我的程序。我已经摆弄了这一堆,我认为问题在于回调,因为当我删除它时,程序成功退出..
sys = require('sys')
exec = require('child_process').exec
p = exec "./script.sh", (error, stdout, stderr) ->
doStuff stdout, ->
console.log "finished"
对于那些讨厌coffeescript的人:
sys = require('sys');
exec = require('child_process').exec;
p = exec("./script.sh", function(error, stdout, stderr) {
return doStuff(stdout, function() {
return console.log("finished");
});
});
编辑:
隔离问题非常痛苦。什么东西是提取网址,这种挂起问题似乎只有在出现错误时才会发生。这是我正在使用的代码。
#!/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 fetch失败并显示错误。这是我得到的控制台日志,即使callbackFetch
似乎调用doneFetching
然后调用callbackDone
,程序仍保持挂起状态。
bookmarks: [ 'http://hackerexperience.com/' ]
http://hackerexperience.com/
2 - done http://hackerexperience.com/
finished import safari bookmarks
我不知所措。谢谢你的帮助。
EDIT2:
所以我在这里有更多的见解。如果我让test1运行足够长时间,它最终会退出。但是,如果我让它继续运行,它最终会存在。但是,我注意到当我将网址更改为'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)