编辑 2
我“解决”了问题,但我不想将其作为答案发布,因为它没有解释实际发生的事情。在我使用的 .NET resourceReader.exe
代码中
Console.OutputEncoding = System.Text.Encoding.UTF8;
将国际化资源以unicode格式输出到stdout
。如果我在程序结束时使用
Console.OutputEncoding = System.Text.Encoding.Default;
然后我在 Node.js 中没有收到任何错误。如果我不重置它,我会收到原始问题中描述的错误。似乎 .NET 以某种方式弄乱了 cmd.exe
上的一些输出编码设置,并导致后续 Node 运行失败!
编辑
我将错误缩小为由 resourceReader.exe
引起的。这是一个 .NET 程序,它从 .NET 程序集中读取一些资源流,并使用 Console.WriteLine
将它们打印到标准输出。我将 Console.OutputEncoding = System.Text.Encoding.UTF8
添加到 resourceReader.exe
因为一些资源是非 ASCII 字母,这就是导致 grunt 崩溃的原因!
如果我删除该行,任务不会崩溃,但资源会以不可打印的 ASCII 字符显示!此外,只有当我实际将非 ASCII 打印到 sdtout 时才会发生崩溃。如果我不打印它们,它就不会出错。
原创
我向我的 Gruntfile 添加了一个步骤,它使用 child_process.execFile
运行并从外部程序读取一些数据并在构建中使用它。现在,每当我运行我的构建时,它第一次运行良好,但第二次崩溃!
这是崩溃的输出(这是在 uglify 任务期间):
File build/Scripts/NDB.contacts.min.js created: 16.85 kBevents.js:85
throw er; // Unhandled 'error' event
^
Error: This socket is closed.
at WriteStream.Socket._writeGeneric (net.js:656:19)
at WriteStream.Socket._write (net.js:709:8)
at doWrite (_stream_writable.js:301:12)
at writeOrBuffer (_stream_writable.js:288:5)
at WriteStream.Writable.write (_stream_writable.js:217:11)
at WriteStream.Socket.write (net.js:634:40)
at Log._write (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:161:26)
at Log.wrapper [as _write] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
at Log._writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:166:8)
at Log.wrapper [as _writeln] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
at Log.writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:177:8)
at Log.wrapper (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
at writeln (C:\...\node_modules\grunt\lib\grunt\fail.js:30:13)
at Object.fail.fatal (C:\...\node_modules\grunt\lib\grunt\fail.js:46:3)
at process.uncaughtHandler (C:\...\node_modules\grunt\lib\grunt.js:121:10)
at process.emit (events.js:129:20)
at process._fatalException (node.js:236:26)
at Task.runTaskFn (C:\...\node_modules\grunt\lib\util\task.js:250:7)
at Task.<anonymous> (C:\...\node_modules\grunt\lib\util\task.js:293:12)
at C:\...\node_modules\grunt\lib\util\task.js:220:11
at process._tickCallback (node.js:355:11)
这是使用 child_process 的任务的代码。
function readAllCultures() {
var readDeferred = q.defer();
childProc.execFile("../tools/resourceReader.exe", function (err, stdout, stderr) {
if (err) throw new Error(err);
var cultures = JSON.parse(stdout);
readDeferred.resolve(cultures);
});
return readDeferred.promise;
}
以下是我在调试时发现的一些可能有用的东西
- 如果我重定向 grunt 的输出(使用
> filename
或| process
)它运行良好 - 当我重定向输出时,我从来没有看到来自 uglify 的消息,它创建了主输出,只看到它创建了源映射。
- 如果我关闭并重新打开我的命令提示符 (
cmd.exe
),它工作正常 - 我使用
rdr.on("close", function() { console.log 为子进程的
和退出相同。这两个事件在第一次运行时都按预期触发。exit
和close
事件添加了一个监听器("close"); }); - 使用 Process Explorer,我可以看到
node.exe
在命令提示符下打开,并在我的命令运行完成后再次关闭。在命令提示符下没有明显“保持打开状态”的进程。
最佳答案
堆栈跟踪最终显示 socket.write
错误这一事实很有趣。您提供的代码中没有任何内容表明您正在尝试写入套接字。
如果我们顺着堆栈往下看,我们可以看到它实际上是在尝试写入一个套接字,因为它正在尝试记录一个未捕获的异常。
因此,首先您的 grunt 任务会抛出一个当前未知的错误,然后 grunt 本身会出现错误,因为它无法告诉您。
我会首先尝试记录您的子进程中发生的错误。目前,如果出现错误,您只需简单地throw
错误,而无需找出它是什么。很可能这就是 grunt 尝试记录但未能记录的内容。
替换
if (err) throw new Error(err);
与
if (err) console.error(err);
这将有望避免 socket.write
问题,并为您提供有关子进程发生什么错误的具体信息。你看到了什么?
其次,我会尝试使用 child_process.exec
而不是 child_process.execFile
。这将生成一个 shell 并在其中运行 resourceReader.exe
(而不是直接运行它)。这可能有助于避免您在后台运行/失败命令时遇到的任何问题,这可能是 socket.write
错误的原因。
关于c# - 运行 child_process.execFile 后 uglify 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37000805/