问题描述
由于我对this approach不满意,也没有答案,因此我尝试使用另一种方法来跟踪已经运行的程序的输出。我将这段代码基于this Unix Stack Exchange,而我试图做的只是检索已经运行的程序的日志信息。
提示:要在不使用strace
的情况下使用sudo
,则需要通过以下命令允许它使用:
echo kernel.yama.ptrace_scope = 0 > /etc/sysctl.d/10-ptrace.conf
可能只有重启后才能工作。
这是我使用strace
Linux命令和节点child_process
的代码,其中-p1234
是我们要跟踪的进程号。
import { spawn } from 'child_process';
const strace = spawn('strace',[ `-p1234`,'-s9999','-e','write']);
strace.stdout.on('data',(data) => {
// I don't kNow why,but my output is not being returned here
console.log(`stdout: ${data}`);
});
strace.stderr.on('data',(data: any) => {
// 'data' output is something like: 'write(4,"my real log",4) = 4\n',// so we need to cleanup a little bit with regex.
const prefix = /^\write\(1,"/
const suffix = /",[0-9]\)?\s*=?\s?[0-9]?/
const raw = `${data}`.trim()
if (raw.match(prefix) && raw.match(suffix)) {
// cleaning msg
let log = raw.replace(prefix,'').trim().replace(suffix,'').trim();
if (!log.includes('\n')) {
// showing msg: "my real log"
console.log(log);
}
}
});
首先:我不解释为什么我的日志是在stderr
而不是stdout
上输出的,但是好吧,我还是遵循编码。
第二:如果我正在运行的程序输出日志的速度很慢,例如一次打印一张,效果很好。
但是当我有2张,3张或4张打印序列时,它不起作用。我想我花了太多时间来清理邮件,所以当另一个strace.stderr.on()
出现时,我正处于过程中,并且会发生一些问题。在这种情况下,我只能看到序列的前print
。
我需要清除很多信息,因为消息的输出格式如下:
'write(4,"9883",4) = 4\n'
那是一团糟。我认为也许只打印消息内容的命令也可以解决我的问题。
关于如何获得这些消息的更一致输出的任何想法?就像我说的,我的唯一目的是检索另一个已经运行的程序正在输出的消息。我还尝试遵循“登录文件并读取文件” 方法,但是正如我所说,我有一些other issues
为实现该目标而提出的任何建议,改进或完全不同的方法,将不胜感激!
解决方法
首先,我对strace(1)手册页的阅读表明stderr是该命令的默认设置(请在该页面中查找--output
)。
在data
事件中从strace获得的输出不能保证在换行符边界上分割。当输出缓慢时,它会stderr
传递到readline的实例:
const rl = require('readline').createInterface({input: strace.stderr})
完成此操作后,如果您需要进一步的帮助来解析输出,则可以使用更好的正则表达式来一次解析整行:
rl.on('line',line => {
const re = /^write\((?<fd>\d+),\s*"(?<data>(?:[^"]|\\")*)",\s*(?<len>\d+)\)\s*=\s*(?<written>\d+)/
const m = line.match(re)
if (m) {
console.log(m.groups.data)
}
})
这将使用新命名的捕获组,因此,如果使用的节点版本非常旧,请删除看起来像?<fd>
的部分,而不要使用m.groups.data
来代替m[2]
。
这还假定strace输出中的双引号将输出为\"
,但我不知道是否确实如此。