使用 Node.js child_process 生成 strace 命令
spawn strace command with Node.js child_process
因为我对 this approach and I got no answers, I'm trying another method to track the output of an already running program. I based this code on this Unix Stack Exchange 不满意,我想做的只是检索已经 运行.
的程序的日志信息
Obs:要在没有 sudo
的情况下使用 strace
,您需要使用以下命令允许它:
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 获得的输出不保证在换行符边界上被分割。当您的输出速度变慢时,它会 碰巧 正常工作。更快的输出会将多行聚集在一起,并可能在 non-newline 边界处拆分行。为了快速修复,将 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 输出中的 double-quote 得到输出为 \"
,但我不知道实际情况是否如此。
因为我对 this approach and I got no answers, I'm trying another method to track the output of an already running program. I based this code on this Unix Stack Exchange 不满意,我想做的只是检索已经 运行.
的程序的日志信息Obs:要在没有 sudo
的情况下使用 strace
,您需要使用以下命令允许它:
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 获得的输出不保证在换行符边界上被分割。当您的输出速度变慢时,它会 碰巧 正常工作。更快的输出会将多行聚集在一起,并可能在 non-newline 边界处拆分行。为了快速修复,将 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 输出中的 double-quote 得到输出为 \"
,但我不知道实际情况是否如此。