From 838873a544822b8f2cdb2b7713bb596b016b7a84 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Wed, 11 Mar 2026 11:03:45 +0100 Subject: [PATCH] configd: change https://github.com/opnsense/core/commit/c8cd5565ec135a0111497fde2e20e3cb79324f0d seemed to have uncovered another issue when it comes to file generation, as each call generates a new tempfile, we're now keeping a lot of them. In order to fix this behavoir, only generate the filename and reuse it when serving cached commands, which was the intention from the beginning. (cherry picked from commit 914e5a20e172200593190e12a7c83670fe22ce1a) --- .../service/modules/actions/script_output.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/opnsense/service/modules/actions/script_output.py b/src/opnsense/service/modules/actions/script_output.py index 3e83239eaf..fb141a4375 100644 --- a/src/opnsense/service/modules/actions/script_output.py +++ b/src/opnsense/service/modules/actions/script_output.py @@ -74,14 +74,22 @@ class Action(BaseAction): output_stream.seek(0) return output_stream.read() with tempfile.NamedTemporaryFile() as error_stream: - tparm = {'prefix': Action.temp_prefix, 'delete': script_hash is None} - with tempfile.NamedTemporaryFile(**tparm) as output_stream: + if script_hash is None or script_hash not in Action.cached_results: + fd, output_filename = tempfile.mkstemp(prefix=Action.temp_prefix) + os.close(fd) + else: + output_filename = Action.cached_results[script_hash]['filename'] + + with open(output_filename, 'a+') as output_stream: fcntl.flock(output_stream, fcntl.LOCK_EX) if script_hash: Action.cached_results[script_hash] = { - 'filename': output_stream.name, + 'filename': output_filename, 'expire': time.time() + self.cache_ttl } + # explicit flush, file may be reused + output_stream.seek(0) + output_stream.truncate() subprocess.run(script_command, env=self.config_environment, shell=True, check=not self.disable_errors, stdout=output_stream, stderr=error_stream) output_stream.seek(0) @@ -92,6 +100,10 @@ class Action(BaseAction): syslog_error('[%s] Script action stderr returned "%s"' % ( message_uuid, script_error_output.strip()[:255] )) + if script_hash is None: + # temp file not for re-use + output_stream.close() + os.remove(output_filename) return script_output except Exception as script_exception: syslog_error('[%s] Script action failed with %s at %s' % (