0

ノードから簡単なシェル スクリプトを実行し、出力を処理したいと考えています。ただし、 child_process は終了しないようで、毎回プログラムを制御する必要があります。私はこれをいじりましたが、コールバックを削除するとプログラムが正常に終了するため、問題はコールバックにあると思います..

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"

そして、ここに2つのテストがあります。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呼び出しが呼び出されたように見えてdoneFetchingも、プログラムはハングしたままcallbackDoneです。

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

私は途方に暮れています。助けてくれてありがとう。

EDIT2:

だから私はここでもう少し洞察を持っています。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