macOS下从Python启动Terminal时消除命令未找到警告
我有一个基于PyQt5的macOS基础应用,通过以下代码启动Terminal.app并执行命令:
cmd = f" cd {os.getcwd()}; bash -c ./backup.sh" subprocess.run(['osascript', '-e', f'tell application "Terminal" to do script "{cmd}"'])
功能正常,但终端执行每个命令都会弹出警告:-bash: __vsc_prompt_cmd_original: command not found。
在新启动的Terminal.app实例中执行echo $PROMPT_COMMAND,输出如下:
🧢 pi@pis-MacBook-Pro ~/Desktop/tmp/tray > echo $PROMPT_COMMAND update_terminal_cwd; __vsc_prompt_cmd_original history -a; history -c; history -r -bash: __vsc_prompt_cmd_original: command not found
我从VSCode交互式终端运行应用时,VSCode终端里echo $PROMPT_COMMAND的输出是__vsc_prompt_cmd_original;换成iTerm2运行应用,问题依旧,iTerm2中该命令输出为history -a; history -c; history -r。
尝试在命令前添加unset PROMPT_COMMAND:
cmd = f" unset PROMPT_COMMAND; cd {os.getcwd()}; bash -c ./backup.sh" subprocess.run(['osascript', '-e', f'tell application "Terminal" to do script "{cmd}"'])
后续命令不再出现警告,但Terminal启动时仍会弹出一次初始警告。
需求:如何启动Terminal.app时完全避免该警告?
问题根源是Terminal.app启动时会继承父进程(VSCode/iTerm2)的PROMPT_COMMAND环境变量,同时Terminal自身会在这个变量前追加update_terminal_cwd; ,导致拼接后的命令里包含不存在的__vsc_prompt_cmd_original。要彻底解决,需要在启动Terminal前就清除父进程传递的PROMPT_COMMAND,而不是在Terminal里执行unset。
方法1:通过osascript启动Terminal时重置环境变量
修改osascript命令,让Terminal启动后执行的第一条命令就是unsetPROMPT_COMMAND,覆盖初始化时继承的环境变量:
cmd = f"cd {os.getcwd()}; bash -c ./backup.sh" subprocess.run([ 'osascript', '-e', f'tell application "Terminal" to do script "unset PROMPT_COMMAND; {cmd}"' ])
这种方式能消除Terminal启动时的初始警告,同时正常执行目标命令。
方法2:启动Terminal时指定干净环境(更彻底)
通过open命令启动Terminal.app,直接清空PROMPT_COMMAND环境变量,从根源上阻止Terminal继承父进程的问题环境:
import os # 构造临时脚本避免引号转义问题 temp_script = "/tmp/terminal_start.sh" with open(temp_script, 'w') as f: f.write(f"""#!/bin/bash cd {os.getcwd()} ./backup.sh # 如果需要保留Terminal窗口,添加下面一行 # bash """) os.chmod(temp_script, 0o755) # 启动Terminal并执行临时脚本,同时清空PROMPT_COMMAND subprocess.run([ 'open', '-a', 'Terminal.app', '--env', 'PROMPT_COMMAND=', temp_script ]) # 执行完后删除临时文件 os.remove(temp_script)
补充说明
如果希望backup.sh执行完成后Terminal窗口不关闭,只需在脚本末尾添加bash命令维持会话即可。
内容的提问来源于stack exchange,提问作者P i

