中止时如何使用 SIGINT 而不是 SIGTERM 终止 Jenkins 作业中的 psql 进程?

Posted

技术标签:

【中文标题】中止时如何使用 SIGINT 而不是 SIGTERM 终止 Jenkins 作业中的 psql 进程?【英文标题】:How to terminate psql process inside Jenkins job with SIGINT instead of SIGTERM when aborted? 【发布时间】:2017-07-19 09:40:33 【问题描述】:

我有一个 Jenkins 作业,它使用 shell (bash) 脚本中的 psql 命令在 PostgreSQL 数据库中触发一个长时间运行的 SQL 函数。有时需要终止计算以解除对服务器上其他查询的阻塞。但是,如果手动中止作业,尽管psql 命令被终止,SQL 函数仍会在服务器上保持运行(在postgresql 进程内)。

我发现psql 需要被 SIGINT 中止才能正确取消查询,但 Jenkins 显然会将 SIGTERM 发送到作业执行中产生的所有进程。

我尝试在作业脚本中捕获 TERM 信号并将 SIGINT 发送到在后台运行的 psql,但 psql 仍然首先收到 SIGTERM 并在不停止查询的情况下完成。

根据this,Jenkins 会杀死脚本的整个进程组,但在单独的进程组 (set -m) 中启动 psql 也无济于事。

有什么方法可以在 Jenkins 作业中止时优雅地停止 psql 查询?

【问题讨论】:

【参考方案1】:

我最终使用了这个解决方法。为 psql 进程添加陷阱 SIGTERM 信号,并在清理过程中用正常的 SIGTERM 杀死正在运行的进程:

function clean() 
    echo "Interrupted: psql #$1" >&2
    kill -SIGINT $1
    wait $1
    echo "psql ended" >&2


psql -c 'select pg_sleep(10)' &
pid=$!

trap "clean $pid" SIGTERM

然后通过 SSH Publisher 构建步骤(Publish Over SSH Plugin)运行脚本。必须设置两个复选框才能使作业正常工作:

    在传输块中的 pty 中执行 -> 高级按钮 如果服务器块中出现错误,则构建失败 -> 高级按钮

【讨论】:

以上是关于中止时如何使用 SIGINT 而不是 SIGTERM 终止 Jenkins 作业中的 psql 进程?的主要内容,如果未能解决你的问题,请参考以下文章

如何中止对 sigwaitinfo 的调用?

如何中止获取请求?

如果段错误不可恢复,为啥称为错误(而不是中止)?

你如何干净地中止一个 Delphi 程序?

程序中止或退出时是不是释放 pthread_mutex_t*?

如何仅在 C 中将 SIGINT 发送到后台进程