diff options
author | John Estabrook <jestabro@vyos.io> | 2021-03-18 13:30:41 -0500 |
---|---|---|
committer | John Estabrook <jestabro@vyos.io> | 2021-03-18 15:39:32 -0500 |
commit | d287cebbc95f516d395534e6ea2d95e3412bd21f (patch) | |
tree | a26119c9e90a3799303b91c91047ecdcbf47054f /src | |
parent | 13005fb6c2beb1e87200e31aadbbd62de4f33729 (diff) | |
download | vyos-1x-d287cebbc95f516d395534e6ea2d95e3412bd21f.tar.gz vyos-1x-d287cebbc95f516d395534e6ea2d95e3412bd21f.zip |
configd: T3411: redirect stdout from scripts to console; to file on boot
Diffstat (limited to 'src')
-rwxr-xr-x | src/services/vyos-configd | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/src/services/vyos-configd b/src/services/vyos-configd index 5b1ab1f1f..8547b5f56 100755 --- a/src/services/vyos-configd +++ b/src/services/vyos-configd @@ -25,6 +25,7 @@ import logging import signal import importlib.util import zmq +from contextlib import contextmanager from vyos.defaults import directories from vyos.configsource import ConfigSourceString, ConfigSourceError @@ -33,6 +34,8 @@ from vyos import ConfigError CFG_GROUP = 'vyattacfg' +script_stdout_log = '/tmp/vyos-configd-script-stdout' + debug = True logger = logging.getLogger(__name__) @@ -59,7 +62,8 @@ configd_env_unset_file = os.path.join(directories['data'], 'vyos-configd-env-uns # sourced on entering config session configd_env_file = '/etc/default/vyos-configd-env' -session_tty = None +session_out = None +session_mode = None def key_name_from_file_name(f): return os.path.splitext(f)[0] @@ -104,14 +108,29 @@ conf_mode_scripts = dict(zip(imports, modules)) exclude_set = {key_name_from_file_name(f) for f in filenames if f not in include} include_set = {key_name_from_file_name(f) for f in filenames if f in include} -def explicit_print(t, m): +@contextmanager +def stdout_redirected(filename, mode): + saved_stdout_fd = None + destination_file = None try: - with open(t, 'w') as f: - f.write(m) - f.write("\n") - f.flush() - except Exception: - pass + sys.stdout.flush() + saved_stdout_fd = os.dup(sys.stdout.fileno()) + destination_file = open(filename, mode) + os.dup2(destination_file.fileno(), sys.stdout.fileno()) + yield + finally: + if saved_stdout_fd is not None: + os.dup2(saved_stdout_fd, sys.stdout.fileno()) + os.close(saved_stdout_fd) + if destination_file is not None: + destination_file.close() + +def explicit_print(path, mode, msg): + try: + with open(path, mode) as f: + f.write(f"\n{msg}\n\n") + except OSError: + logger.critical("error explicit_print") def run_script(script, config) -> int: config.set_level([]) @@ -122,15 +141,17 @@ def run_script(script, config) -> int: script.apply(c) except ConfigError as e: logger.critical(e) - explicit_print(session_tty, str(e)) + explicit_print(session_out, session_mode, str(e)) return R_ERROR_COMMIT - except Exception: + except Exception as e: + logger.critical(e) return R_ERROR_DAEMON return R_SUCCESS def initialization(socket): - global session_tty + global session_out + global session_mode # Reset config strings: active_string = '' session_string = '' @@ -158,9 +179,15 @@ def initialization(socket): logger.debug(f"config session pid is {pid_string}") try: - session_tty = os.readlink(f"/proc/{pid_string}/fd/1") + session_out = os.readlink(f"/proc/{pid_string}/fd/1") + session_mode = 'w' except FileNotFoundError: - session_tty = None + session_out = None + + # if not a 'live' session, for example on boot, write to file + if not session_out or '/dev/pts' not in session_out: + session_out = script_stdout_log + session_mode = 'a' try: configsource = ConfigSourceString(running_config_text=active_string, @@ -194,7 +221,8 @@ def process_node_data(config, data) -> int: if script_name in exclude_set: return R_PASS - result = run_script(conf_mode_scripts[script_name], config) + with stdout_redirected(session_out, session_mode): + result = run_script(conf_mode_scripts[script_name], config) return result |