执行程序崩溃后如何重置tty?

时间:2014-06-11 19:01:44

标签: linux bash tty

我正在编写一个围绕Docker和nsenter的Ruby包装器。我的工具提供的命令之一是在容器中启动Bash shell。目前,我这样做:

payload = "sudo nsenter --target #{pid(container_name)} --mount --uts --ipc --net --pid -- env #{env} /bin/bash -i -l;"
Kernel.exec(payload)

在Ruby中,Kernel#exec依赖于exec(2)系统调用,因此没有fork。 一个问题是容器有时会过早死亡,这会有效地杀死我新创建的Bash提示符。然后我回到最初用于运行我的Ruby工具的提示,但我看不到我正在输入的内容,tty似乎已经破坏并且有效地运行重置可以解决问题。

如果我执行的程序崩溃,我想有条件地运行reset。我发现以下效果很好:

$ ./myrubytool || reset

除非我想避免强迫每次使用我的工具的人追加|| reset

我尝试了以下内容:

  

payload ="(sudo nsenter --target#{pid(container_name)} - mount --uts --ipc --net --pid - env#{env} / bin / bash -i -l)||复位;"

但这令人惊讶地将reset置于后台(即我可以通过输入fg来重置)。一个好处是tty工作正常,但它并不是很理想。

你有什么想法解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

如果在终端中禁用了终端回声,则可以运行命令stty echo以重新启用终端回声。(相反,stty -echo禁用终端回声,stty -a显示所有终端设置。)

即使已经启用了终端回声,也可以安全运行,所以如果你想安全地播放它,你可以做./myrubytool ; stty echo这样的事情,如果它被禁用,它会重新启用终端回声而不管退出Ruby程序的状态。如果您愿意,可以将它放在shell脚本中。

可能有一种方法在Ruby程序退出时执行命令(通常称为"陷阱"),但我不熟悉Ruby以了解是否存在这样的能力。

但是,如果您要创建一般用途的脚本,您可能应该研究更强大的技术,而不是依赖于解决方法。

答案 1 :(得分:0)

这个怎么样?它应该完全符合你的要求 它在一个单独的进程中运行该命令,等待它,如果在完成时,返回值不为0,则它​​运行命令reset

payload = "sudo nsenter --target #{pid(container_name)} --mount --uts --ipc --net --pid -- env #{env} /bin/bash -i -l;"
fork { Kernel.exec(payload) }
pid, status = Process.wait2
unless status.exitstatus == 0
     system("reset")
end

修改
如果您只想重新开启回声,请将system("reset")行更改为system("stty echo")