16 node.js
我试图通过传递数据来执行Inkscape stdin.Inkscape仅支持此功能/dev/stdin.基本上,我正在尝试做这样的事情:
echo "<sgv>...</svg>" | inkscape -z -f /dev/stdin -A /dev/stdout
Run Code Online (Sandbox Code Playgroud)
我不想将SVG写入磁盘.
我试过使用stdin.write(),但它不起作用(也许是因为/dev/stdin):
var cmd = spawn("inkscape", ["-z", "-f", "/dev/stdin", "-A", "/dev/stdout"], {encoding: "buffer", stdio: ["pipe", stdoutPipe, "pipe"]});
cmd.stdin.write(svg);
Run Code Online (Sandbox Code Playgroud)
这确实有效,但我必须将SVG写入磁盘:
var cmd = spawn("inkscape", ["-z", "-f", "/dev/stdin", "-A", "/dev/stdout"], {encoding: "buffer", stdio: [fs.openSync('file.svg', "a"), stdoutPipe, "pipe"]});
Run Code Online (Sandbox Code Playgroud)
我试过传递一个流stdio,但我只是继续TypeError: Incorrect value for stdio stream: [object Object]
有任何想法吗?
这些示例使用Inkscape,但我的问题适用于任何使用的任意程序/dev/stdin.
顺便说一句,这对我有用:
var exec = require('child_process').exec;
exec("echo \"<svg>...</svg>\" | inkscape -z -f /dev/stdin -A /dev/stdout | cat", function (error, stdout, stderr) {});
Run Code Online (Sandbox Code Playgroud)
除了,我的SVG太长,所以它抛出一个错误: Error: spawn Unknown system errno 7
小智 7
好吧,我没有Inkscape,但这似乎解决了Node.js方面的问题.我wc在Inkscape中使用它作为一个立场; 该-c选项只输出给定文件中的字节数(在本例中/dev/stdin).
var child_process = require('child_process');
/**
* Create the child process, with output piped to the script's stdout
*/
var wc = child_process.spawn('wc', ['-c', '/dev/stdin']);
wc.stdout.pipe(process.stdout);
/**
* Write some data to stdin, and then use stream.end() to signal that we're
* done writing data.
*/
wc.stdin.write('test');
wc.stdin.end();
Run Code Online (Sandbox Code Playgroud)
这个技巧似乎表明你已经完成了对流的写作.根据SVG的大小,您可能需要通过处理事件来关注 Inkscape的背压'drain'.
至于将流传递给child_process.spawn调用,您需要使用该'pipe'选项,然后将可读流传输到其中child.stdin,如下所示.我知道这在Node v0.10.26中有效,但在此之前不确定.
var stream = require('stream');
var child_process = require('child_process');
/**
* Create the child process, with output piped to the script's stdout
*/
var wc = child_process.spawn('wc', ['-c', '/dev/stdin'], {stdin: 'pipe'});
wc.stdout.pipe(process.stdout);
/**
* Build a readable stream with some data pushed into it.
*/
var readable = new stream.Readable();
readable._read = function noop() {}; // See note below
readable.push('test me!');
readable.push(null);
/**
* Pipe our readable stream into wc's standard input.
*/
readable.pipe(wc.stdin);
Run Code Online (Sandbox Code Playgroud)
显然,这种方法有点复杂,你应该使用上面的方法,除非你有充分的理由(你有效地实现了自己的可读字符串).
注意:该readable._push函数必须根据文档实现,但不一定要做任何事情.
小智 5
所以,我想出了一个解决方案.这看起来有点像黑客,但它的工作正常.
首先,我制作了这个单行shell脚本:
cat | inkscape -z -f /dev/stdin -A /dev/stdout | cat
Run Code Online (Sandbox Code Playgroud)
然后,我只是生成该文件并写入stdin,如下所示:
cmd = spawn("shell_script");
cmd.stdin.write(svg);
cmd.stdin.end();
cmd.stdout.pipe(pipe);
Run Code Online (Sandbox Code Playgroud)
我真的认为这应该没有shell脚本,但它不会(至少对我来说).这可能是Node.js错误.
问题来自于节点中的文件描述符是套接字,并且如果它是套接字,那么linux(可能是大多数Unices)将不允许你打开/ dev/stdin.
我在https://github.com/nodejs/node-v0.x-archive/issues/3530#issuecomment-6561239上找到了bnoordhuis的解释
给定的解决方案接近@nmrugg的答案:
var run = spawn("sh", ["-c", "cat | your_command_using_dev_stdin"]);
Run Code Online (Sandbox Code Playgroud)
进一步的工作之后,您现在可以使用https://www.npmjs.com/package/posix-pipe模块来确保进程看到的stdin不是套接字.
看看这个模块中的"应该将数据传递给子进程"测试归结为
var p = pipe()
var proc = spawn('your_command_using_dev_stdin', [ .. '/dev/stdin' .. ],
{ stdio: [ p[0], 'pipe', 'pipe' ] })
p[0].destroy() // important to avoid reading race condition between parent/child
proc.stdout.pipe(destination)
source.pipe(p[1])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5889 次 |
| 最近记录: |