class WebSandboxConsole::Sandbox

Attributes

code[RW]
exe_tmp_file[RW]
pass_auth[RW]
uuid[RW]

Public Class Methods

new(code = nil, pass_auth = false) click to toggle source
# File lib/web_sandbox_console/sandbox.rb, line 8
def initialize(code = nil, pass_auth = false)
  @code         = code
  @uuid         = SecureRandom.uuid
  @pass_auth    = pass_auth.presence || false
  @exe_tmp_file = "#{Rails.root}/tmp/sandbox/#{uuid}.rb"
end

Public Instance Methods

add_tmp_file_dir() click to toggle source

添加临时文件目录

# File lib/web_sandbox_console/sandbox.rb, line 84
def add_tmp_file_dir
  FileUtils.mkdir_p(tmp_file_dir)  unless File.directory?(tmp_file_dir)
end
asyn_evalotor() click to toggle source

异步后台执行

# File lib/web_sandbox_console/sandbox.rb, line 24
def asyn_evalotor
  evalotor_block do
    Thread.new {exec_rails_runner}
    ["已在后台执行,请耐心等待😊"]
  end
end
auto_clean_tmp_file() click to toggle source

自动删除临时文件

# File lib/web_sandbox_console/sandbox.rb, line 94
def auto_clean_tmp_file
  FileUtils.rm_rf(Dir["#{tmp_file_dir}/*"]) if tmp_file_need_clean?
end
check_syntax() click to toggle source

检查 语法

# File lib/web_sandbox_console/sandbox.rb, line 112
def check_syntax
  prepare_check_syntax
  unless `ruby -c #{self.exe_tmp_file}`.include?('Syntax OK')
    raise SandboxError, "存在语法错误"
  end
end
evalotor() click to toggle source

同步执行

# File lib/web_sandbox_console/sandbox.rb, line 16
def evalotor
  evalotor_block do
    exec_rails_runner
    get_result
  end
end
evalotor_block() { || ... } click to toggle source

执行结构块

# File lib/web_sandbox_console/sandbox.rb, line 32
def evalotor_block
  begin
    check_syntax
    write_exe_tmp_file
    yield
  rescue SandboxError => e
    [e.message]
  rescue Exception => e
    ["发生未知错误: #{e.inspect};#{e.backtrace[0..2].join('\r\n')}"]
  end
end
exec_rails_runner() click to toggle source

运行rails runner

# File lib/web_sandbox_console/sandbox.rb, line 120
def exec_rails_runner
  @stdout = `RAILS_ENV=#{Rails.env} bundle exec rails runner #{self.exe_tmp_file}`
end
get_result() click to toggle source

最终结果

# File lib/web_sandbox_console/sandbox.rb, line 134
def get_result
  if @stdout.present?
    stdout_arr = ['------------ 打印值 ----------']
    stdout_arr.concat(@stdout.to_s.split("\n"))
    stdout_arr << '------------ 返回值 ----------'
    stdout_arr.concat(return_result_arr)
  else
    return_result_arr
  end
end
no_rollback_code() click to toggle source

不回滚code

# File lib/web_sandbox_console/sandbox.rb, line 72
    def no_rollback_code
      <<-EOF
        result = eval(#{self.code.inspect})
      EOF
    end
prepare_check_syntax() click to toggle source

准备检查语法

# File lib/web_sandbox_console/sandbox.rb, line 106
def prepare_check_syntax
  add_tmp_file_dir
  File.open(self.exe_tmp_file, 'w'){|f| f << self.code}
end
return_result_arr() click to toggle source

返回结果

# File lib/web_sandbox_console/sandbox.rb, line 125
def return_result_arr
  last_10_lines = `tail -n 100 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
  
  last_10_lines.split("\n").map do |line|
    line.split("#{self.uuid}:").last.split("|||")
  end.flatten
end
rollback_code() click to toggle source

回滚code

# File lib/web_sandbox_console/sandbox.rb, line 62
    def rollback_code
      <<-EOF
        ActiveRecord::Base.transaction(requires_new: true) do
          result = eval(#{self.code.inspect})
          raise ActiveRecord::Rollback
        end
      EOF
    end
runner_code() click to toggle source
# File lib/web_sandbox_console/sandbox.rb, line 44
    def runner_code
      str =<<-CODE
        result = nil
        begin
          WebSandboxConsole.current_uuid("#{self.uuid}")
          WebSandboxConsole.init_safe_env
          WebSandboxConsole.logger_sql
          #{self.pass_auth ? no_rollback_code : rollback_code}
        rescue Exception => e
          WebSandboxConsole.log_p(e)
        rescue SyntaxError => e
          WebSandboxConsole.log_p(e)
        end
        WebSandboxConsole.log_p(result)
      CODE
    end
tmp_file_dir() click to toggle source

临时文件目录

# File lib/web_sandbox_console/sandbox.rb, line 79
def tmp_file_dir
  File.dirname(self.exe_tmp_file)
end
tmp_file_need_clean?() click to toggle source

临时文件 需要清理?

# File lib/web_sandbox_console/sandbox.rb, line 89
def tmp_file_need_clean?
  Dir["#{tmp_file_dir}/*"].count > 6
end
write_exe_tmp_file() click to toggle source

写入 执行临时文件

# File lib/web_sandbox_console/sandbox.rb, line 99
def write_exe_tmp_file
  add_tmp_file_dir
  auto_clean_tmp_file
  File.open(self.exe_tmp_file, 'w'){|f| f << runner_code}
end