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
|
BUILD_DIR = build
|
||||||
SRC_DIR = src
|
SRC_DIR = src
|
||||||
|
TESTS_DIR = tests
|
||||||
|
|
||||||
SRC = $(wildcard $(SRC_DIR)/*.c)
|
SRC = $(wildcard $(SRC_DIR)/*.c)
|
||||||
SRC := $(filter-out $(SRC_DIR)/hook_write.c, $(SRC)) # 排除 hook_write.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_OBJ = $(BUILD_DIR)/hook_write.o
|
||||||
HOOK_TARGET = $(BUILD_DIR)/$(HOOK_NAME)
|
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
|
# 如果需要开启 debug,只需执行 make DEBUG=1
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
CFLAGS += -DDEBUG -g
|
CFLAGS += -DDEBUG -g
|
||||||
|
|
@ -34,10 +40,12 @@ ifeq ($(NO_CONFIG_CHECK),1)
|
||||||
CFLAGS += -DNO_CONFIG_CHECK
|
CFLAGS += -DNO_CONFIG_CHECK
|
||||||
endif
|
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)
|
all: pre_build $(TARGET) $(HOOK_TARGET)
|
||||||
|
|
||||||
|
test_client: pre_build $(TEST_CLIENT)
|
||||||
|
|
||||||
pre_build:
|
pre_build:
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
@echo "Building with debug flags..."
|
@echo "Building with debug flags..."
|
||||||
|
|
@ -65,6 +73,10 @@ $(HOOK_OBJ): $(HOOK_SRC)
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
$(CC) $(CFLAGS) -Wno-error=unused-result -c $< -o $@
|
$(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:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
#include <linux/limits.h> // for PATH_MAX
|
#include <linux/limits.h> // for PATH_MAX
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#define SOCKET_PATH "/etc/exec_hook/exec.sock"
|
#define SOCKET_PATH "/var/run/bash-smart.sock"
|
||||||
#define MAX_BUF_SIZE 4096
|
#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