diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index e0d41ab90af..cbd797273c1 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -433,16 +433,18 @@
If canvas item redraw debugging is active, this will be the time the flash will last each time they redraw.
- If [code]true[/code], logs all output to files.
+ If [code]true[/code], logs all output and error messages to files. See also [member debug/file_logging/log_path], [member debug/file_logging/max_log_files], and [member application/run/flush_stdout_on_print].
Desktop override for [member debug/file_logging/enable_file_logging], as log files are not readily accessible on mobile/Web platforms.
Path at which to store log files for the project. Using a path under [code]user://[/code] is recommended.
+ This can be specified manually on the command line using the [code]--log-file <file>[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. If this command line argument is specified, log rotation is automatically disabled (see [member debug/file_logging/max_log_files]).
- Specifies the maximum number of log files allowed (used for rotation).
+ Specifies the maximum number of log files allowed (used for rotation). Set to [code]1[/code] to disable log file rotation.
+ If the [code]--log-file <file>[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url] is used, log rotation is always disabled.
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when an [code]assert[/code] call always evaluates to false.
diff --git a/main/main.cpp b/main/main.cpp
index dbe186d63ab..1e0869e7f54 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -172,6 +172,7 @@ static bool editor = false;
static bool project_manager = false;
static bool cmdline_tool = false;
static String locale;
+static String log_file;
static bool show_help = false;
static uint64_t quit_after = 0;
static OS::ProcessID editor_pid = 0;
@@ -450,7 +451,9 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --text-driver Text driver (Fonts, BiDi, shaping).\n");
OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n");
OS::get_singleton()->print(" --headless Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script.\n");
- OS::get_singleton()->print(" --write-movie Writes a video to the specified path (usually with .avi or .png extension).\n");
+ OS::get_singleton()->print(" --log-file Write output/error log to the specified path instead of the default location defined by the project.\n");
+ OS::get_singleton()->print(" path should be absolute or relative to the project directory.\n");
+ OS::get_singleton()->print(" --write-movie Write a video to the specified path (usually with .avi or .png extension).\n");
OS::get_singleton()->print(" --fixed-fps is forced when enabled, but it can be used to change movie FPS.\n");
OS::get_singleton()->print(" --disable-vsync can speed up movie writing but makes interaction more difficult.\n");
OS::get_singleton()->print(" --quit-after can be used to specify the number of frames to write.\n");
@@ -1165,6 +1168,15 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
audio_driver = NULL_AUDIO_DRIVER;
display_driver = NULL_DISPLAY_DRIVER;
+ } else if (I->get() == "--log-file") { // write to log file
+
+ if (I->next()) {
+ log_file = I->next()->get();
+ N = I->next()->next();
+ } else {
+ OS::get_singleton()->print("Missing log file path argument, aborting.\n");
+ goto error;
+ }
} else if (I->get() == "--profiling") { // enable profiling
use_debug_profiler = true;
@@ -1689,12 +1701,24 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF("debug/file_logging/log_path", "user://logs/godot.log");
GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/file_logging/max_log_files", PROPERTY_HINT_RANGE, "0,20,1,or_greater"), 5);
- if (!project_manager && !editor && FileAccess::get_create_func(FileAccess::ACCESS_USERDATA) &&
- GLOBAL_GET("debug/file_logging/enable_file_logging")) {
+ // If `--log-file` is used to override the log path, allow creating logs for the project manager or editor
+ // and even if file logging is disabled in the Project Settings.
+ // `--log-file` can be used with any path (including absolute paths outside the project folder),
+ // so check for filesystem access if it's used.
+ if (FileAccess::get_create_func(!log_file.is_empty() ? FileAccess::ACCESS_FILESYSTEM : FileAccess::ACCESS_USERDATA) &&
+ (!log_file.is_empty() || (!project_manager && !editor && GLOBAL_GET("debug/file_logging/enable_file_logging")))) {
// Don't create logs for the project manager as they would be written to
// the current working directory, which is inconvenient.
- String base_path = GLOBAL_GET("debug/file_logging/log_path");
- int max_files = GLOBAL_GET("debug/file_logging/max_log_files");
+ String base_path;
+ int max_files;
+ if (!log_file.is_empty()) {
+ base_path = log_file;
+ // Ensure log file name respects the specified override by disabling log rotation.
+ max_files = 1;
+ } else {
+ base_path = GLOBAL_GET("debug/file_logging/log_path");
+ max_files = GLOBAL_GET("debug/file_logging/max_log_files");
+ }
OS::get_singleton()->add_logger(memnew(RotatedFileLogger(base_path, max_files)));
}
diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion
index 490af0a8a5a..f65cf378705 100644
--- a/misc/dist/shell/_godot.zsh-completion
+++ b/misc/dist/shell/_godot.zsh-completion
@@ -51,7 +51,8 @@ _arguments \
'--text-driver[set the text driver]:text driver name' \
'--tablet-driver[set the pen tablet input driver]:tablet driver name' \
'--headless[enable headless mode (--display-driver headless --audio-driver Dummy), useful for servers and with --script]' \
- '--write-movie[writes a video to the specified path (usually with .avi or .png extension)]:path to output video file' \
+ '--log-file[write output/error log to the specified path instead of the default location defined by the project]:path to output log file' \
+ '--write-movie[write a video to the specified path (usually with .avi or .png extension)]:path to output video file' \
'(-f --fullscreen)'{-f,--fullscreen}'[request fullscreen mode]' \
'(-m --maximized)'{-m,--maximized}'[request a maximized window]' \
'(-w --windowed)'{-w,--windowed}'[request windowed mode]' \
diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion
index c78f0a1f336..63efa95c10d 100644
--- a/misc/dist/shell/godot.bash-completion
+++ b/misc/dist/shell/godot.bash-completion
@@ -54,6 +54,7 @@ _complete_godot_options() {
--text-driver
--tablet-driver
--headless
+--log-file
--write-movie
--fullscreen
--maximized
diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish
index fbfa7344f11..3f0675fcb2b 100644
--- a/misc/dist/shell/godot.fish
+++ b/misc/dist/shell/godot.fish
@@ -67,7 +67,8 @@ complete -c godot -l gpu-index -d "Use a specific GPU (run with --verbose to get
complete -c godot -l text-driver -d "Set the text driver" -x
complete -c godot -l tablet-driver -d "Set the pen tablet input driver" -x
complete -c godot -l headless -d "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script"
-complete -c godot -l write-movie -d "Writes a video to the specified path (usually with .avi or .png extension). --fixed-fps is forced when enabled" -x
+complete -c godot -l log-file -d "Write output/error log to the specified path instead of the default location defined by the project" -x
+complete -c godot -l write-movie -d "Write a video to the specified path (usually with .avi or .png extension). --fixed-fps is forced when enabled" -x
# Display options:
complete -c godot -s f -l fullscreen -d "Request fullscreen mode"