我正在编写关于Docker和nsenter的Ruby包装器。我的工具提供的命令之一是在容器中启动Bash。目前,我这样做:
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有效地解决了这个问题。
如果我执行的程序崩溃,我想有条件地运行reset。我发现以下几点效果很好:
$ ./myrubytool || reset不过,我希望避免每次都强迫人们使用我的工具附加|| reset。
我尝试了以下几点:
有效载荷= "(sudo nsenter目标#{pid(container_name)} -装入-uts-ipc-net- env #{env} /bin/bash -i -l)
但令人惊讶的是,这会将reset置于后台(即,我可以通过输入fg来运行重置)。一个好处是tty工作正常,但并不是很理想。
你有什么办法解决这个问题吗?
发布于 2014-06-11 19:17:22
如果终端回波已在终端中禁用,则可以运行命令stty echo 重新启用终端回波。(相反,stty -echo禁用终端回波,stty -a显示所有终端设置)。
这是安全的运行,即使终端回显已经启用,所以如果你想让它安全,你可以做一些像./myrubytool ; stty echo,这将重新启用终端回声,如果它是禁用的,而不管退出状态的红宝石程序。如果愿意,可以将其放入shell脚本中。
当Ruby程序退出时,可能有一种执行命令的方法(通常被称为“陷阱”),但我对Ruby还不太熟悉,不知道是否存在这样的功能。
但是,如果您要创建一个通用脚本,可能应该研究更健壮的技术,而不是依赖于解决方案.
发布于 2014-06-11 22:49:22
这个怎么样?它应该能做你想做的事。
它在一个单独的进程中运行命令,等待它,如果它完成时返回值不是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")。
https://stackoverflow.com/questions/24247225
复制相似问题