fix: 修复socket路径不一致,提供测试
This commit is contained in:
parent
8bcfa9e7cc
commit
21027a79be
14
Makefile
14
Makefile
|
|
@ -8,6 +8,7 @@ HOOK_NAME = hook_write.so
|
|||
|
||||
BUILD_DIR = build
|
||||
SRC_DIR = src
|
||||
TESTS_DIR = tests
|
||||
|
||||
SRC = $(wildcard $(SRC_DIR)/*.c)
|
||||
SRC := $(filter-out $(SRC_DIR)/hook_write.c, $(SRC)) # 排除 hook_write.c
|
||||
|
|
@ -19,6 +20,11 @@ HOOK_SRC = $(SRC_DIR)/hook_write.c
|
|||
HOOK_OBJ = $(BUILD_DIR)/hook_write.o
|
||||
HOOK_TARGET = $(BUILD_DIR)/$(HOOK_NAME)
|
||||
|
||||
# 测试客户端
|
||||
TEST_CLIENT = $(BUILD_DIR)/test_client
|
||||
TEST_CLIENT_SRC = $(TESTS_DIR)/test_client.c
|
||||
TEST_CLIENT_DEPS = $(BUILD_DIR)/client.o $(BUILD_DIR)/debug.o
|
||||
|
||||
# 如果需要开启 debug,只需执行 make DEBUG=1
|
||||
ifeq ($(DEBUG),1)
|
||||
CFLAGS += -DDEBUG -g
|
||||
|
|
@ -34,10 +40,12 @@ ifeq ($(NO_CONFIG_CHECK),1)
|
|||
CFLAGS += -DNO_CONFIG_CHECK
|
||||
endif
|
||||
|
||||
.PHONY: all clean debug hook rebuild pre_build
|
||||
.PHONY: all clean debug hook rebuild pre_build test_client
|
||||
|
||||
all: pre_build $(TARGET) $(HOOK_TARGET)
|
||||
|
||||
test_client: pre_build $(TEST_CLIENT)
|
||||
|
||||
pre_build:
|
||||
ifeq ($(DEBUG),1)
|
||||
@echo "Building with debug flags..."
|
||||
|
|
@ -65,6 +73,10 @@ $(HOOK_OBJ): $(HOOK_SRC)
|
|||
@mkdir -p $(BUILD_DIR)
|
||||
$(CC) $(CFLAGS) -Wno-error=unused-result -c $< -o $@
|
||||
|
||||
$(TEST_CLIENT): $(TEST_CLIENT_SRC) $(TEST_CLIENT_DEPS)
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
$(CC) -Wall -Wextra -o $@ $(TEST_CLIENT_SRC) $(TEST_CLIENT_DEPS)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#include <linux/limits.h> // for PATH_MAX
|
||||
#include <errno.h>
|
||||
|
||||
#define SOCKET_PATH "/etc/exec_hook/exec.sock"
|
||||
#define SOCKET_PATH "/var/run/bash-smart.sock"
|
||||
#define MAX_BUF_SIZE 4096
|
||||
|
||||
// 函数声明
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
pip is not installed. Please install pip to proceed.
|
||||
Installing required Python packages...
|
||||
Successfully installed click-8.1.3
|
||||
Finished installing Python packages.
|
||||
|
||||
This is a test error log file for testing the client functionality.
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# 客户端测试程序
|
||||
|
||||
## 编译
|
||||
|
||||
```bash
|
||||
make test_client
|
||||
```
|
||||
|
||||
## 运行测试
|
||||
|
||||
确保 Go 服务端正在运行,然后执行:
|
||||
|
||||
```bash
|
||||
./build/test_client /tmp/test_error.log
|
||||
```
|
||||
|
||||
## 测试说明
|
||||
|
||||
测试程序会:
|
||||
1. 连接到 Unix socket (`/etc/exec_hook/exec.sock`)
|
||||
2. 发送模拟的执行参数(命令、参数、环境变量、日志路径)
|
||||
3. 接收并显示服务端返回的所有消息
|
||||
4. 等待 socket 关闭后退出
|
||||
|
||||
## 创建测试日志文件
|
||||
|
||||
如果需要自定义测试日志内容:
|
||||
|
||||
```bash
|
||||
cat > /tmp/test_error.log << 'EOF'
|
||||
This is a test error log file.
|
||||
|
||||
Error: command not found
|
||||
Usage: test_script.py [OPTIONS]
|
||||
|
||||
Exit code: 127
|
||||
EOF
|
||||
```
|
||||
|
||||
## 预期行为
|
||||
|
||||
- 成功情况: 显示服务端返回的所有消息,最后输出 "✓ 测试成功"
|
||||
- 失败情况: 输出错误信息,返回非零退出码
|
||||
BIN
tests/a.out
BIN
tests/a.out
Binary file not shown.
BIN
tests/forkpty
BIN
tests/forkpty
Binary file not shown.
BIN
tests/makefault
BIN
tests/makefault
Binary file not shown.
|
|
@ -1,18 +0,0 @@
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -g
|
||||
|
||||
all: client-tests
|
||||
|
||||
client-tests: client-tests.o client.o
|
||||
$(CC) $(CFLAGS) -o client-tests client-tests.o client.o
|
||||
|
||||
client-tests.o: client-tests.c client.h
|
||||
$(CC) $(CFLAGS) -c client-tests.c
|
||||
|
||||
client.o: client.c client.h
|
||||
$(CC) $(CFLAGS) -c client.c
|
||||
|
||||
clean:
|
||||
rm -f client-tests *.o
|
||||
|
||||
.PHONY: all clean
|
||||
Binary file not shown.
|
|
@ -1,30 +0,0 @@
|
|||
#include "client.h"
|
||||
|
||||
int main() {
|
||||
// 测试参数
|
||||
const char *filename = "/usr/bin/ls";
|
||||
char *const argv[] = {
|
||||
"ls",
|
||||
"-l",
|
||||
"/home",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *const envp[] = {
|
||||
"PATH=/usr/local/bin:/usr/bin:/bin",
|
||||
"HOME=/home/user",
|
||||
"LANG=en_US.UTF-8",
|
||||
NULL
|
||||
};
|
||||
|
||||
// 调用socket发送函数
|
||||
int result = send_exec_params(filename, argv, envp, "./test.log");
|
||||
|
||||
if(result == 0) {
|
||||
printf("Parameters sent successfully\n");
|
||||
} else {
|
||||
printf("Failed to send parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
|
@ -1,181 +0,0 @@
|
|||
#include "client.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
// 读取完整消息
|
||||
ssize_t readMessage(int sock, char *buffer, size_t maxSize) {
|
||||
uint32_t messageLen;
|
||||
// 先读取消息长度
|
||||
if (read(sock, &messageLen, sizeof(messageLen)) != sizeof(messageLen)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 检查buffer大小是否足够
|
||||
if (messageLen >= maxSize) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 读取完整消息
|
||||
size_t totalRead = 0;
|
||||
while (totalRead < messageLen) {
|
||||
ssize_t n = read(sock, buffer + totalRead, messageLen - totalRead);
|
||||
if (n <= 0) return -1;
|
||||
totalRead += n;
|
||||
}
|
||||
buffer[messageLen] = '\0';
|
||||
return messageLen;
|
||||
}
|
||||
|
||||
int send_exec_params(const char *filename, char *const argv[],
|
||||
char *const envp[], const char *logPath) {
|
||||
char abs_path[PATH_MAX];
|
||||
char pwd[PATH_MAX];
|
||||
|
||||
// 获取当前工作目录
|
||||
if (getcwd(pwd, sizeof(pwd)) == NULL) {
|
||||
perror("getcwd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (logPath[0] != '/') { // 相对路径
|
||||
size_t pwd_len = strlen(pwd);
|
||||
size_t log_len = strlen(logPath);
|
||||
if (pwd_len + log_len + 2 > PATH_MAX) {
|
||||
errno = ENAMETOOLONG;
|
||||
perror("path too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(abs_path, pwd, PATH_MAX - 1);
|
||||
abs_path[PATH_MAX - 1] = '\0';
|
||||
strncat(abs_path, "/", PATH_MAX - strlen(abs_path) - 1);
|
||||
strncat(abs_path, logPath, PATH_MAX - strlen(abs_path) - 1);
|
||||
|
||||
char real_path[PATH_MAX];
|
||||
if (realpath(abs_path, real_path) == NULL) {
|
||||
perror("realpath");
|
||||
return -1;
|
||||
}
|
||||
strncpy(abs_path, real_path, PATH_MAX - 1);
|
||||
abs_path[PATH_MAX - 1] = '\0';
|
||||
} else {
|
||||
strncpy(abs_path, logPath, PATH_MAX - 1);
|
||||
abs_path[PATH_MAX - 1] = '\0';
|
||||
}
|
||||
|
||||
size_t path_len = strlen(abs_path);
|
||||
|
||||
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock == -1) {
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 设置TCP_NODELAY
|
||||
// int flag = 1;
|
||||
// setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
|
||||
|
||||
struct sockaddr_un addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
|
||||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
perror("connect");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 发送文件名
|
||||
size_t filename_len = strlen(filename);
|
||||
write(sock, &filename_len, sizeof(size_t));
|
||||
write(sock, filename, filename_len);
|
||||
|
||||
// 发送当前工作目录
|
||||
size_t pwd_len = strlen(pwd);
|
||||
write(sock, &pwd_len, sizeof(size_t));
|
||||
write(sock, pwd, pwd_len);
|
||||
|
||||
// 发送argv
|
||||
int argc = 0;
|
||||
while (argv[argc] != NULL) argc++;
|
||||
write(sock, &argc, sizeof(int));
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
size_t arg_len = strlen(argv[i]);
|
||||
write(sock, &arg_len, sizeof(size_t));
|
||||
write(sock, argv[i], arg_len);
|
||||
}
|
||||
|
||||
// 发送envp
|
||||
int envc = 0;
|
||||
while (envp[envc] != NULL) envc++;
|
||||
write(sock, &envc, sizeof(int));
|
||||
|
||||
for (int i = 0; i < envc; i++) {
|
||||
size_t env_len = strlen(envp[i]);
|
||||
write(sock, &env_len, sizeof(size_t));
|
||||
write(sock, envp[i], env_len);
|
||||
}
|
||||
|
||||
// 发送logPath
|
||||
write(sock, &path_len, sizeof(size_t));
|
||||
write(sock, abs_path, path_len);
|
||||
|
||||
// 接收服务器响应
|
||||
char buffer[BUFFER_SIZE];
|
||||
char display_buffer[BUFFER_SIZE];
|
||||
ssize_t bytes_read;
|
||||
int started = 0;
|
||||
|
||||
// 等待接收[sthttp]标记
|
||||
while (!started) {
|
||||
bytes_read = readMessage(sock, buffer, BUFFER_SIZE);
|
||||
if (bytes_read <= 0) {
|
||||
perror("Failed to read start marker");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strstr(buffer, "[sthttp]")) {
|
||||
started = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 持续读取消息直到收到[end]
|
||||
while (1) {
|
||||
bytes_read = readMessage(sock, buffer, BUFFER_SIZE);
|
||||
if (bytes_read <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strstr(buffer, "[end]")) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 处理[res]...[wait]消息
|
||||
char *res_start = strstr(buffer, "[res]");
|
||||
char *wait_end = strstr(buffer, "[wait]");
|
||||
|
||||
if (res_start && wait_end) {
|
||||
size_t content_len = wait_end - (res_start + strlen("[res]"));
|
||||
if (content_len < BUFFER_SIZE) {
|
||||
strncpy(display_buffer, res_start + strlen("[res]"), content_len);
|
||||
display_buffer[content_len] = '\0';
|
||||
printf("%s\n", display_buffer);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// exec_socket.h
|
||||
|
||||
#ifndef EXEC_SOCKET_H
|
||||
#define EXEC_SOCKET_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <linux/limits.h> // for PATH_MAX
|
||||
#include <errno.h>
|
||||
|
||||
#define SOCKET_PATH "/etc/exec_hook/exec.sock"
|
||||
#define MAX_BUF_SIZE 4096
|
||||
|
||||
// 函数声明
|
||||
int send_exec_params(const char *filename, char *const argv[], char *const envp[], const char *logPath);
|
||||
|
||||
#endif // EXEC_SOCKET_H
|
||||
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
我是一段标准错误输出
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#include "../src/client.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* 测试客户端 - 用于测试 send_exec_params 函数
|
||||
*
|
||||
* 用法:
|
||||
* ./test_client <log_file_path>
|
||||
*
|
||||
* 示例:
|
||||
* ./test_client /tmp/test_error.log
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "用法: %s <log_file_path>\n", argv[0]);
|
||||
fprintf(stderr, "示例: %s /tmp/test_error.log\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *log_path = argv[1];
|
||||
|
||||
// 模拟要执行的命令
|
||||
const char *filename = "/usr/bin/python3";
|
||||
|
||||
// 模拟命令行参数
|
||||
char *test_argv[] = {
|
||||
"python3",
|
||||
"test_script.py",
|
||||
"--arg1",
|
||||
"value1",
|
||||
NULL
|
||||
};
|
||||
|
||||
// 模拟环境变量
|
||||
char *test_envp[] = {
|
||||
"PATH=/usr/bin:/bin",
|
||||
"HOME=/home/test",
|
||||
"USER=test",
|
||||
"SHELL=/bin/bash",
|
||||
NULL
|
||||
};
|
||||
|
||||
printf("===== 客户端测试开始 =====\n");
|
||||
printf("socket地址:%s\n", SOCKET_PATH);
|
||||
printf("文件名: %s\n", filename);
|
||||
printf("日志路径: %s\n", log_path);
|
||||
printf("参数:\n");
|
||||
for (int i = 0; test_argv[i] != NULL; i++) {
|
||||
printf(" argv[%d]: %s\n", i, test_argv[i]);
|
||||
}
|
||||
printf("\n正在发送请求到服务端...\n\n");
|
||||
printf("--- 服务端响应 ---\n");
|
||||
|
||||
// 调用客户端函数
|
||||
int result = send_exec_params(filename, test_argv, test_envp, log_path);
|
||||
|
||||
printf("\n--- 响应结束 ---\n");
|
||||
|
||||
if (result == 0) {
|
||||
printf("\n✓ 测试成功\n");
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "\n✗ 测试失败: send_exec_params 返回 %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue