【问题标题】:How to reset tty after exec-ed program crashes?exec-ed程序崩溃后如何重置tty?
【发布时间】:2014-06-11 19:01:44
【问题描述】:

我正在围绕 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) 系统调用,因此没有分叉。 一个问题是容器有时会过早死亡,这有效地杀死了我新创建的 Bash 提示符。然后我恢复了最初用于运行我的 Ruby 工具的提示,但我看不到我正在输入的内容,tty 似乎坏了,运行 reset 有效地解决了这个问题。

如果我执行的程序崩溃,我想有条件地运行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 工作正常,但并不理想。

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

【问题讨论】:

    标签: linux bash tty


    【解决方案1】:

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

    即使终端回显已经启用,也可以安全运行,所以如果你想安全地运行它,你可以执行类似./myrubytool ; stty echo 的操作,如果终端回显被禁用,则无论退出状态如何,都会重新启用终端回显你的 Ruby 程序。如果你愿意,你可以把它放在一个 shell 脚本中。

    可能有一种方法可以在 Ruby 程序退出时执行命令(通常称为“陷阱”),但我对 Ruby 不够熟悉,无法知道是否存在此类功能。

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

    【讨论】:

    • 感谢您的回答。不幸的是,我并不能真正控制 Docker 容器何时崩溃。在尝试运行 nsenter 之前,我通过测试开放端口使我的命令更加健壮(这可以确保容器正常运行)。这有效地防止了问题的发生,但我仍然很想找到 Bash 将程序置于后台的解释,以及是否有办法实现我想要的。
    【解决方案2】:

    这个怎么样?它应该完全符合您的要求。
    它在一个单独的进程中运行命令,等待它,如果完成后返回值不为 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")

    【讨论】:

    • 请注意,reset 不仅仅是重新打开终端回显。我意识到这是 OP 写的关于当前使用的内容,但它不一定是这项工作的最佳工具。
    • 感谢您的回答。不幸的是,这将主进程置于后台(因此我需要执行“fg”来重置运行)。我的猜测是,在交互模式下,Bash 一次不能运行多个程序,因此它会将东西放在后台。在您的代码中,分叉的进程以交互方式运行有效负载,而 Bash 将主进程置于后台。
    • @Janitrix 您对它为什么不起作用的解释没有意义。它非常适合我。 bash 没有将有效载荷放在“背景”中;我的代码是(它也不在bash 的背景中;fg 不会改变任何东西)。
    猜你喜欢
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 2012-10-31
    相关资源
    最近更新 更多