Ruby + Sinatra:在后台运行ruby脚本并访问Sinatra中的Variables

时间:2015-11-01 18:08:07

标签: ruby sinatra background-process

如何在服务器后台运行ruby脚本,同时仍然能够获取脚本在加载页面时用来显示用户的变量。

我需要服务器在无限循环中在后台连续运行进程。

后台处理示例:

while 0==0
  if @variable!=nil
    @variable+=1
  else
    @variable=0
  end
end

如何在我的服务器后台运行并让sinatra在收到get请求时获取@variable的值:ex:

get 'variable' do
    "This is the current value of the variable: #{@variable}"
end

2 个答案:

答案 0 :(得分:2)

您可能最好将服务器端进程的输出放在数据库,文件,共享内存段或键值存储(例如Redis)中,并在请求时从Sinatra访问当前值是。虽然理论上可行(使用分叉的进程或后台线程在Sinatra机架之前启动),但您可能不应该尝试将这两个内容混合到一个进程中。

回应你的评论,看起来你刚刚开始使用Ruby并且可能正在编程。您应该花一些时间来了解数据库,SQL和迁移(例如ActiveRecord迁移)。对于许多实际用例来说,这将是一个很好的知识。

由于安装和配置MySQL,Redis或类似的东西可能超出了您的范围,我们可以使用简单的SQLite数据库(和sqlite3 gem)来解决您的问题。 SQLite在某种程度上类似于关系数据库,因为它理解SQL语句,但它只是使用存在于磁盘上的文件而不是完整的服务。我们的服务器端进程(即循环)将负责创建数据库,保存我们的值的表以及更新值。我们的Sinatra进程将打开数据库并根据需要检索当前值。

在我们进入代码之前,我想强调这是一个非常简单的例子,它只是解决问题的一种方法。您可以使用许多其他技术。也许其他一些SO海报会很友好地发布其他建议。 : - )

background.rb:

require 'sqlite3'

db = SQLite3::Database.new('/tmp/test.db')

# Initialize the table and zero count if not yet present.
db.execute <<-SQL
  CREATE TABLE IF NOT EXISTS my_values (
    id INTEGER PRIMARY KEY,
    my_count INTEGER
  );

  INSERT OR IGNORE INTO my_values (id, my_count) VALUES (1, 0);
SQL

# Prepare a query to run every interval.
stmt = db.prepare <<-SQL
  UPDATE my_values
  SET my_count = my_count + 1
  WHERE id = 1;
SQL

# Main processing loop.
loop do
  stmt.execute
  sleep 10
end

sinatra.rb:

require 'sinatra'
require 'sqlite3'

configure do
  set :database, SQLite3::Database.new('/tmp/test.db', { :readonly => true })
end

get '/variable' do
  count = settings.database.get_first_value <<-SQL
    SELECT my_count FROM my_values WHERE id = 1;
  SQL

  "This is the current value of the variable: #{count}"
end

随着您继续学习并成长为Ruby程序员,有很多方法可以改进上述内容:

  1. 使用诸如Sequel,DataMapper或ActiveRecord之类的ORM(而不是INSERTUPDATESELECT SQL语句。
  2. 使用ORM的迁移来更改数据库模式(而不是CREATE TABLE SQL语句)。
  3. 使用&#34;真实&#34;数据库,如MySQL,PostgreSQL或Firebird(而不是SQLite),或切换到使用键值存储,如Redis,Memcached或Rocks(而不是传统的基于SQL的数据库)。
  4. 添加一些&#34;健全检查&#34;到background.rb以确保例如only one copy is running一次{。}}。
  5. 改进background.rb以使其背景(守护进程)本身并写出其活动的日志。
  6. 使用Puma和连接池等线程应用程序服务器进行sinatra.rb中的数据库连接(某些ORM提供此功能)。您需要了解有关Rack的更多信息并创建一个单独的&#34; rackup&#34;脚本(例如config.ru)。
  7. 希望这有帮助。

答案 1 :(得分:1)

您可以在另一个线程中执行此操作,并使变量global访问它,例如:

require 'sinatra'

Thread.new do
    loop do
        if $variable!=nil
            $variable+=1
        else
            $variable=0
        end
    end
end

get '\variable' do
    "This is the current value of the variable: #{$variable}"
end

来源:http://blog.markwatson.com/2011/11/ruby-sinatra-web-apps-with-background.html?m=1