tcsetpgrp failed重新编译tini

本文详细解析了在启动SparkOperator时遇到的tini源码错误问题,通过深入研究tini源码,找到了解决方案并成功修复了错误。文章最后总结了如何替换镜像中的tini以解决问题。

1 Overview

在启动 Spark Operator 的时候出现了一个意想不到的问题。

[root@sholdmix01node1 /data/runzhliu/spark]# kubectl log  -n kube-system spark-sparkoperator-86f6c889cd-ggbmc
log is DEPRECATED and will be removed in a future version. Use logs instead.
++ id -u
+ myuid=185
++ id -g
+ mygid=0
+ set +e
++ getent passwd 185
+ uidentry=
+ set -e
+ echo 185
185
0

+ echo 0
+ echo
+ [[ -z '' ]]
+ [[ -w /etc/passwd ]]
+ echo '185:x:185:0:anonymous uid:/opt/spark:/bin/false'
+ exec /usr/bin/tini -s -- /usr/bin/spark-operator
[FATAL tini (9)] tcsetpgrp failed: Permission denied

因为本人在腾讯,这是因为开发环境的 tlinux 的问题,导致 tini 出错了。寻找了很久,也没找到 特别有效的信息,于是查看一下 tini 的源码,看看 这个 错误是如何产生的。

2 tini 源码

大家可以看到这行代码,错误信息就是由他打印的。

优化以下代码,并测试stop功能。#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <signal.h> #include <ctype.h> #define MAX_INPUT 1024 #define MAX_ARGS 64 // 全局变量记录当前前台进程PID pid_t foreground_pid = 0; // 信号处理器 //设置sigint_handler函数为终止当前的前台进程 void sigint_handler(int sig) { if (foreground_pid != 0) { kill(foreground_pid, SIGKILL); printf("\n"); } } // 设置sigtstp_handler函数为暂停当前的前台进程 void sigtstp_handler(int sig) { if (foreground_pid != 0) { kill(foreground_pid, SIGTSTP); printf("\n[%d] stopped\n", foreground_pid); foreground_pid = 0; } } // 解析输入命令 //将命令行输入input字符串分割成args数组,并返回args数组的长度argc,argc通常会被用来 //调用execvp函数执行外部命令。 int parse_command(char *input, char **args) { int argc = 0; char *token = strtok(input, " \t\n"); while (token != NULL && argc < MAX_ARGS - 1) { args[argc++] = token; token = strtok(NULL, " \t\n"); } args[argc] = NULL; // execvp要求以NULL结尾 return argc; } // 执行外部命令bckground=0表示前台执行,background!=表示后台执行 void execute_external(char **args, int background) { int pipefd[2]; if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid < 0) { perror("fork"); return; } else if (pid == 0) { // 子进程执行命令 close(pipefd[0]); dup2(pipefd[1], STDOUT_FILENO); close(pipefd[1]); if (execvp(args[0], args) < 0) { perror("execvp"); exit(EXIT_FAILURE); } } else { // 父进程处理 if (!background) { printf("前台进程[%d]\n", pid); foreground_pid = pid; close(pipefd[1]); char buf[1024]; ssize_t count; while ((count = read(pipefd[0], buf, sizeof(buf)-1)) > 0) { buf[count] = '\0'; printf("%s", buf); } close(pipefd[0]); int status; waitpid(pid, &status, 0); foreground_pid = 0; } else { printf("后台进程[%d]\n", pid); close(pipefd[0]); close(pipefd[1]); waitpid(pid, NULL, 0); } } } // 内置命令处理 int handle_builtin(char **args, int argc) { if (strcmp(args[0], "exit") == 0) { exit(EXIT_SUCCESS); } else if (strcmp(args[0], "stop") == 0 && argc > 1) { pid_t pid = atoi(args[1]); if (kill(pid, SIGTERM) == 0) { printf("Stopped process %d\n", pid); } else { perror("kill"); } return 1; } return 0; // 不是内置命令 } int main() { char input[MAX_INPUT]; char *args[MAX_ARGS]; // 设置信号处理器 //SIGINT(也就是ctrl+c)绑定函数sigint_handler(终止当前前台进程) //SIGTSTP(也就是ctrl+z)绑定函数sigtstp_handler(暂停当前前台进程) signal(SIGINT, sigint_handler); signal(SIGTSTP, sigtstp_handler); while (1) { printf("mysh> "); fflush(stdout); // 读取输入 ctrl+d退出 if (fgets(input, MAX_INPUT, stdin) == NULL) { break; // 处理EOF (Ctrl+D) } // 解析命令 int argc = parse_command(input, args); if (argc == 0) continue; // 空命令 // 检查后台执行 int background = 0; if (argc > 0 && strcmp(args[argc-1], "&") == 0) { background = 1; args[argc-1] = NULL; argc--; } // 处理内置命令 if (handle_builtin(args, argc)) { continue; } // 执行外部命令 execute_external(args, background); } return EXIT_SUCCESS; }
08-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值