Child_process 处理带有回车 (\r) 的 STDOUT 流

dan*_*ght 5 javascript rsync stream child-process node.js

我正在编写一个简单的(ish)应用程序,它允许工作中的内部系统从远程服务器请求复制过程(使用 rsync)到另一个使用 REST 调用发起的远程服务器。

我对express框架已经足够熟悉了,刚开始尝试child_process库,偶然发现了一个小问题。

我使用 node's 成功启动了 rsync 进程childProcess.spawn(),我的问题是 rsync 输出其进度行缓冲,用回车符 (\r) 而不是换行符 (\n)。因此,STDOUT 事件process.stdout.on('data', {})只在说它正在设置传输之前被调用一次,然后在复制完成后,因为 STDOUT 数据不会在回车时刷新,随着进度更新,只有一个换行符,当工作完成。

在最新版本的 rsync (3.1.0) 中有一个开关可以将输出缓冲区结尾更改为 \n 而不是 \r 但不幸的是,我工作的公司很长一段时间都不会采用这个版本。

我正在以通常的方式生成和读取 child_process ....

var doCopy = function (onFinish) {
    var process = childProcess.spawn('ssh', [
        source.user + "@" + source.host,
        "rsync",
        "-avz",
        "--progress",
        source.path + source.file,
        "-e ssh",
        dest.user + "@" + dest.host + ":" + dest.path
    ]);

    process.on('error', function (error) {
        console.log("ERR: " + error.code);
    })

    process.stdout.on('data', function (data) {
        console.log("OUT: " + data);
    });

    process.stderr.on('data', function (data) {
        console.log("ERR: " + data);
    });

    process.on('close', function (code) {
        console.log("FIN: " + code);
        if(onFinish){
            onFinish(code);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

..并且控制台输出是..

OUT: building file list ... 
OUT: 
1 file to consider

OUT: test4.mp4

         32,768   0%    0.00kB/s    0:00:00  
    169,738,240  32%  161.84MB/s    0:00:02  
    338,165,760  64%  161.32MB/s    0:00:01  
    504,692,736  96%  160.53MB/s    0:00:00  
    524,288,000 100%  160.35MB/s    0:00:03 (xfr#1, to-chk=0/1)

OUT: 
sent 509,959 bytes  received 46 bytes  113,334.44 bytes/sec
total size is 524,288,000  speedup is 1,028.01

FIN: 0
Run Code Online (Sandbox Code Playgroud)

所以你可以看到 stdout.on('data,) 只在 rsync 输出一个新行(有一个 'OUT:' 的地方)时被调用。

我的问题是,我可以改变这个吗?当 \r 发生时,也许可以将流通过转换进行刷新?然后我可以正则表达式该行并再次提供进度更新。

如果做不到这一点,我想我唯一的其他选择是生成另一个进程来监视不断增长的文件?

非常感谢任何帮助/建议。

dan*_*ght 3

我发现这个非常好的模块完全符合我想要实现的目标。允许我用任何字符(在我的例子中为“\r”)分隔标准输出缓冲区并触发新的标准输出事件来处理数据。喜欢....

var splitter = process.stdout.pipe(StreamSplitter("\r"));

splitter.on('token', function (data) {
    console.log("OUT: " + data);
});

splitter.on('done', function (data) {
    console.log("DONE: " + data);
});
Run Code Online (Sandbox Code Playgroud)