【问题标题】:How to make irb quit after long idle?长时间闲置后如何让irb退出?
【发布时间】:2014-03-28 10:58:18
【问题描述】:

我是一名 DBA,我偶然发现了这种情况:开发人员运行 irb 会话(来自 Ruby on Rails 应用程序)。此 irb 保持数据库连接打开。有时——他们忘记了它,它继续“运行”——什么都不做,但仍然使用一个数据库连接。

我想在他们的 irb 配置中添加某种“空闲超时”。是否可以?怎么做?

【问题讨论】:

  • 在一段时间后终止进程可能会更好,因为我认为 irb 没有自毁选项。或者可能在每天凌晨 2 点终止进程或其他什么?
  • 凌晨 2 点是个非常糟糕的主意,因为我们至少有 4 个不同时区的工人 :) 所有人都在同一台机器上工作 :)
  • 嗯,是的,那是行不通的:)
  • 您想在客户端上强制执行此操作,并且即使他们没有连接到数据库,也让他们的 irb 会话超时?超时空闲数据库连接可能不是更好吗?如果是 Postgres,显然有像 PGBouncer 这样的东西代理连接并管理空闲连接,您可以让开发人员在开发环境中配置他们的连接设置以通过这样的代理/连接管理器。
  • 我知道 pgbouncer,问题是我喜欢来自应用程序的空闲数据库连接——我只是不喜欢开发人员提供的它们。即使他们由于运行迁移而使用应用凭据。

标签: ruby irb


【解决方案1】:

这里有一个快速的技巧,你可以如何实现它。

请注意,这并没有考虑到用户可能正在 irb 会话中执行一些长时间运行的任务。它只是查看最后一个输入的时间戳;如果它没有改变,那么它会直接终止进程:

更新:它现在检查 irb 当前是否正在运行命令,如果是,则忽略任何超时。

# Add some methods to IRB::Context and IRB::Irb
# for easier timeout implementation.
class IRB::Irb
  def status
    @signal_status
  end
end

class IRB::Context
  attr_reader :irb
  attr_reader :line_no

  def is_evaluating?
    self.irb.status == :IN_EVAL
  end
end

# Implement an auto exit timer thread. Timeout is given in seconds.
module IRB
  def self.auto_exit_after(timeout = 60)
    Thread.new {
      context    = IRB.conf[:MAIN_CONTEXT]
      last_input = Time.now
      last_line  = context.line_no

      loop {
        sleep 10

        # Check if irb is running a command
        if context.is_evaluating?
          # Reset the input time and ignore any timeouts
          last_input = Time.now
          next
        end

        # Check for new input
        if last_line != context.line_no
          # Got new input
          last_line  = context.line_no
          last_input = Time.now
          next
        end

        # No new input, check if idle time exceeded
        if Time.now - last_input > timeout    
          $stderr.puts "\n** IRB exiting due to idle timeout. Goodbye..."
          Process.kill("KILL", Process.pid)
        end
      }
    }
  end
end

要使用它,请将代码添加到.irbrc,或在启动 irb 时自动加载的其他地方,然后启动计时器:

IRB.auto_exit_after(60)

【讨论】:

  • 这几乎可以正常工作 - 但几乎很重要。如果我在 irb 中运行一些长时间运行的命令——足够长到比超时时间长——它也会被杀死。我知道用户可以修改截止日期,但如果我要信任用户,我一开始就不会遇到这个问题。所以问题是 - 如果有命令正在运行,是否可以将其修改为 not kill irb?
  • 错过了您在开始时对长时间运行命令所做的评论。嗯 - 听起来我想要的东西是不可能的吗?
  • @user3095735 当您掌握了编程的力量时,没有什么是不可能的:) 这里的问题是我们可以使它变得多么漂亮或可靠。应该可以,但要花更多的时间去调查。如果我有空闲时间,也许我会看看。 irb 源代码就在 Ruby 中,只需研究它在后台是如何工作的,看看你可以在哪里挂钩(或找到其他替代方法来检测正在运行的任务)。
  • 是的 - 好吧,但我不能(实际上)自己做,抱歉 - 但我对 Ruby 几乎一无所知。
  • 对于 Rails 控制台,IRB 上下文不会立即初始化。我在Thread.new 的第一行添加了一个sleep(5),以便让它有时间进行初始化。
猜你喜欢
  • 1970-01-01
  • 2016-02-19
  • 1970-01-01
  • 2021-01-02
  • 2023-04-10
  • 2014-12-21
  • 2017-09-25
  • 2012-10-20
  • 2018-07-15
相关资源
最近更新 更多