当试图从 make 过滤很长的输出以获取特定的警告或错误消息时,第一个想法是这样的:
$ make | grep -i 'warning: someone set up us the bomb'
但是,结果并不完全令人满意。输出不仅包含过滤结果,grep
还包含来自目标某处使用的其他工具的消息stdout
。stderr
make
现在的问题是:
- 其他输出从何而来?
- 如何编写输出只包含过滤行的过滤命令?
要回答问题:
stdout
of连接make
到stdin
grep。make
'sstderr
仍然连接到终端,因此将在不过滤的情况下打印。make
解决方案是连接stderr
到它stdin
并忽略stdin
$ make 2>&1 >/dev/null | grep -i 'warning: someone set up us the bomb'
这只会打印 grep 的输出,但不会打印 make 或其他工具(如rm
.
我只是想看看我的编译器的警告。使用 make 的静音选项让我接近我想要的地方。
从制作手册页:
-s, --silent, --quiet
Silent operation; do not print the commands as they are executed.
我仍然想忽略大量编译器警告,所以我在调用 make 时设置了 CFLAGS
例如:
make -s CFLAGS="-Wno-deprecated-declarations"
如果您使用的是 libtool,这也很方便
make LIBTOOLFLAGS='--silent' --quiet
如果我只对特定文件或一组文件感兴趣,我会使用 touch 命令,然后使用静默 make。
触摸 foo.c; make -s CFLAGS="-Wno-deprecated-declarations"
最初我开始尝试 grep make 输出,但静默调用 make、控制编译警告和触摸文件以限制编译会更干净。毕竟,您仍然可以使用 grep,但我会先查看构建系统和编译器手册页。
排除标准错误:
make 2>/dev/null | grep -i 'warning: someone set up us the bomb'
$ ls
hello
$ ls hello bye
ls: cannot access bye: No such file or directory # <--- this is stderr
hello
$ ls hello bye 2>/dev/null # <--- stderr are sent to /dev/null, so don't appear
hello
如评论中所见,所有make
输出都以 stderr 形式给出,因此第一个解决方案根本不匹配任何内容。因此,我的建议是使用以下内容:
make 2> >(tee make_output.log >&2)
然后 grep make_output.log
。正如在如何将“tee”与管道一起使用时如何将标准错误写入文件中所见?.
$ ls aaa
ls: cannot access aaa: No such file or directory
$ ls aaa 2> >(tee stderr.log >&2)
ls: cannot access aaa: No such file or directory
$ cat stderr.log
ls: cannot access aaa: No such file or directory