分离子终端的stdout和stderr
This commit is contained in:
parent
3f49fdedb1
commit
0b5815897d
|
|
@ -23,7 +23,8 @@
|
||||||
"init_cleanup.h": "c",
|
"init_cleanup.h": "c",
|
||||||
"stdbool.h": "c",
|
"stdbool.h": "c",
|
||||||
"stat.h": "c",
|
"stat.h": "c",
|
||||||
"debug.h": "c"
|
"debug.h": "c",
|
||||||
|
"types.h": "c"
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "disabled"
|
"C_Cpp.errorSquiggles": "disabled"
|
||||||
}
|
}
|
||||||
Binary file not shown.
BIN
build/pty_dup.o
BIN
build/pty_dup.o
Binary file not shown.
Binary file not shown.
|
|
@ -100,3 +100,20 @@ arg[1]: --color=auto
|
||||||
arg[0]: pip
|
arg[0]: pip
|
||||||
arg[1]: install
|
arg[1]: install
|
||||||
arg[2]: torch
|
arg[2]: torch
|
||||||
|
[Sat Apr 12 10:41:47 2025
|
||||||
|
] Command: /home/qcqcqc/miniconda3/bin/pip
|
||||||
|
arg[0]: pip
|
||||||
|
arg[1]: install
|
||||||
|
arg[2]: torch
|
||||||
|
[Sat Apr 12 10:41:56 2025
|
||||||
|
] Command: /home/qcqcqc/miniconda3/bin/pip
|
||||||
|
arg[0]: pip
|
||||||
|
arg[1]: install
|
||||||
|
arg[2]: torch
|
||||||
|
arg[3]: abglpkhnjokb
|
||||||
|
[Sat Apr 12 10:43:13 2025
|
||||||
|
] Command: /home/qcqcqc/miniconda3/bin/pip
|
||||||
|
arg[0]: pip
|
||||||
|
arg[1]: install
|
||||||
|
arg[2]: torch
|
||||||
|
arg[3]: abglpkhnjokb
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
欢迎使用北冥云计算服务!
|
||||||
|
[DEBUG][PID 2277570] src/pty_dup.c:95:dupIO(): forkpty result is: 0.
|
||||||
|
[DEBUG][PID 2277570] src/pty_dup.c:103:dupIO(): Child process ready.
|
||||||
|
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
Requirement already satisfied: torch in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (2.6.0)
|
||||||
|
Requirement already satisfied: filelock in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (3.18.0)
|
||||||
|
Requirement already satisfied: typing-extensions>=4.10.0 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (4.12.2)
|
||||||
|
Requirement already satisfied: networkx in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (3.4.2)
|
||||||
|
Requirement already satisfied: jinja2 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (3.1.6)
|
||||||
|
Requirement already satisfied: fsspec in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (2025.3.2)
|
||||||
|
Requirement already satisfied: nvidia-cuda-nvrtc-cu12==12.4.127 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.4.127)
|
||||||
|
Requirement already satisfied: nvidia-cuda-runtime-cu12==12.4.127 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.4.127)
|
||||||
|
Requirement already satisfied: nvidia-cuda-cupti-cu12==12.4.127 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.4.127)
|
||||||
|
Requirement already satisfied: nvidia-cudnn-cu12==9.1.0.70 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (9.1.0.70)
|
||||||
|
Requirement already satisfied: nvidia-cublas-cu12==12.4.5.8 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.4.5.8)
|
||||||
|
Requirement already satisfied: nvidia-cufft-cu12==11.2.1.3 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (11.2.1.3)
|
||||||
|
Requirement already satisfied: nvidia-curand-cu12==10.3.5.147 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (10.3.5.147)
|
||||||
|
Requirement already satisfied: nvidia-cusolver-cu12==11.6.1.9 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (11.6.1.9)
|
||||||
|
Requirement already satisfied: nvidia-cusparse-cu12==12.3.1.170 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.3.1.170)
|
||||||
|
Requirement already satisfied: nvidia-cusparselt-cu12==0.6.2 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (0.6.2)
|
||||||
|
Requirement already satisfied: nvidia-nccl-cu12==2.21.5 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (2.21.5)
|
||||||
|
Requirement already satisfied: nvidia-nvtx-cu12==12.4.127 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.4.127)
|
||||||
|
Requirement already satisfied: nvidia-nvjitlink-cu12==12.4.127 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (12.4.127)
|
||||||
|
Requirement already satisfied: triton==3.2.0 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (3.2.0)
|
||||||
|
Requirement already satisfied: setuptools in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (75.8.0)
|
||||||
|
Requirement already satisfied: sympy==1.13.1 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from torch) (1.13.1)
|
||||||
|
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from sympy==1.13.1->torch) (1.3.0)
|
||||||
|
Requirement already satisfied: MarkupSafe>=2.0 in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (from jinja2->torch) (3.0.2)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
ERROR: Could not find a version that satisfies the requirement abglpkhnjokb (from versions: none)
|
||||||
|
ERROR: No matching distribution found for abglpkhnjokb
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
欢迎使用北冥云计算服务!
|
||||||
|
[DEBUG][PID 2277714] src/pty_dup.c:95:dupIO(): forkpty result is: 0.
|
||||||
|
[DEBUG][PID 2277714] src/pty_dup.c:103:dupIO(): Child process ready.
|
||||||
|
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
Requirement already satisfied: torch in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (2.6.0)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
ERROR: Could not find a version that satisfies the requirement abglpkhnjokb (from versions: none)
|
||||||
|
ERROR: No matching distribution found for abglpkhnjokb
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
欢迎使用北冥云计算服务!
|
||||||
|
[DEBUG][PID 2278618] src/pty_dup.c:95:dupIO(): forkpty result is: 0.
|
||||||
|
[DEBUG][PID 2278618] src/pty_dup.c:103:dupIO(): Child process ready.
|
||||||
|
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
Requirement already satisfied: torch in /home/qcqcqc/miniconda3/lib/python3.12/site-packages (2.6.0)
|
||||||
|
|
@ -35,6 +35,17 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_PATH_LEN 256
|
||||||
|
|
||||||
|
#define GET_LOG_FILE(c_pid, is_stdout) ({ \
|
||||||
|
static char filename[MAX_PATH_LEN]; \
|
||||||
|
snprintf(filename, MAX_PATH_LEN, "%s.%ld.%s", \
|
||||||
|
LOG_OUT_FILE, \
|
||||||
|
(long)c_pid, \
|
||||||
|
(is_stdout) ? "stdout" : "stderr"); \
|
||||||
|
filename; \
|
||||||
|
})
|
||||||
|
|
||||||
#define ANSI_COLOR_RED "\033[31m"
|
#define ANSI_COLOR_RED "\033[31m"
|
||||||
#define ANSI_COLOR_YELLOW "\033[33m"
|
#define ANSI_COLOR_YELLOW "\033[33m"
|
||||||
#define ANSI_COLOR_RESET "\033[0m"
|
#define ANSI_COLOR_RESET "\033[0m"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "signal_handlers.h"
|
#include "signal_handlers.h"
|
||||||
#include "terminal_utils.h"
|
#include "terminal_utils.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
FILE *log_file = NULL;
|
FILE *log_file = NULL;
|
||||||
pid_t child_pid;
|
pid_t child_pid;
|
||||||
|
|
@ -22,15 +23,66 @@ void print_child_status() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void dupIO() {
|
||||||
|
// pid_t pid;
|
||||||
|
// int master;
|
||||||
|
// struct termios term;
|
||||||
|
// struct winsize win;
|
||||||
|
|
||||||
|
// DEBUG_LOG("Setup termios....");
|
||||||
|
// setup_termios(&term);
|
||||||
|
|
||||||
|
// signal(SIGINT, handle_sigint);
|
||||||
|
// signal(SIGCHLD, handle_sigchld);
|
||||||
|
|
||||||
|
// if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) < 0) {
|
||||||
|
// perror("ioctl TIOCGWINSZ failed");
|
||||||
|
// exit(1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pid = forkpty(&master, NULL, &term, &win);
|
||||||
|
// DEBUG_LOG("forkpty result is: %d.", pid);
|
||||||
|
// child_pid = pid;
|
||||||
|
|
||||||
|
// if (pid < 0) {
|
||||||
|
// perror("forkpty failed");
|
||||||
|
// exit(1);
|
||||||
|
// } else if (pid == 0) {
|
||||||
|
// DEBUG_LOG("Child process ready.");
|
||||||
|
// signal(SIGINT, SIG_DFL);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// DEBUG_LOG("Ready to handle IO");
|
||||||
|
// handle_io(master);
|
||||||
|
// close(master);
|
||||||
|
|
||||||
|
// if (WIFEXITED(child_status)) {
|
||||||
|
// exit(WEXITSTATUS(child_status));
|
||||||
|
// } else if (WIFSIGNALED(child_status)) {
|
||||||
|
// exit(128 + WTERMSIG(child_status));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// exit(1);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
void dupIO() {
|
void dupIO() {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int master;
|
int master;
|
||||||
|
int stderr_pipe[2];
|
||||||
struct termios term;
|
struct termios term;
|
||||||
struct winsize win;
|
struct winsize win;
|
||||||
|
|
||||||
DEBUG_LOG("Setup termios....");
|
DEBUG_LOG("Setup termios....");
|
||||||
setup_termios(&term);
|
setup_termios(&term);
|
||||||
|
|
||||||
|
// 创建stderr的pipe
|
||||||
|
if (pipe(stderr_pipe) < 0) {
|
||||||
|
perror("pipe failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
signal(SIGINT, handle_sigint);
|
signal(SIGINT, handle_sigint);
|
||||||
signal(SIGCHLD, handle_sigchld);
|
signal(SIGCHLD, handle_sigchld);
|
||||||
|
|
||||||
|
|
@ -47,14 +99,35 @@ void dupIO() {
|
||||||
perror("forkpty failed");
|
perror("forkpty failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
|
// 子进程
|
||||||
DEBUG_LOG("Child process ready.");
|
DEBUG_LOG("Child process ready.");
|
||||||
signal(SIGINT, SIG_DFL);
|
signal(SIGINT, SIG_DFL);
|
||||||
|
|
||||||
|
// 关闭pipe读端
|
||||||
|
close(stderr_pipe[0]);
|
||||||
|
|
||||||
|
// 重定向stderr到pipe写端
|
||||||
|
if (dup2(stderr_pipe[1], STDERR_FILENO) < 0) {
|
||||||
|
perror("dup2 failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
close(stderr_pipe[1]);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 父进程
|
||||||
|
// 关闭pipe写端
|
||||||
|
close(stderr_pipe[1]);
|
||||||
|
|
||||||
|
// 设置pipe读端为非阻塞
|
||||||
|
fcntl(stderr_pipe[0], F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
DEBUG_LOG("Ready to handle IO");
|
DEBUG_LOG("Ready to handle IO");
|
||||||
handle_io(master);
|
handle_io(master, stderr_pipe[0], child_pid); // 需要修改handle_io函数签名,传入stderr_pipe读端
|
||||||
|
|
||||||
close(master);
|
close(master);
|
||||||
|
close(stderr_pipe[0]);
|
||||||
|
|
||||||
if (WIFEXITED(child_status)) {
|
if (WIFEXITED(child_status)) {
|
||||||
exit(WEXITSTATUS(child_status));
|
exit(WEXITSTATUS(child_status));
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,10 @@ void setup_termios(struct termios *term) {
|
||||||
cfsetospeed(term, B38400);
|
cfsetospeed(term, B38400);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_io(int master_fd) {
|
void handle_io(int master_fd, int stderr_fd, pid_t c_pid) {
|
||||||
struct termios orig_term, raw_term;
|
struct termios orig_term, raw_term;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
struct pollfd fds[3]; // 增加一个pollfd用于stderr
|
||||||
|
|
||||||
// 保存原始终端设置
|
// 保存原始终端设置
|
||||||
DEBUG_LOG("Saving original config.");
|
DEBUG_LOG("Saving original config.");
|
||||||
|
|
@ -57,9 +59,6 @@ void handle_io(int master_fd) {
|
||||||
cfmakeraw(&raw_term);
|
cfmakeraw(&raw_term);
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &raw_term);
|
tcsetattr(STDIN_FILENO, TCSANOW, &raw_term);
|
||||||
|
|
||||||
char buffer[BUFFER_SIZE];
|
|
||||||
struct pollfd fds[2];
|
|
||||||
|
|
||||||
// 设置非阻塞模式
|
// 设置非阻塞模式
|
||||||
fcntl(master_fd, F_SETFL, O_NONBLOCK);
|
fcntl(master_fd, F_SETFL, O_NONBLOCK);
|
||||||
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
||||||
|
|
@ -70,16 +69,24 @@ void handle_io(int master_fd) {
|
||||||
fds[1].fd = master_fd;
|
fds[1].fd = master_fd;
|
||||||
fds[1].events = POLLIN;
|
fds[1].events = POLLIN;
|
||||||
|
|
||||||
// 打开日志文件(以追加写模式)
|
fds[2].fd = stderr_fd; // 新增stderr的fd
|
||||||
int log_fd = open(LOG_OUT_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
fds[2].events = POLLIN;
|
||||||
if (log_fd == -1) {
|
|
||||||
|
// 打开两个日志文件
|
||||||
|
// 获取stderr日志文件名
|
||||||
|
const char *stdout_log = GET_LOG_FILE(c_pid, 1);
|
||||||
|
const char *stderr_log = GET_LOG_FILE(c_pid, 0);
|
||||||
|
int stdout_log_fd = open(stdout_log, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||||
|
int stderr_log_fd = open(stderr_log, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
||||||
|
|
||||||
|
if (stdout_log_fd == -1 || stderr_log_fd == -1) {
|
||||||
perror("Failed to open log file");
|
perror("Failed to open log file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
DEBUG_LOG("poll.....");
|
DEBUG_LOG("poll.....");
|
||||||
int ret = poll(fds, 2, 100); // 设置超时以便定期检查子进程状态
|
int ret = poll(fds, 3, 100); // 修改为监控3个fd
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
perror("poll failed");
|
perror("poll failed");
|
||||||
|
|
@ -89,12 +96,39 @@ void handle_io(int master_fd) {
|
||||||
// 优先处理 PTY 输出,确保缓冲区中的数据被完全读出
|
// 优先处理 PTY 输出,确保缓冲区中的数据被完全读出
|
||||||
DEBUG_LOG("Handling pty output...");
|
DEBUG_LOG("Handling pty output...");
|
||||||
if (fds[1].revents & (POLLIN | POLLHUP)) {
|
if (fds[1].revents & (POLLIN | POLLHUP)) {
|
||||||
DEBUG_LOG("Read from: %d \n\r", master_fd);
|
|
||||||
ssize_t n = read(master_fd, buffer, sizeof(buffer));
|
ssize_t n = read(master_fd, buffer, sizeof(buffer));
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
// 直接写入,让终端自己处理控制序列
|
// 直接写入,让终端自己处理控制序列
|
||||||
write(STDOUT_FILENO, buffer, n);
|
write(STDOUT_FILENO, buffer, n);
|
||||||
write(log_fd, buffer, n);
|
write(stdout_log_fd, buffer, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理stderr
|
||||||
|
// 处理stderr
|
||||||
|
DEBUG_LOG("Handling stderr output...");
|
||||||
|
if (fds[2].revents & (POLLIN | POLLHUP)) {
|
||||||
|
ssize_t n = read(stderr_fd, buffer, sizeof(buffer));
|
||||||
|
if (n > 0) {
|
||||||
|
// 先保存当前光标位置
|
||||||
|
// write(STDERR_FILENO, "\033[s", 3); // 保存光标位置
|
||||||
|
|
||||||
|
// 移动到最后一行
|
||||||
|
write(STDERR_FILENO, "\033[999B", 6); // 移动到底部
|
||||||
|
write(STDERR_FILENO, "\r", 1); // 回到行首
|
||||||
|
|
||||||
|
// 输出带颜色的错误信息
|
||||||
|
write(STDERR_FILENO, "\033[31m", 5); // 设置红色
|
||||||
|
write(STDERR_FILENO, buffer, n);
|
||||||
|
write(STDERR_FILENO, "\033[0m", 4); // 重置颜色
|
||||||
|
|
||||||
|
// 恢复光标位置
|
||||||
|
// write(STDERR_FILENO, "\033[u", 3); // 恢复光标位置
|
||||||
|
write(STDERR_FILENO, "\033[999B", 6); // 移动到底部
|
||||||
|
write(STDERR_FILENO, "\r", 1); // 回到行首
|
||||||
|
|
||||||
|
// 写入日志
|
||||||
|
write(stderr_log_fd, buffer, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,8 +154,8 @@ void handle_io(int master_fd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_fd >= 0) {
|
if (stdout_log_fd >= 0) {
|
||||||
written = write(log_fd, buffer, n);
|
written = write(stdout_log_fd, buffer, n);
|
||||||
if (written < 0) {
|
if (written < 0) {
|
||||||
perror("write to log failed");
|
perror("write to log failed");
|
||||||
break;
|
break;
|
||||||
|
|
@ -152,9 +186,14 @@ void handle_io(int master_fd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_LOG("Try to close log_fd: %d", log_fd);
|
DEBUG_LOG("Try to close stdout_log_fd: %d", stdout_log_fd);
|
||||||
if (log_fd > 0) {
|
if (stdout_log_fd > 0) {
|
||||||
close(log_fd);
|
close(stdout_log_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG("Try to close stderr_log_fd: %d", stderr_log_fd);
|
||||||
|
if (stderr_log_fd > 0) {
|
||||||
|
close(stderr_log_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保输出缓冲区被刷新
|
// 确保输出缓冲区被刷新
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,6 @@
|
||||||
#define TERMINAL_UTILS_H
|
#define TERMINAL_UTILS_H
|
||||||
|
|
||||||
void setup_termios(struct termios *term);
|
void setup_termios(struct termios *term);
|
||||||
void handle_io(int master_fd);
|
void handle_io(int master_fd, int stderr_fd, pid_t c_pid) ;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue