Avoid Jupyter terminal job-control noise

This commit is contained in:
wuyang6
2026-06-12 21:38:53 +08:00
parent c91f65c856
commit c795ec1b5d
2 changed files with 31 additions and 2 deletions
+23 -2
View File
@@ -542,7 +542,7 @@ PY
pid_file = shlex.quote(f'{run_dir}/{marker}.pid') pid_file = shlex.quote(f'{run_dir}/{marker}.pid')
env_prefix = self._remote_env_prefix() env_prefix = self._remote_env_prefix()
inner_command = f'{env_prefix}{command}' inner_command = f'{env_prefix}{command}'
wrapped = ( wrapper_script = (
f'mkdir -p {workspace} {quoted_run_dir} && ' f'mkdir -p {workspace} {quoted_run_dir} && '
f'cd {workspace} && ' f'cd {workspace} && '
f'printf "\\n{start_marker}\\n"; ' f'printf "\\n{start_marker}\\n"; '
@@ -561,6 +561,11 @@ PY
f'rm -f {pid_file}; ' f'rm -f {pid_file}; '
f'printf "\\n{marker}:%s\\n" "$__zk_status"' f'printf "\\n{marker}:%s\\n" "$__zk_status"'
) )
# Run the wrapper inside a foreground non-interactive bash. Sending the
# whole background-job wrapper directly to the terminal shell can make
# the interactive shell print job-control lines such as
# "[1] + Done (setsid bash -lc ...)", which can hide the real stdout.
wrapped = f'bash -lc {shlex.quote(wrapper_script)}'
with self._lock: with self._lock:
name = self._ensure_terminal() name = self._ensure_terminal()
ws_url = self._terminal_websocket_url(name) ws_url = self._terminal_websocket_url(name)
@@ -1288,11 +1293,27 @@ def clean_terminal_output(text: str) -> str:
lines = [ lines = [
line.rstrip('\r') line.rstrip('\r')
for line in cleaned.splitlines() for line in cleaned.splitlines()
if line.strip() not in {'#', '>'} and not re.fullmatch(r'(>\s*)+', line.strip()) if (
line.strip() not in {'#', '>'}
and not re.fullmatch(r'(>\s*)+', line.strip())
and not is_wrapper_job_control_line(line.strip())
)
] ]
return '\n'.join(lines).strip('\r\n') return '\n'.join(lines).strip('\r\n')
def is_wrapper_job_control_line(line: str) -> bool:
"""Return true for terminal job-control notices created by our wrapper."""
if 'setsid bash -lc' not in line:
return False
return bool(
re.match(
r'^\[\d+\]\s*[+-]?\s*(Done|done|Terminated|terminated|Killed|killed|Exit \d+)',
line,
)
)
def extract_terminal_command_output(text: str, *, start_marker: str) -> str: def extract_terminal_command_output(text: str, *, start_marker: str) -> str:
"""Drop terminal echo/prompt text before the wrapper's real start marker.""" """Drop terminal echo/prompt text before the wrapper's real start marker."""
if not start_marker: if not start_marker:
+8
View File
@@ -35,6 +35,14 @@ class TestJupyterRuntimeOutputFiltering(unittest.TestCase):
self.assertEqual(output, 'actual') self.assertEqual(output, 'actual')
def test_clean_terminal_output_drops_wrapper_job_control_line(self) -> None:
cleaned = clean_terminal_output(
'real-output\r\n'
'[1] + Done (setsid bash -lc "export A=1; lscpu")\r\n'
)
self.assertEqual(cleaned, 'real-output')
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()