SSH执行含time.sleep的远程Python脚本停滞问题排查
问题描述
远程服务器$HOME目录下有test.py脚本,内容如下:
# test.py (this is on the remote server in $HOME) import sys import time def test(num_samples): # First start with a monitoring period of 50 seconds. monitoring_period = 5 a = 0 while a < num_samples: print(a, num_samples) time.sleep(monitoring_period) a += 1000 if __name__ == "__main__": print("Start") test(int(sys.argv[1]))
直接在远程服务器本地执行脚本时一切正常:
node0:~$ python test.py 500 Start 0 500
但通过SSH远程执行时出现停滞,连首条print("Start")的输出都看不到:
❯ ssh -o StrictHostKeyChecking=no <user>@<remote-server> "pushd \$HOME; python test.py 500" ~ ~ // 此处停滞无任何输出
有趣的是,移除脚本中的time.sleep(.)语句后,SSH远程执行又恢复正常:
❯ ssh -o StrictHostKeyChecking=no <user>@<remote-server> "pushd \$HOME; python test.py 500" ~ ~ Start 0 500
疑问:
- 具体是什么原因导致的?是
time.sleep语句引发的问题吗? - 如果是,Python解释器是否会在执行脚本首条语句(
print("Start"))前就检测到该语句?
问题解答
核心原因是Python的输出缓冲机制,和
time.sleep直接相关
当通过SSH执行脚本时,Python默认会对标准输出(stdout)启用块缓冲模式。本地终端运行时,stdout属于交互式终端,Python会自动使用行缓冲,所以print("Start")会立即输出;但SSH执行时,stdout是管道类型的非交互式输出,Python会攒够一定量的内容才会刷新到终端。而time.sleep(5)会让进程进入休眠状态,此时缓冲里的内容还没达到触发刷新的阈值,导致你看不到任何输出,看起来像是停滞了。Python不会提前检测
time.sleep,print("Start")已经执行print("Start")实际上已经被执行了,只是输出被暂存在内存缓冲中没有刷出来。Python是逐行解释执行的,会先执行if __name__ == "__main__"块里的print("Start"),再调用test函数,遇到time.sleep才进入休眠。只是缓冲没被刷新,才让你误以为这条语句没执行。
解决办法:
- 执行Python时添加
-u参数,强制禁用输出缓冲:ssh -o StrictHostKeyChecking=no <user>@<remote-server> "pushd \$HOME; python -u test.py 500" - 或者在
print语句中添加flush=True参数,强制刷新输出:print("Start", flush=True) print(a, num_samples, flush=True)
内容的提问来源于stack exchange,提问作者diviquery
相关产品推荐
相关产品推荐

