执行程序崩溃后如何重设tty? [英] How to reset tty after exec-ed program crashes?

查看:66
本文介绍了执行程序崩溃后如何重设tty?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a Ruby wrapper around Docker and nsenter. One of the command my tool provides is to start a Bash shell within a container. Currently, I am doing it like this:

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) syscall,因此没有派生.一个问题是该容器有时过早死亡,从而有效地杀死了我新创建的Bash提示.然后,我得到了最初用于运行Ruby工具的提示,但是我看不到我在键入什么,tty似乎坏了,运行reset可以有效地解决问题.

In Ruby, Kernel#exec relies on the exec(2) syscall, hence there is no fork. One issue is that the container sometime dies prematurely which effectively kills my newly created Bash prompt. I then get back the prompt originally used to run my Ruby tool, but I cannot see what I am typing anymore, the tty seems broken and running reset effectively solves the issue.

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

I'd like to conditionally run reset if the program I exec-ed crashes. I found that the following works well:

$ ./myrubytool || reset

除了我要避免强迫人们使用我的工具附加 ||每次重置.

Except I'd like to avoid forcing people using my tool to append || reset every time.

我尝试了以下操作:

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

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

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

But this surprisingly puts reset in the background (i.e. I can run reset by entering fg). One benefit is that the tty is working properly, but it's not really ideal.

您有解决此问题的想法吗?

Would you have any idea to solve this issue?

推荐答案

这个怎么样?它应该可以完全满足您的要求.
它在一个单独的进程中运行该命令,然后等待它,如果完成,返回值不为0,则它​​运行命令 reset .

How about this? It should do exactly what you want.
It runs the command in a separate process, waits on it, and if, when it finishes, the return value is not 0, it runs the command 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").

这篇关于执行程序崩溃后如何重设tty?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆