如何在不显示stdout的情况下使用set-x



在CI中,我正在运行一个调用许多bash脚本的bash脚本。

./internals/declination/create "${RELEASE_VERSION}" "${CI_COMMIT_REF_NAME}" > /dev/null

不会禁用脚本返回的stdout

Gitlabi CI运行程序在100MB的日志后停止日志记录,它说Job's log exceeded limit of 10240000 bytes

我知道日志脚本只能长大。

如何优化输出日志大小?

我不需要拥有所有的stdout,我可以拥有stderr,但这将是一个没有信息的长时间运行的脚本。

有没有一种方法可以像执行set -x时一样显示正在运行的命令?

编辑

看了答案,我没能解决我的问题。我需要补充的是,我正在使用nodejs来运行运行长bash脚本的bash脚本。

这就是我在.gitlab-ci.yml:中调用节点脚本的方式

scripts:
- node my_script.js

my_script.js中,我有:

exports.handler = () => {
const ls = spawn('bash', [path.join(__dirname, 'release.sh')], { stdio: 'inherit' });
ls.on('close', (code) => {
if (code !== 0) {
console.log(`ps process exited with code ${code}`);
process.exitCode = code;
}
});
};

my_script.sh中,我有:

./internals/declination/create "${RELEASE_VERSION}" "${CI_COMMIT_REF_NAME}" > /dev/null

您可以使用exec选择性地重定向文件句柄。

exec >stdout 2>stderr

然而,这会失去与端子的连接,因此在此点之后没有简单的方法向端子输出任何内容。

您可以使用m>&n复制文件句柄,其中m是要复制的文件描述符的编号,n是新描述符的编号(选择99这样的大数字以避免意外地破坏现有句柄(。

exec 98<&1  # stdout
exec 99<&2  # stderr
exec >/dev/null 2>&1
:

要重新启用输出,

exec 1<&98 2<&99

如果您重定向到一个临时文件而不是/dev/null,那么现在显然可以向调用者显示这些文件的tail

tail -n 100 "$TMPDIR"/stdout "$TMPDIR"/stderr

(在共享服务器上,可能在脚本开始时使用mktemp创建一个唯一的临时目录;静态硬编码文件名使其无法同时运行两个构建。(

由于您通常无法预测下一个错误将在哪里发生,因此可能将所有这些都放在一个包装脚本中,该脚本执行重定向、运行构建并最终显示临时日志文件的尾部。一些构建服务器可能希望每隔几分钟在日志文件中看到一些生命迹象,因此可能每隔一段时间就会在循环中看到tail几行。

另一方面,如果只有一个构建命令,那么整个构建作业的stdout和stderr可以简单地重定向到日志文件,而不需要来回exec。如果需要为脚本的部分选择性地启用输出,请如上所述使用exec;但对于大规模重定向,只重定向一个命令。

总之,也许您的构建脚本会是这样的。

#!/bin/sh
t=$(mktemp -t -d cibuild.XXXXXXXX) || exit
trap 'kill $buildpid; wait $buildpid; tail -n 500 "$t"/*; rm -rf "$t"' 0 1 2 3 5 15
# Your original commands here
${initial_process_wd}/internals/declination/create "${RELEASE_VERSION}" "${CI_COMMIT_REF_NAME}">"$t"/stdout 2>"$t"/stderr &
buildpid=$!
while kill -0 $buildpid; do
sleep 180
date
tail -n 1 "$t"/*
done
wait

这种方法的一个缺陷是丢失了时间信息。一个合适的解决方案可以让你看到每一行是什么时候产生的,并按照消息的打印顺序显示混合的标准输出和标准错误,可能带有可见的时间戳,甚至带有着色提示(stderr的红色时间戳?(

选项1

如果您的脚本将错误消息输出到stderr,您可以使用command > /dev/null忽略stdout的所有输出,其中/dev/null是一个黑洞,它将带走任何输出。

选项2

如果您的错误消息中有任何模式,您可以使用grep来过滤掉这些错误消息。


编辑1:

要显示正在运行的命令,可以向bash提供-x命令;因此,您的命令将是

bash -x ${initial_process_wd}/internals/declination/create "${RELEASE_VERSION}" "${CI_COMMIT_REF_NAME}" > /dev/null

bash将执行的命令打印到stderr


编辑2:

如果要减小输出文件的大小,可以使用${initial_process_wd}/internals/declination/create "${RELEASE_VERSION}" "${CI_COMMIT_REF_NAME}" | gzip > logfile将其传递给gzip

要读取日志文件的内容,可以使用zcat logfile

相关内容

最新更新