├── .gitignore ├── LICENSE ├── README.md ├── backend ├── __init__.py ├── core │ ├── __init__.py │ ├── apis │ │ ├── __init__.py │ │ └── runner.py │ ├── controllers │ │ └── __init__.py │ ├── models │ │ └── __init__.py │ ├── services │ │ ├── __init__.py │ │ └── runner.py │ ├── settings.py │ ├── utils │ │ ├── __init__.py │ │ └── uuid.py │ └── views │ │ └── __init__.py ├── run.py └── sh │ ├── run.sh │ ├── run_code.sh │ └── run_code_ex.sh ├── docs ├── .gitkeep └── reference.md ├── frontend ├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── README.md ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js ├── index.html ├── node_modules │ └── .gitkeep ├── package.json ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── Hello.vue │ ├── main.js │ └── router │ │ └── index.js ├── static │ └── .gitkeep └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js ├── log └── .gitkeep ├── requirements.txt └── run.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Compiled binary addons (http://nodejs.org/api/addons.html) 30 | build/Release 31 | 32 | # Dependency directories 33 | node_modules 34 | jspm_packages 35 | 36 | # Optional npm cache directory 37 | .npm 38 | 39 | # Optional eslint cache 40 | .eslintcache 41 | 42 | # Optional REPL history 43 | .node_repl_history 44 | 45 | # Output of 'npm pack' 46 | *.tgz 47 | 48 | # Yarn Integrity file 49 | .yarn-integrity 50 | 51 | ### VisualStudioCode template 52 | .vscode/* 53 | !.vscode/settings.json 54 | !.vscode/tasks.json 55 | !.vscode/launch.json 56 | !.vscode/extensions.json 57 | ### Python template 58 | # Byte-compiled / optimized / DLL files 59 | __pycache__/ 60 | *.py[cod] 61 | *$py.class 62 | 63 | # C extensions 64 | *.so 65 | 66 | # Distribution / packaging 67 | .Python 68 | env/ 69 | build/ 70 | develop-eggs/ 71 | dist/ 72 | downloads/ 73 | eggs/ 74 | .eggs/ 75 | lib/ 76 | lib64/ 77 | parts/ 78 | sdist/ 79 | var/ 80 | *.egg-info/ 81 | .installed.cfg 82 | *.egg 83 | 84 | # PyInstaller 85 | # Usually these files are written by a python script from a template 86 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 87 | *.manifest 88 | *.spec 89 | 90 | # Installer logs 91 | pip-log.txt 92 | pip-delete-this-directory.txt 93 | 94 | # Unit test / coverage reports 95 | htmlcov/ 96 | .tox/ 97 | .coverage 98 | .coverage.* 99 | .cache 100 | nosetests.xml 101 | coverage.xml 102 | *,cover 103 | .hypothesis/ 104 | 105 | # Translations 106 | *.mo 107 | *.pot 108 | 109 | # Django stuff: 110 | local_settings.py 111 | 112 | # Flask stuff: 113 | instance/ 114 | .webassets-cache 115 | 116 | # Scrapy stuff: 117 | .scrapy 118 | 119 | # Sphinx documentation 120 | docs/_build/ 121 | 122 | # PyBuilder 123 | target/ 124 | 125 | # Jupyter Notebook 126 | .ipynb_checkpoints 127 | 128 | # pyenv 129 | .python-version 130 | 131 | # celery beat schedule file 132 | celerybeat-schedule 133 | 134 | # dotenv 135 | .env 136 | 137 | # virtualenv 138 | .venv/ 139 | venv/ 140 | ENV/ 141 | 142 | # Spyder project settings 143 | .spyderproject 144 | 145 | # Rope project settings 146 | .ropeproject 147 | ### Linux template 148 | *~ 149 | 150 | # temporary files which can be created if a process still has a handle open of a deleted file 151 | .fuse_hidden* 152 | 153 | # KDE directory preferences 154 | .directory 155 | 156 | # Linux trash folder which might appear on any partition or disk 157 | .Trash-* 158 | 159 | # .nfs files are created when an open file is removed but is still being accessed 160 | .nfs* 161 | ### Example user template template 162 | ### Example user template 163 | 164 | # IntelliJ project files 165 | out 166 | gen### macOS template 167 | *.DS_Store 168 | .AppleDouble 169 | .LSOverride 170 | 171 | # Icon must end with two \r 172 | Icon 173 | 174 | 175 | # Thumbnails 176 | ._* 177 | 178 | # Files that might appear in the root of a volume 179 | .DocumentRevisions-V100 180 | .fseventsd 181 | .Spotlight-V100 182 | .TemporaryItems 183 | .Trashes 184 | .VolumeIcon.icns 185 | .com.apple.timemachine.donotpresent 186 | 187 | # Directories potentially created on remote AFP share 188 | .AppleDB 189 | .AppleDesktop 190 | Network Trash Folder 191 | Temporary Items 192 | .apdisk 193 | ### Windows template 194 | # Windows image file caches 195 | Thumbs.db 196 | ehthumbs.db 197 | 198 | # Folder config file 199 | Desktop.ini 200 | 201 | # Recycle Bin used on file shares 202 | $RECYCLE.BIN/ 203 | 204 | # Windows Installer files 205 | *.cab 206 | *.msi 207 | *.msm 208 | *.msp 209 | 210 | # Windows shortcuts 211 | *.lnk 212 | ### JetBrains template 213 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 214 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 215 | 216 | # User-specific stuff: 217 | .idea/tasks.xml 218 | 219 | # Sensitive or high-churn files: 220 | .idea/dataSources/ 221 | .idea/dataSources.ids 222 | .idea/dataSources.xml 223 | .idea/dataSources.local.xml 224 | .idea/sqlDataSources.xml 225 | .idea/dynamic.xml 226 | .idea/uiDesigner.xml 227 | 228 | # Gradle: 229 | .idea/gradle.xml 230 | .idea/libraries 231 | 232 | # Mongo Explorer plugin: 233 | .idea/mongoSettings.xml 234 | 235 | ## File-based project format: 236 | *.iws 237 | 238 | ## Plugin-specific files: 239 | 240 | # IntelliJ 241 | /out/ 242 | 243 | # mpeltonen/sbt-idea plugin 244 | .idea_modules/ 245 | 246 | # JIRA plugin 247 | atlassian-ide-plugin.xml 248 | 249 | # Crashlytics plugin (for Android Studio and IntelliJ) 250 | com_crashlytics_export_strings.xml 251 | crashlytics.properties 252 | crashlytics-build.properties 253 | fabric.properties 254 | 255 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 hh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # code-runner 2 | 基于 Flask, Docker 实现的在线编程网站. 3 | 4 | 5 | 6 | ## 项目依赖: 7 | 8 | - 前端: 9 | - vue.js 10 | - [CodeMirror](http://codemirror.net/demo/theme.html) 11 | - [vue-codemirror](https://github.com/surmon-china/vue-codemirror) 12 | - [vue-codemirror: 文档](https://surmon-china.github.io/vue-codemirror/) 13 | - 后端: 14 | - [docker-py](https://github.com/docker/docker-py) 15 | - [文档](https://docker-py.readthedocs.io/en/stable/) 16 | - [Pika](https://github.com/pika/pika) 17 | - [celery](https://github.com/celery/celery) 18 | - flask 19 | - docker 20 | 21 | ## 开发环境搭建: 22 | 23 | 24 | 25 | ### 1. 前端环境初始化: 26 | 27 | ```bash 28 | 29 | # vue-cli · Generated "frontend". 30 | # To get started: 31 | 32 | cd frontend 33 | npm install 34 | npm run dev 35 | 36 | 37 | ``` 38 | 39 | ### 2. 拉取 docker 容器: 40 | 41 | - [daocloud - gcc:4.9.2 镜像](https://hub.daocloud.io/repos/9bd717cf-7e5b-4943-843a-1c9104cb596f) 42 | - [配置 Docker 加速器](https://www.daocloud.io/mirror#accelerator-doc) 43 | 44 | 45 | ```bash 46 | 47 | docker pull daocloud.io/library/gcc:4.9.2 48 | 49 | 50 | ``` 51 | 52 | ### 3. 运行项目后台服务: 53 | 54 | ```bash 55 | # server: 56 | 57 | python 58 | 59 | ``` 60 | 61 | 62 | 63 | ## 参考: 64 | 65 | - [Docker SDK for Python](https://docker-py.readthedocs.io/en/stable/) 66 | - [about docker run ](https://github.com/docker/docker-py/issues/933) 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /backend/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /backend/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhstore/code-runner/064474908ac0abefebbc7d9759bc8ae2e30721f2/backend/core/__init__.py -------------------------------------------------------------------------------- /backend/core/apis/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /backend/core/apis/runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from flask import request 5 | from flask_restful import Resource, reqparse, abort 6 | 7 | from backend.core.services.runner import CodeRunner 8 | from backend.core.settings import ContainerConfig 9 | 10 | parser = reqparse.RequestParser() 11 | 12 | # 参数校验: 13 | parser.add_argument("lang", type=str) 14 | parser.add_argument("code", type=str) 15 | 16 | 17 | class Runner(Resource): 18 | def post(self): 19 | #data = request.get_json() 20 | data = parser.parse_args() 21 | lang = data.get("lang").lower() # 语言类型不区分大小写 22 | code = data.get("code") 23 | 24 | # 编程语言类型不支持: 25 | if lang not in ContainerConfig.language_support: 26 | abort(400) # 参数不合法, 直接返回 [400 Bad Request] 27 | 28 | r = CodeRunner(code, lang) 29 | return r.run() 30 | 31 | -------------------------------------------------------------------------------- /backend/core/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhstore/code-runner/064474908ac0abefebbc7d9759bc8ae2e30721f2/backend/core/controllers/__init__.py -------------------------------------------------------------------------------- /backend/core/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhstore/code-runner/064474908ac0abefebbc7d9759bc8ae2e30721f2/backend/core/models/__init__.py -------------------------------------------------------------------------------- /backend/core/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhstore/code-runner/064474908ac0abefebbc7d9759bc8ae2e30721f2/backend/core/services/__init__.py -------------------------------------------------------------------------------- /backend/core/services/runner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import docker 5 | from requests.exceptions import ReadTimeout 6 | 7 | from backend.core.settings import ContainerConfig 8 | from backend.core.utils.uuid import create_uuid 9 | 10 | # 保存待执行的源码文件: 11 | class CodeWriter(ContainerConfig): 12 | def __init__(self, content, file_type, java_class_name=None): 13 | self.file_name = create_uuid() # 随机生成 14 | self.file_type = file_type 15 | self.java_class_name = java_class_name 16 | 17 | # 保存代码文件 18 | self.save_code(content) 19 | # 保存命令 20 | self.cmd = self.save_cmd() 21 | 22 | @property 23 | def file_path(self): 24 | """文件名称+后缀拼接 25 | 26 | :return: 27 | """ 28 | lang = self.language_support.get(self.file_type) 29 | 30 | if self.java_class_name: 31 | fp = "{}_{}.{}".format(self.file_name, self.java_class_name, lang) 32 | else: 33 | fp = "{}.{}".format(self.file_name, lang) 34 | 35 | return fp 36 | 37 | def save_code(self, content): 38 | """保存代码文件 39 | :param content: 代码内容 40 | :return: 41 | """ 42 | # 文件保存的绝对路径: 43 | file_path = os.path.join(self.volume_path, self.file_path) 44 | 45 | with open(file_path, mode="w", encoding="utf8") as f: 46 | f.write(content[:1024*64]) # 文件大小限定64k 47 | 48 | def save_cmd(self): 49 | """保存代码执行的 shell 命令 50 | :return: 51 | """ 52 | # 容器中执行文件的绝对路径: 53 | file_path = os.path.join(self.volume_bind_path, self.file_path) 54 | 55 | cmd = "/bin/bash {0}/{1} {2} {3}/{4} {5} {5}".format( 56 | self.volume_bind_path, 57 | self.shell_01, 58 | self.timeout, 59 | self.volume_bind_path, 60 | self.shell_02, 61 | file_path 62 | ) 63 | return cmd 64 | 65 | 66 | # 启动容器: 67 | class ContainerWorker(ContainerConfig): 68 | """ 69 | 源码中关于 volume 的配置参数设置: 70 | 71 | container_id = cli.create_container( 72 | 'busybox', 'ls', volumes=['/mnt/vol1', '/mnt/vol2'], 73 | host_config=cli.create_host_config(binds={ 74 | '/home/user1/': { 75 | 'bind': '/mnt/vol2', 76 | 'mode': 'rw', 77 | }, 78 | '/var/www': { 79 | 'bind': '/mnt/vol1', 80 | 'mode': 'ro', 81 | } 82 | }) 83 | ) 84 | 85 | 86 | """ 87 | def __init__(self, cmd): 88 | self.client = docker.APIClient() 89 | # 容器待执行指令: 90 | self.cmd = cmd 91 | 92 | def create(self): 93 | #self.cmd = "ls /code-runner" 94 | 95 | # 容器共享 volume 配置参数设置: 96 | container = self.client.create_container( 97 | image=self.image_name, 98 | command=self.cmd, 99 | volumes=[self.volume_path], # 只定义了共享目录, 下一个配置中设置目录映射 100 | host_config=self.client.create_host_config(binds={ 101 | self.volume_path: { 102 | 'bind': self.volume_bind_path, # 映射到容器中的路径 103 | 'mode': self.volume_mode, 104 | }, 105 | }) 106 | ) 107 | return container 108 | 109 | def run(self): 110 | ctr = self.create() 111 | 112 | self.client.start(container=ctr.get("Id")) # 启动容器 113 | try: 114 | self.client.wait(container=ctr, timeout=self.timeout) # 等待执行, 超时判断 115 | except ReadTimeout as e: 116 | print("too slow, killed!") 117 | self.client.kill(container=ctr) # 超时, kill 掉 118 | 119 | ctr_logs = self.client.logs(container=ctr.get("Id")) 120 | 121 | self.client.stop(ctr) # 退出容器 122 | self.client.remove_container(ctr, v=True, force=True) # 清理容器 123 | return ctr_logs[:1024*64] # 截取日志长度,保留64k 124 | 125 | # 代码执行服务: 126 | class CodeRunner(object): 127 | def __init__(self, content, file_type, java_class_name=None): 128 | self.cw = CodeWriter(content, file_type, java_class_name) 129 | self.cmd = self.cw.cmd 130 | self.runner = ContainerWorker(self.cmd) 131 | 132 | def run(self): 133 | log = self.runner.run() 134 | return self.parse(log) 135 | 136 | def parse(self, logs): 137 | sep = "=1=2=3=4=5=== I Am A Dividing Line ! ===5=4=3=2=1=" 138 | flag1 = "RESULT: " 139 | flag2 = "STATUS_CODE: " 140 | flag3 = "TIME_COST: " 141 | 142 | if isinstance(logs, bytes): 143 | logs = logs.decode() 144 | 145 | values = logs.split(sep) 146 | #print(values) 147 | _, v_result, v_status, v_time = values 148 | 149 | result = { 150 | "result": v_result.strip().lstrip(flag1).strip(), 151 | "status": v_status.strip().lstrip(flag2).strip(), 152 | "time": v_time.strip().lstrip(flag3).strip() 153 | } 154 | print(result) 155 | return result 156 | 157 | 158 | if __name__ == '__main__': 159 | image_name = "daocloud.io/library/gcc:4.9.2" 160 | code = """ 161 | 162 | import datetime 163 | import os 164 | print("hello world!") 165 | #print(os.getcwd()) 166 | print(datetime.datetime.now()) 167 | 168 | 169 | """ 170 | 171 | code_timeout = """ 172 | 173 | import time 174 | time.sleep(4) 175 | print("can you see me?") 176 | 177 | """ 178 | 179 | a = CodeWriter(code, "python") 180 | 181 | 182 | runner = CodeRunner(code, "python") 183 | runner.run() 184 | 185 | # 超时判断: 186 | runner2 = CodeRunner(code_timeout, "python") 187 | runner2.run() 188 | -------------------------------------------------------------------------------- /backend/core/settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | # docker 容器 默认配置项: 6 | class ContainerConfig(object): 7 | # 容器镜像名: 8 | image_name = "daocloud.io/library/gcc:4.9.2" 9 | 10 | # 宿主机共享目录: 11 | volume_path = "/iDockerShare/codebox" #"/code-runner" 12 | # 映射到容器中的路径: 13 | volume_bind_path = "/code-runner" # /code-runner 14 | volume_mode = "rw" 15 | 16 | shell_01 = "run.sh" 17 | shell_02 = "run_code.sh" 18 | 19 | # 支持的编程语言: 20 | language_support = { 21 | "python": "py", 22 | "ruby": "rb", 23 | "c": "c", 24 | "c++": "cpp", 25 | "java": "java", 26 | "go": "go", 27 | "perl": "pl", 28 | } 29 | 30 | # 程序执行超时时间: 31 | timeout = 3 32 | -------------------------------------------------------------------------------- /backend/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /backend/core/utils/uuid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import time 5 | import random 6 | 7 | 8 | # 生成随机ID 9 | def create_uuid(): 10 | ts = int(time.time() * 1000) - 1400000000000 11 | value = (ts << 16) + random.randint(0, 65535) 12 | return hex(value)[2:-1] 13 | -------------------------------------------------------------------------------- /backend/core/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhstore/code-runner/064474908ac0abefebbc7d9759bc8ae2e30721f2/backend/core/views/__init__.py -------------------------------------------------------------------------------- /backend/run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | import time 6 | from flask import Flask, request, jsonify 7 | from flask_restful import Api 8 | 9 | from backend.core.apis.runner import Runner 10 | 11 | app = Flask(__name__) 12 | api = Api(app) 13 | 14 | # restful API: 15 | 16 | api.add_resource(Runner, '/run') 17 | 18 | 19 | @app.route("/") 20 | def index(): 21 | current_time = time.strftime("Current time:\n%Z # %Y-%m-%d # %p %I:%M:%S", 22 | time.localtime(time.time())) 23 | 24 | return "
Hello, visitor.\r\n %s" % current_time 25 | 26 | 27 | if __name__ == '__main__': 28 | app.run(host='0.0.0.0', port=5000, debug=True) 29 | -------------------------------------------------------------------------------- /backend/sh/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | kill_time=$1 3 | sh_file=$2 4 | code_file=$3 5 | 6 | ################################################### 7 | # msg: 8 | SEP="=1=2=3=4=5=== I Am A Dividing Line ! ===5=4=3=2=1=" 9 | ERROR_LOG="RESULT: timeout! killed! ${SEP} STATUS_CODE: -1 ${SEP} TIME_COST: 0" 10 | 11 | ################################################### 12 | 13 | # run 14 | timeout -s 9 ${kill_time} ${sh_file} ${code_file} 15 | 16 | ################################################### 17 | 18 | # kill judge. 19 | if [ $? != 0 ] 20 | then 21 | echo "${ERROR_LOG}" 22 | fi 23 | 24 | 25 | 26 | # clean 27 | #rm -rf ${code_file} ${code_file}.* 28 | -------------------------------------------------------------------------------- /backend/sh/run_code.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | code_file=$1 3 | 4 | ###########error log info : ################ 5 | SEP="=1=2=3=4=5=== I Am A Dividing Line ! ===5=4=3=2=1=" 6 | 7 | ERROR_1="you must provide a file!" 8 | ERROR_2="file does not exist!" 9 | ERROR_3="invalid language!" 10 | 11 | ERROR_LOG_1="${SEP} RESULT: ${ERROR_1} ${SEP} STATUS_CODE: -2 ${SEP} TIME_COST: 0" 12 | ERROR_LOG_2="${SEP} RESULT: ${ERROR_2} ${SEP} STATUS_CODE: -3 ${SEP} TIME_COST: 0" 13 | ERROR_LOG_3="${ERROR_3} ${SEP} STATUS_CODE: -4 ${SEP} TIME_COST: 0" 14 | OK_LOG="${SEP} STATUS_CODE: 1 ${SEP} TIME_COST: 0" 15 | 16 | 17 | ########## error judge : #################### 18 | if [ -z $1 ];then 19 | echo ${ERROR_LOG_1} 20 | exit 1 21 | fi 22 | 23 | if [ ! -f $1 ];then 24 | echo ${ERROR_LOG_2} 25 | exit 1 26 | fi 27 | 28 | ########################################### 29 | 30 | # create code_folder 31 | 32 | file="${code_file##*/}" 33 | folder="${file%%.*}" 34 | extension="${file##*.}" 35 | 36 | 37 | mkdir ${folder} 38 | chmod 777 ${folder} 39 | mv ${code_file} ${folder} 40 | code_path="./${folder}/${folder}.${extension}" 41 | 42 | 43 | ########################################### 44 | # test log: 45 | 46 | #echo "Server Log:" 47 | #echo "mkdir Folder name: ${folder}" 48 | #rm -rf "/iDockerShare" 49 | #echo "Current Folder: $(pwd)" 50 | ##echo "Current Folder Content: $(ls -a)" 51 | #echo "Current Folder Content: $(ls)" 52 | #echo "Code Path: ${code_path}" 53 | 54 | ######### run code : ####################### 55 | 56 | echo "${SEP} RESULT: " 57 | 58 | TIME_START=`date +%s%N`; #time_countion 59 | 60 | case "$extension" in 61 | "c") 62 | gcc -o ${code_path}.out -g ${code_path} &&./${code_path}.out 63 | ;; 64 | "cpp") 65 | g++ -o ${code_path}.out -g ${code_path} &&./${code_path}.out 66 | ;; 67 | "java") 68 | java_class=${code_path##*_} 69 | java_path="${folder}/${java_class}" 70 | mv ${code_path} ${java_path} 71 | cd ${folder} 72 | javac ${java_class} && java ${java_class%.*} 73 | cd .. 74 | ;; 75 | "go") 76 | go run ${code_path} 77 | ;; 78 | "pl") 79 | perl ${code_path} 80 | ;; 81 | "py") 82 | python ${code_path} 83 | ;; 84 | "rb") 85 | ruby ${code_path} 86 | ;; 87 | *) 88 | echo ${ERROR_LOG_3} 89 | ;; 90 | esac 91 | 92 | ########################################### 93 | 94 | echo "${SEP} STATUS_CODE: $?" 95 | 96 | TIME_END=`date +%s%N`; 97 | time=$((TIME_END-TIME_START)) 98 | time=`expr ${time} / 1000000` 99 | 100 | echo "${SEP} TIME_COST: ${time}" 101 | 102 | ########################################### 103 | -------------------------------------------------------------------------------- /backend/sh/run_code_ex.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | prog=$1 3 | 4 | ###########error log info : ################ 5 | SEP="@@--@@--codebox--@@--@@" 6 | 7 | ERROR_1="you must provide a file!" 8 | ERROR_2="file does not exist!" 9 | ERROR_3="invalid language!" 10 | 11 | ERROR_LOG_1="INFO: ${ERROR_1} ${SEP} STATUS_CODE: 1 ${SEP} TIME_COST: 0" 12 | ERROR_LOG_2="INFO: ${ERROR_2} ${SEP} STATUS_CODE: 1 ${SEP} TIME_COST: 0" 13 | ERROR_LOG_3="INFO: ${ERROR_3} ${SEP} STATUS_CODE: 1 ${SEP} TIME_COST: 0" 14 | 15 | ##########error judge : #################### 16 | if [ -z $1 ];then 17 | echo ${ERROR_LOG_1} 18 | exit 1 19 | fi 20 | 21 | if [ ! -f $1 ];then 22 | echo ${ERROR_LOG_2} 23 | exit 1 24 | fi 25 | 26 | #########run code : ####################### 27 | 28 | echo "INFO: " 29 | TIME_START=`date +%s%N`; #time_countion 30 | 31 | extension="${prog##*.}" 32 | case "$extension" in # 多版本支持 33 | "c99") 34 | gcc -o $prog.out -g $prog &&./$prog.out 35 | ;; 36 | "c11") 37 | gcc -o $prog.out -g $prog &&./$prog.out # 待修改C11编译选项 38 | ;; 39 | "cpp99") 40 | g++ -o $prog.out -g $prog &&./$prog.out 41 | ;; 42 | "cpp11") 43 | g++ -o $prog.out -g $prog &&./$prog.out # 待修改C++11编译选项 44 | ;; 45 | "java") 46 | javac $prog && java ${prog%.*} # 待修改 47 | ;; 48 | "py2") 49 | python $prog # 待修改 50 | ;; 51 | "py3") 52 | python $prog # 待修改 53 | ;; 54 | "rb") 55 | ruby $prog 56 | ;; 57 | "go") 58 | go run $prog 59 | ;; 60 | "pl") 61 | perl $prog 62 | ;; 63 | *) 64 | echo ${ERROR_LOG_3} 65 | ;; 66 | esac 67 | 68 | ########################################### 69 | 70 | echo "${SEP} STATUS_CODE: $?" 71 | TIME_END=`date +%s%N`; 72 | time=$((TIME_END-TIME_START)) 73 | time=`expr $time / 1000000` 74 | 75 | echo "${SEP} TIME_COST: ${time}" 76 | 77 | ########################################### 78 | -------------------------------------------------------------------------------- /docs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhstore/code-runner/064474908ac0abefebbc7d9759bc8ae2e30721f2/docs/.gitkeep -------------------------------------------------------------------------------- /docs/reference.md: -------------------------------------------------------------------------------- 1 | 2 | # 参考: 3 | 4 | 5 | ## Flask-RESTful API 6 | 7 | - [ Flask-RESTful API ](http://www.pythondoc.com/Flask-RESTful/quickstart.html) 8 | - [install](https://flask-restful.readthedocs.io/en/0.3.5/installation.html) 9 | - [POST 提交参数合法性校验](http://flask-restful.readthedocs.io/en/0.3.5/quickstart.html#argument-parsing) 10 | - [完整示例, 给出最佳实践](http://flask-restful.readthedocs.io/en/0.3.5/quickstart.html#full-example) 11 | 12 | ```bash 13 | 14 | pip install flask-restful 15 | 16 | 17 | ``` 18 | 19 | 20 | ## API 设计规范: 21 | 22 | - [跟着 Github 学习 Restful HTTP API 设计](http://cizixs.com/2016/12/12/restful-api-design-guide) 23 | 24 | 25 | -------------------------------------------------------------------------------- /frontend/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | test/unit/coverage 8 | test/e2e/reports 9 | selenium-debug.log 10 | -------------------------------------------------------------------------------- /frontend/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # frontend 2 | 3 | > A Vue.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /frontend/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /frontend/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8080, 27 | autoOpenBrowser: true, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /frontend/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /frontend/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |