我希望能够从使用与 Prometheus 不同的用户运行的 CI 工具向 Prometheus 进程发送 SIGHUP 信号。假设 CI 使用gitlab-runner
用户,Prometheus 使用prometheus
用户。我认为我可以通过以下步骤向 Prometheus 进程发送 SIGHUP 信号:
- 创建一个执行命令的简单 shell 脚本
kill
:
$ cat `which promhup`
kill -HUP $(pgrep prometheus)
- 更改此脚本的所有权并设置
setuid
此文件的位:
chown prometheus promhup
chmod +x promhup
chmod u+s promhup
然后,我期望如果我简单地运行promhup
,它就可以向 Prometheus 进程发送所需的信号。但是,我收到以下错误:
/usr/bin/promhup: line 1: kill: (602) - Operation not permitted
权限现在如下所示:
$ ls -l `which promhup`
-rwsr-xr-x 1 prometheus root 51 Jan 27 19:36 /usr/bin/promhup
我做错了什么?如何在不授予sudo
CI 用户访问权限的情况下实现此目的?
答案1
出于安全原因,Linux 忽略脚本/解释可执行文件(以 #! 开头的脚本)上的 setuid 位。
作为一种 hack 解决方案,您可以尝试使用以下方法从脚本中编译出一个简单的二进制文件https://github.com/neurobin/shc并将其设置为:
sudo add-apt-repository ppa:neurobin/ppa
sudo apt-get install shc
shc -f my_promhup_script -o promhup
sudo mv promhup /usr/bin/
尽管我更愿意选择 sudo 选项 - 但这就是它的设计目的。
更新:
对于 sudo 选项,您可以向 sudoers 添加类似这样的内容:
gitlab-runner ALL = (ALL) ALL
gitlab-runner ALL = (root) NOPASSWD: /usr/bin/promhup
这将使你的 sudo 不仅在为你的脚本询问密码,同时为其他脚本询问密码
答案2
@OWGrant 的回答的第一段给出了解决这个问题的很好的观点:
出于安全原因,Linux 忽略脚本/解释可执行文件(以 #! 开头的脚本)上的 setuid 位。
它启发我用 C 语言编写了一个等效的程序,它可以工作:
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
FILE *fp;
char pid[10];
fp = popen("/usr/bin/pgrep prometheus", "r");
if (fp == NULL)
exit(1);
fgets(pid, sizeof(pid), fp);
char* ptr = pid;
while(ptr) {
if(*ptr == '\n') {
*ptr = '\0';
break;
}
ptr++;
}
pclose(fp);
char* args[] = {"/usr/bin/kill", "-HUP", pid, NULL};
execvp(args[0], args);
return 0;
}
用法如下:
gcc promhup.c -o promhup
chmod +x promhup
chown prometheus promhup
chmod u+s promhup
sudo mv promhup /usr/bin
然后运行一个简单的promhup
命令就会SIGHUP
向 Prometheus 进程发送一个信号。