web_sandbox_console 0.1.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +143 -6
  3. data/app/assets/images/web_sandbox_console/logo-icon.png +0 -0
  4. data/app/assets/javascripts/web_sandbox_console/application.js +0 -1
  5. data/app/assets/javascripts/web_sandbox_console/code_editor.js +0 -0
  6. data/app/assets/javascripts/web_sandbox_console/codemirror.js +9778 -0
  7. data/app/assets/javascripts/web_sandbox_console/matchbrackets.js +158 -0
  8. data/app/assets/javascripts/web_sandbox_console/ruby.js +298 -0
  9. data/app/assets/stylesheets/web_sandbox_console/application.css +85 -14
  10. data/app/assets/stylesheets/web_sandbox_console/codemirror.css +349 -0
  11. data/app/assets/stylesheets/web_sandbox_console/common.css +231 -0
  12. data/app/assets/stylesheets/web_sandbox_console/docs.css +274 -0
  13. data/app/assets/stylesheets/web_sandbox_console/home.css +47 -0
  14. data/app/assets/stylesheets/web_sandbox_console/lucario.css +45 -0
  15. data/app/controllers/web_sandbox_console/application_controller.rb +4 -0
  16. data/app/controllers/web_sandbox_console/authorization_controller.rb +82 -0
  17. data/app/controllers/web_sandbox_console/home_controller.rb +44 -4
  18. data/app/views/layouts/web_sandbox_console/application.html.erb +82 -11
  19. data/app/views/web_sandbox_console/authorization/auth_page.html.erb +33 -0
  20. data/app/views/web_sandbox_console/home/do_view_file.js.erb +14 -0
  21. data/app/views/web_sandbox_console/home/download_page.html.erb +22 -0
  22. data/app/views/web_sandbox_console/home/eval_code.js.erb +1 -1
  23. data/app/views/web_sandbox_console/home/index.html.erb +34 -7
  24. data/app/views/web_sandbox_console/home/view_file.html.erb +39 -0
  25. data/config/routes.rb +12 -0
  26. data/lib/generators/web_sandbox_console/templates/web_sandbox_console.rb +20 -3
  27. data/lib/generators/web_sandbox_console/templates/web_sandbox_console.yml +5 -0
  28. data/lib/generators/web_sandbox_console/web_sandbox_console_generator.rb +5 -0
  29. data/lib/web_sandbox_console.rb +4 -0
  30. data/lib/web_sandbox_console/common.rb +29 -8
  31. data/lib/web_sandbox_console/configuration.rb +9 -1
  32. data/lib/web_sandbox_console/safe_ruby.rb +116 -16
  33. data/lib/web_sandbox_console/sandbox.rb +119 -20
  34. data/lib/web_sandbox_console/sandbox_error.rb +4 -0
  35. data/lib/web_sandbox_console/version.rb +1 -1
  36. data/lib/web_sandbox_console/view_file.rb +257 -0
  37. data/lib/web_sandbox_console/view_file_error.rb +4 -0
  38. metadata +28 -6
  39. data/app/jobs/web_sandbox_console/application_job.rb +0 -4
@@ -0,0 +1,39 @@
1
+ <h3>查看文件</h3>
2
+ <div class="view_file">
3
+ <%= form_tag do_view_file_path, method: :post, remote: true do %>
4
+ <table>
5
+ <tr>
6
+ <td>文件/目录路径</td>
7
+ <td>
8
+ <%= text_field_tag :file_or_dir, nil, class: 'file_or_dir', placeholder: '请输入文件路径...'%>
9
+ </td>
10
+ <td>起始行数</td>
11
+ <td><%= text_field_tag :start_line_num, nil, class: 'h30', placeholder: '默认从第1行开始...' %></td>
12
+ <td>结束行数</td>
13
+ <td><%= text_field_tag :end_line_num, nil, class: 'h30', placeholder: '默认从第100行结束...' %></td>
14
+
15
+ </tr>
16
+ <tr>
17
+ <td>过滤内容</td>
18
+ <td>
19
+ <%= text_field_tag :grep_content, nil, class: 'file_or_dir' %>
20
+ </td>
21
+ <td>过滤开始时间</td>
22
+ <td><%= text_field_tag :sed_start_time, nil, class: 'h30', placeholder: Time.current.strftime("%F %T") %></td>
23
+
24
+ <td>过滤结束时间</td>
25
+ <td><%= text_field_tag :sed_end_time, nil, class: 'h30', placeholder: Time.current.strftime("%F %T") %></td>
26
+ <td><%= submit_tag '提交', data: { disable_with: "已发送,处理中..." }, class: 'view-file-button' %></td>
27
+ </tr>
28
+ </table>
29
+ <% end %>
30
+ <span class="tip">注意:过滤时将忽略筛选行数;过滤内容中不能出现单引号</span>
31
+ </div>
32
+
33
+ <div class="output-content">
34
+
35
+ </div>
36
+
37
+ <style type="text/css">
38
+
39
+ </style>
@@ -2,4 +2,16 @@ WebSandboxConsole::Engine.routes.draw do
2
2
  root "home#index"
3
3
 
4
4
  post :eval_code, to: "home#eval_code"
5
+ get :view_file, to: "home#view_file"
6
+ post :do_view_file, to: "home#do_view_file"
7
+
8
+ # 授权相关
9
+ get :fetch_token, to: "authorization#fetch_token"
10
+ get :auth_page, to: "authorization#auth_page"
11
+ post :auth, to: "authorization#auth"
12
+
13
+ # 文件下载
14
+ get :download_page, to: "home#download_page"
15
+ get :download, to: "home#download"
5
16
  end
17
+
@@ -1,3 +1,8 @@
1
+ require 'yaml'
2
+
3
+ config_file_path = "#{Rails.root}/config/web_sandbox_console.yml"
4
+ config_hash = File.exists?(config_file_path) ? YAML.load_file(config_file_path).with_indifferent_access[:web_sandbox_console] : {}
5
+
1
6
  # web_sandbox_console 配置文件
2
7
  # 以下配置 都是可选的 缺少的情况下用默认值 或者 不生效
3
8
  WebSandboxConsole.setup do |config|
@@ -7,8 +12,10 @@ WebSandboxConsole.setup do |config|
7
12
  # 配置 ip 白名单
8
13
  # config.ip_whitelist = %w(192.168.23.12 192.145.2.0/24)
9
14
 
10
- # # 配置 基本认证
11
- # config.http_basic_auth = {name: 'dmy', password: '123456'}
15
+ # 配置 基本认证 在 config/web_sandbox_console.yml中配置
16
+ # PS: 1. 即使config/web_sandbox_console.yml文件不存在,也不会有任何使用上的影响,效果相当于没有开启
17
+ # 2. 下面这行不用注释掉,只要不配置yml文件就行
18
+ config.http_basic_auth = config_hash[:http_basic_auth]
12
19
 
13
20
  # # 配置 黑名单 类方法
14
21
  # config.class_method_blacklist = {File: %i(delete read write),Dir: %i(new delete mkdir)}
@@ -16,7 +23,17 @@ WebSandboxConsole.setup do |config|
16
23
  # # 配置 黑名单 实例方法
17
24
  # config.instance_method_blacklist = {Kernel: %i(system exec `),File: %i(chmod chown)}
18
25
 
26
+ # 文件黑名单列表 (如果是目录 则目录下所有文件都不可用)目录以 / 结尾
27
+ # 默认都是项目路径下的
28
+ # config.view_file_blacklist = %w(config/secrets.yml vendor/)
29
+
30
+ # 配置 文件权限,是否仅能查看log文件,默认开启
31
+ #config.only_view_log_file = false
32
+
33
+ # 通过非对称加密方式 升级权限,授权通过后,可获得执行数据权限(PS: 数据操作不再回滚)
34
+ # PS:配置同 http_basic_auth
35
+ config.public_key = config_hash[:public_key]
36
+
19
37
  # # 配置 日志路径 默认路径位于项目下
20
38
  # config.console_log_path = "log/web_sandbox_console.log"
21
39
  end
22
-
@@ -0,0 +1,5 @@
1
+ web_sandbox_console:
2
+ http_basic_auth:
3
+ name: dmy
4
+ password: 123456
5
+ public_key: "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMbJOE1vQT1jFpaH1GPYzdRJN/\nLh8VePmzXs5BYOLHB0xIjArL1NlXMbCJ+AS2rv3/oHIOdHhEuZw0tmm9DhG100R8\nRjBpsEKCDI88jl9qRkFmD3CVk8XQXv6c2IkRZCYSTvgDkmnKAlORksfw+p0cR2AQ\nlAtAsNsNviKYBzXKfQIDAQAB\n-----END PUBLIC KEY-----\n"
@@ -5,4 +5,9 @@ class WebSandboxConsoleGenerator < Rails::Generators::Base
5
5
  # 源文件 目标位置
6
6
  copy_file "web_sandbox_console.rb", "config/initializers/web_sandbox_console.rb"
7
7
  end
8
+
9
+ # 生成配置yaml文件
10
+ def copy_config_file
11
+ copy_file "web_sandbox_console.yml", "config/web_sandbox_console.yml.example"
12
+ end
8
13
  end
@@ -1,8 +1,12 @@
1
+ require 'fileutils'
1
2
  require "web_sandbox_console/engine"
3
+ require "web_sandbox_console/sandbox_error"
2
4
  require "web_sandbox_console/configuration"
3
5
  require "web_sandbox_console/common.rb"
4
6
  require "web_sandbox_console/safe_ruby"
5
7
  require "web_sandbox_console/sandbox"
8
+ require "web_sandbox_console/view_file_error"
9
+ require "web_sandbox_console/view_file"
6
10
 
7
11
 
8
12
  module WebSandboxConsole
@@ -1,17 +1,38 @@
1
1
  module WebSandboxConsole
2
2
  module Common
3
- # uuid 方便取出日志
4
- def log_p(msg_or_exce, uuid = nil)
5
- @logger ||= Logger.new(log_path)
3
+
4
+ def current_uuid(uuid=nil)
5
+ @uuid ||= uuid
6
+ end
7
+
8
+ # logger sql语句
9
+ def logger_sql
10
+ logger = fetch_logger
11
+ logger.level = 0
12
+ logger.formatter = proc {|severity, time, progname, msg| "#{current_uuid}: #{msg}\n"}
13
+ ActiveRecord::Base.logger = logger
14
+ end
6
15
 
7
- if msg_or_exce.respond_to?(:message)
8
- @logger.info "#{uuid}:" + msg_or_exce.message
9
- @logger.info "#{uuid}:" + msg_or_exce.backtrace.join("|||")
10
- else
11
- @logger.info "#{uuid}:" + msg_or_exce.inspect
16
+ # uuid 方便取出日志
17
+ def log_p(msg_or_exce, is_general_text = false)
18
+ uuid = current_uuid
19
+ logger = fetch_logger
20
+
21
+ if msg_or_exce.respond_to?(:message) # 异常
22
+ logger.info "#{uuid}:" + msg_or_exce.message
23
+ logger.info "#{uuid}:" + msg_or_exce.backtrace.join("|||")
24
+ elsif is_general_text # 普通文本
25
+ logger.info "#{uuid}:" + msg_or_exce.inspect
26
+ else # 返回值
27
+ logger.info "#{uuid}: => " + msg_or_exce.inspect
12
28
  end
13
29
  end
14
30
 
31
+ # 获取 logger
32
+ def fetch_logger
33
+ @logger ||= Logger.new(log_path, 'daily')
34
+ end
35
+
15
36
  def log_path
16
37
  "#{Rails.root}/#{self.console_log_path || "log/web_sandbox_console.log"}"
17
38
  end
@@ -9,13 +9,21 @@ module WebSandboxConsole
9
9
  mattr_accessor :class_method_blacklist
10
10
  # 实例方法 黑名单 hash
11
11
  mattr_accessor :instance_method_blacklist
12
+ # 文件列表 黑名单
13
+ mattr_accessor :view_file_blacklist
14
+ # 仅能查看日志文件
15
+ mattr_accessor :only_view_log_file
12
16
  # 日志路径
13
17
  mattr_accessor :console_log_path
14
18
  # 挂载 引擎路由位置
15
19
  mattr_accessor :mount_engine_route_path
20
+ # 公钥
21
+ mattr_accessor :public_key
16
22
 
17
23
  # 默认 引擎路由位置
18
24
  @@mount_engine_route_path = '/web_sandbox_console'
25
+ # 默认 开启仅可查看日志
26
+ @@only_view_log_file = true
19
27
 
20
28
  # 内置 实例方法 黑名单
21
29
  INSTANT_METOD_BUILT_IN_BLACKLIST = {
@@ -26,7 +34,7 @@ module WebSandboxConsole
26
34
  # 内置 类方法 黑名单
27
35
  CLASS_METHOD_BUILT_IN_BLACKLIST = {
28
36
  Kernel: %i(system exec `),
29
- File: %i(chmod chown new open delete read write),
37
+ File: %i(chmod chown new delete read write open),
30
38
  Dir: %i(new delete mkdir)
31
39
  }
32
40
 
@@ -5,17 +5,16 @@ module WebSandboxConsole
5
5
  sanitize_constants
6
6
  sanitize_instance_methods
7
7
  sanitize_class_methods
8
+ sanitize_logger_new
9
+ sanitize_csv
10
+ compatible_file_cache
11
+ compatible_i18n_translate
12
+ blacklist_method_remind
8
13
  end
9
14
 
10
15
  # 净化 类方法
11
16
  def sanitize_class_methods
12
- blacklist = if class_method_blacklist
13
- merge_method_hash(CLASS_METHOD_BUILT_IN_BLACKLIST, class_method_blacklist)
14
- else
15
- CLASS_METHOD_BUILT_IN_BLACKLIST
16
- end
17
-
18
- blacklist.each do |klass, methods|
17
+ class_method_blacklists.each do |klass, methods|
19
18
  klass = Object.const_get(klass)
20
19
  methods.each do |method|
21
20
  next if klass.singleton_methods.exclude?(method)
@@ -26,13 +25,7 @@ module WebSandboxConsole
26
25
 
27
26
  # 净化 实例方法
28
27
  def sanitize_instance_methods
29
- blacklist = if instance_method_blacklist
30
- merge_method_hash(INSTANT_METOD_BUILT_IN_BLACKLIST,instance_method_blacklist)
31
- else
32
- INSTANT_METOD_BUILT_IN_BLACKLIST
33
- end
34
-
35
- blacklist.each do |klass, methods|
28
+ instance_method_blacklists.each do |klass, methods|
36
29
  klass = Object.const_get(klass)
37
30
  methods.each do |method|
38
31
  next if (klass != Kernel) && klass.instance_methods.exclude?(method)
@@ -41,6 +34,24 @@ module WebSandboxConsole
41
34
  end
42
35
  end
43
36
 
37
+ # 类方法黑名单列表
38
+ def class_method_blacklists
39
+ blacklist = if class_method_blacklist
40
+ merge_method_hash(CLASS_METHOD_BUILT_IN_BLACKLIST, class_method_blacklist)
41
+ else
42
+ CLASS_METHOD_BUILT_IN_BLACKLIST
43
+ end
44
+ end
45
+
46
+ # 实例方法黑名单列表
47
+ def instance_method_blacklists
48
+ blacklist = if instance_method_blacklist
49
+ merge_method_hash(INSTANT_METOD_BUILT_IN_BLACKLIST,instance_method_blacklist)
50
+ else
51
+ INSTANT_METOD_BUILT_IN_BLACKLIST
52
+ end
53
+ end
54
+
44
55
  # 净化 常量
45
56
  def sanitize_constants
46
57
  return unless constant_blacklist
@@ -52,13 +63,13 @@ module WebSandboxConsole
52
63
  # 将两个hash 内部数组也同时合并,并去重
53
64
  def merge_method_hash(hash1, hash2)
54
65
  # 格式统一
55
- hash2.transform_keys!(&:to_sym).transform_values!{|val_arr| val_arr.map{|val| val.to_sym}}
66
+ hash2.transform_keys!(&:to_sym).transform_keys!(&:to_sym).transform_values!{|i| i.map(&:to_sym)}
56
67
  # 共有的key
57
68
  common_keys = hash2.keys & hash1.keys
58
69
  # hash2 特有keys
59
70
  hash2_special_keys = hash2.keys - hash1.keys
60
71
  # 特有keys 直接合到 hash1
61
- hash1.merge!(hash2.slice(hash2_special_keys))
72
+ hash1.merge!(hash2.slice(*hash2_special_keys))
62
73
  # 共用keys 数组去重
63
74
  common_keys.each do |key|
64
75
  hash1[key] = (hash1[key] | hash2[key]).uniq
@@ -66,5 +77,94 @@ module WebSandboxConsole
66
77
  hash1
67
78
  end
68
79
 
80
+ # 发现代码 中有 Logger.new(Rails.root.join('log', 'hubar')) 写法, 会 触发 File.open方法
81
+ # 封装后避免调用 File.open(禁用)
82
+ def sanitize_logger_new
83
+ Logger.instance_eval do
84
+ def new(logdev, shift_age = 0, shift_size = 1048576)
85
+ instance = allocate
86
+ instance.send(:initialize, logdev.to_s, shift_age, shift_size)
87
+ instance
88
+ end
89
+ end
90
+ end
91
+
92
+ # 净化 csv
93
+ def sanitize_csv
94
+ require 'csv' unless defined? CSV
95
+
96
+ CSV.instance_eval do
97
+ # 重写方法 以写日志方式 写数据
98
+ def open(filename, mode="r", **options)
99
+ # 无论输入什么路径 都只会在log下创建文件
100
+ basename = File.basename(filename, ".*")
101
+ file_path = "#{Rails.root}/log/#{basename}.csv"
102
+ logger = Logger.new(file_path)
103
+ logger.formatter = proc {|severity, datetime, progname, msg| msg}
104
+
105
+ logger.instance_exec do
106
+ # 支持类型 csv 数据写入方式
107
+ def << (data_arr)
108
+ self.info data_arr.join(",") + "\n"
109
+ end
110
+ end
111
+
112
+ yield(logger)
113
+ end
114
+ end
115
+ end
116
+
117
+ # 兼容文件缓存
118
+ def compatible_file_cache
119
+ ActiveSupport::Cache::FileStore.class_exec do
120
+ def write_entry(key, entry, options)
121
+ true
122
+ end
123
+
124
+ def delete_entry(key, options)
125
+ true
126
+ end
127
+ end
128
+ end
129
+
130
+ # 兼容翻译
131
+ def compatible_i18n_translate
132
+ I18n.instance_exec do
133
+ def translate(*args)
134
+ "ActiveRecord::RecordInvalid: 校验失败"
135
+ end
136
+ alias :t :translate
137
+ end
138
+ end
139
+
140
+ # 当拦截黑名单方法时提醒
141
+ def blacklist_method_remind
142
+ Kernel.class_exec do
143
+ # 发现此处method_missing Array 没有flatten方法
144
+ def flatten_arr(arr)
145
+ new_arr = []
146
+ arr.each do |e|
147
+ if e.is_a?(Array)
148
+ new_arr.concat(flatten_arr(e))
149
+ else
150
+ new_arr << e
151
+ end
152
+ end
153
+ new_arr
154
+ end
155
+
156
+ def method_missing(name,*params)
157
+ class_methods = WebSandboxConsole.class_method_blacklists.values
158
+ instance_methods = WebSandboxConsole.instance_method_blacklists.values
159
+
160
+ if flatten_arr([class_methods, instance_methods]).include?(name.to_sym)
161
+ msg = "PS:当前代码执行过程中可能调用了黑名单方法,若代码正常返回,请忽略此条提醒"
162
+ WebSandboxConsole.log_p(msg, true)
163
+ end
164
+ super
165
+ end
166
+ end
167
+ end
168
+
69
169
  end
70
170
  end
@@ -1,47 +1,146 @@
1
1
  module WebSandboxConsole
2
2
  class Sandbox
3
- attr_accessor :code
4
- attr_accessor :uuid
3
+ attr_accessor :code # 代码
4
+ attr_accessor :uuid # 唯一标识
5
+ attr_accessor :pass_auth # 是否通过授权
6
+ attr_accessor :exe_tmp_file # 执行临时文件(由code 组成的运行代码)
5
7
 
6
- def initialize(code = nil)
7
- @code = escape_single_quote_mark(code)
8
- @uuid = SecureRandom.uuid
8
+ def initialize(code = nil, pass_auth = false)
9
+ @code = code
10
+ @uuid = SecureRandom.uuid
11
+ @pass_auth = pass_auth.presence || false
12
+ @exe_tmp_file = "#{Rails.root}/tmp/sandbox/#{uuid}.rb"
9
13
  end
10
14
 
15
+ # 同步执行
11
16
  def evalotor
12
- `bundle exec rails runner '#{runner_code}'`
13
- get_result
17
+ evalotor_block do
18
+ exec_rails_runner
19
+ get_result
20
+ end
21
+ end
22
+
23
+ # 异步后台执行
24
+ def asyn_evalotor
25
+ evalotor_block do
26
+ Thread.new {exec_rails_runner}
27
+ ["已在后台执行,请耐心等待😊"]
28
+ end
29
+ end
30
+
31
+ # 执行结构块
32
+ def evalotor_block
33
+ begin
34
+ check_syntax
35
+ write_exe_tmp_file
36
+ yield
37
+ rescue SandboxError => e
38
+ [e.message]
39
+ rescue Exception => e
40
+ ["发生未知错误: #{e.inspect};#{e.backtrace[0..2].join('\r\n')}"]
41
+ end
14
42
  end
15
43
 
16
44
  def runner_code
17
45
  str =<<-CODE
18
- WebSandboxConsole.init_safe_env
19
46
  result = nil
20
47
  begin
21
- ActiveRecord::Base.transaction(requires_new: true) do
22
- result = eval(#{self.code.inspect})
23
- raise ActiveRecord::Rollback
24
- end
48
+ WebSandboxConsole.current_uuid("#{self.uuid}")
49
+ WebSandboxConsole.init_safe_env
50
+ WebSandboxConsole.logger_sql
51
+ #{self.pass_auth ? no_rollback_code : rollback_code}
25
52
  rescue Exception => e
26
- WebSandboxConsole.log_p(e, "#{self.uuid}")
53
+ WebSandboxConsole.log_p(e)
27
54
  rescue SyntaxError => e
28
- WebSandboxConsole.log_p(e, "#{self.uuid}")
55
+ WebSandboxConsole.log_p(e)
29
56
  end
30
- WebSandboxConsole.log_p(result, "#{self.uuid}")
57
+ WebSandboxConsole.log_p(result)
31
58
  CODE
32
59
  end
33
60
 
34
- def get_result
35
- last_10_lines = `tail -n 10 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
61
+ # 回滚code
62
+ def rollback_code
63
+ <<-EOF
64
+ ActiveRecord::Base.transaction(requires_new: true) do
65
+ result = eval(#{self.code.inspect})
66
+ raise ActiveRecord::Rollback
67
+ end
68
+ EOF
69
+ end
70
+
71
+ # 不回滚code
72
+ def no_rollback_code
73
+ <<-EOF
74
+ result = eval(#{self.code.inspect})
75
+ EOF
76
+ end
77
+
78
+ # 临时文件目录
79
+ def tmp_file_dir
80
+ File.dirname(self.exe_tmp_file)
81
+ end
82
+
83
+ # 添加临时文件目录
84
+ def add_tmp_file_dir
85
+ FileUtils.mkdir_p(tmp_file_dir) unless File.directory?(tmp_file_dir)
86
+ end
87
+
88
+ # 临时文件 需要清理?
89
+ def tmp_file_need_clean?
90
+ Dir["#{tmp_file_dir}/*"].count > 6
91
+ end
92
+
93
+ # 自动删除临时文件
94
+ def auto_clean_tmp_file
95
+ FileUtils.rm_rf(Dir["#{tmp_file_dir}/*"]) if tmp_file_need_clean?
96
+ end
97
+
98
+ # 写入 执行临时文件
99
+ def write_exe_tmp_file
100
+ add_tmp_file_dir
101
+ auto_clean_tmp_file
102
+ File.open(self.exe_tmp_file, 'w'){|f| f << runner_code}
103
+ end
104
+
105
+ # 准备检查语法
106
+ def prepare_check_syntax
107
+ add_tmp_file_dir
108
+ File.open(self.exe_tmp_file, 'w'){|f| f << self.code}
109
+ end
110
+
111
+ # 检查 语法
112
+ def check_syntax
113
+ prepare_check_syntax
114
+ unless `ruby -c #{self.exe_tmp_file}`.include?('Syntax OK')
115
+ raise SandboxError, "存在语法错误"
116
+ end
117
+ end
118
+
119
+ # 运行rails runner
120
+ def exec_rails_runner
121
+ @stdout = `RAILS_ENV=#{Rails.env} bundle exec rails runner #{self.exe_tmp_file}`
122
+ end
123
+
124
+ # 返回结果
125
+ def return_result_arr
126
+ last_10_lines = `tail -n 100 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
36
127
 
37
128
  last_10_lines.split("\n").map do |line|
38
129
  line.split("#{self.uuid}:").last.split("|||")
39
130
  end.flatten
40
131
  end
41
132
 
42
- # 转义单引号
43
- def escape_single_quote_mark(code)
44
- code.gsub(/'/,'"')
133
+ # 最终结果
134
+ def get_result
135
+ if @stdout.present?
136
+ stdout_arr = ['------------ 打印值 ----------']
137
+ stdout_arr.concat(@stdout.to_s.split("\n"))
138
+ stdout_arr << '------------ 返回值 ----------'
139
+ stdout_arr.concat(return_result_arr)
140
+ else
141
+ return_result_arr
142
+ end
45
143
  end
144
+
46
145
  end
47
146
  end