diff --git a/lib/MySQL_Logger.cpp b/lib/MySQL_Logger.cpp index 9a50442a03..328bcf5190 100644 --- a/lib/MySQL_Logger.cpp +++ b/lib/MySQL_Logger.cpp @@ -1261,14 +1261,25 @@ void MySQL_Logger::audit_flush_log_unlocked() { } void MySQL_Logger::events_open_log_unlocked() { - events.log_file_id=events_find_next_id(); - if (events.log_file_id!=0) { - events.log_file_id=events_find_next_id()+1; - } else { - events.log_file_id++; + // Check if this is a special device file like /dev/stdout or /dev/stderr + bool is_special_device = (strcmp(events.base_filename, "/dev/stdout") == 0 || + strcmp(events.base_filename, "/dev/stderr") == 0); + + if (!is_special_device) { + events.log_file_id=events_find_next_id(); + if (events.log_file_id!=0) { + events.log_file_id=events_find_next_id()+1; + } else { + events.log_file_id++; + } } + char *filen=NULL; - if (events.base_filename[0]=='/') { // absolute path + if (is_special_device) { + // For special device files, use the filename directly without rotation + filen=(char *)malloc(strlen(events.base_filename)+1); + strcpy(filen, events.base_filename); + } else if (events.base_filename[0]=='/') { // absolute path filen=(char *)malloc(strlen(events.base_filename)+11); sprintf(filen,"%s.%08d",events.base_filename,events.log_file_id); } else { // relative path @@ -1310,14 +1321,25 @@ void MySQL_Logger::events_open_log_unlocked() { }; void MySQL_Logger::audit_open_log_unlocked() { - audit.log_file_id=audit_find_next_id(); - if (audit.log_file_id!=0) { - audit.log_file_id=audit_find_next_id()+1; - } else { - audit.log_file_id++; + // Check if this is a special device file like /dev/stdout or /dev/stderr + bool is_special_device = (strcmp(audit.base_filename, "/dev/stdout") == 0 || + strcmp(audit.base_filename, "/dev/stderr") == 0); + + if (!is_special_device) { + audit.log_file_id=audit_find_next_id(); + if (audit.log_file_id!=0) { + audit.log_file_id=audit_find_next_id()+1; + } else { + audit.log_file_id++; + } } + char *filen=NULL; - if (audit.base_filename[0]=='/') { // absolute path + if (is_special_device) { + // For special device files, use the filename directly without rotation + filen=(char *)malloc(strlen(audit.base_filename)+1); + strcpy(filen, audit.base_filename); + } else if (audit.base_filename[0]=='/') { // absolute path filen=(char *)malloc(strlen(audit.base_filename)+11); sprintf(filen,"%s.%08d",audit.base_filename,audit.log_file_id); } else { // relative path diff --git a/test/tap/tests/test_logger_special_devices-t.cpp b/test/tap/tests/test_logger_special_devices-t.cpp new file mode 100644 index 0000000000..ecffa4f077 --- /dev/null +++ b/test/tap/tests/test_logger_special_devices-t.cpp @@ -0,0 +1,92 @@ +/** + * @file test_logger_special_devices-t.cpp + * @brief Tests for MySQL_Logger special device file handling (/dev/stdout, /dev/stderr) + * @details This test ensures that eventslog_filename and auditlog_filename can be set to + * special device files like /dev/stdout and /dev/stderr without rotation errors. + */ + +#include +#include +#include +#include +#include +#include + +#include "mysql.h" +#include "mysqld_error.h" +#include "proxysql.h" +#include "cpp-dotenv/dotenv.h" + +#include "tap.h" +#include "command_line.h" +#include "utils.h" + +int main(int argc, char** argv) { + CommandLine cl; + + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + MYSQL* proxysql_admin = mysql_init(NULL); + + if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return -1; + } + + plan(6); + + // Test 1: Set eventslog_filename to /dev/stdout (should not fail) + { + MYSQL_QUERY(proxysql_admin, "SET mysql-eventslog_filename='/dev/stdout'"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + ok(true, "Successfully set eventslog_filename to /dev/stdout"); + } + + // Test 2: Set eventslog_filename to /dev/stderr (should not fail) + { + MYSQL_QUERY(proxysql_admin, "SET mysql-eventslog_filename='/dev/stderr'"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + ok(true, "Successfully set eventslog_filename to /dev/stderr"); + } + + // Test 3: Set auditlog_filename to /dev/stdout (should not fail) + { + MYSQL_QUERY(proxysql_admin, "SET mysql-auditlog_filename='/dev/stdout'"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + ok(true, "Successfully set auditlog_filename to /dev/stdout"); + } + + // Test 4: Set auditlog_filename to /dev/stderr (should not fail) + { + MYSQL_QUERY(proxysql_admin, "SET mysql-auditlog_filename='/dev/stderr'"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + ok(true, "Successfully set auditlog_filename to /dev/stderr"); + } + + // Test 5: FLUSH LOGS with special device should work + { + MYSQL_QUERY(proxysql_admin, "SET mysql-eventslog_filename='/dev/stdout'"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + MYSQL_QUERY(proxysql_admin, "PROXYSQL FLUSH LOGS"); + ok(true, "FLUSH LOGS works with /dev/stdout"); + } + + // Test 6: Verify we can switch back to regular file + { + MYSQL_QUERY(proxysql_admin, "SET mysql-eventslog_filename='/tmp/test_events.log'"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + ok(true, "Successfully switched back to regular file"); + } + + // Cleanup + MYSQL_QUERY(proxysql_admin, "SET mysql-eventslog_filename=''"); + MYSQL_QUERY(proxysql_admin, "SET mysql-auditlog_filename=''"); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + + mysql_close(proxysql_admin); + + return exit_status(); +} \ No newline at end of file