Skip to content

linwebs/appinventor-sources

 
 

Repository files navigation

title tags
CHSH AI2 Server Note
AI2

CHSH AI2 Server Note

https://ai2.linwebs.tw/
hackmd: https://hackmd.io/@linwebstw/BklO1UBEL

[TOC]

說明

以下範例目錄以 /data-disk/ai2-server/appinventor-sources-20210223/ 為例
Domain 以 ai2.linwebs.tw 為例

AI2 Server 登入網址 (Proxy)

指定使用者名稱登入網址

https://ai2.linwebs.tw/login/google

AI2 Server 更新(2021/3)

  • 查看 remote
     (local)$ git remote -v
    
  • 新增 AI2 官方 source
     (local)$ git remote add mit-cml https://github.com/mit-cml/appinventor-sources.git
    
  • 取得更新
     (local)$ git fetch mit-cml
    
  • commit 更新
     (local)$ git commit -am "commit message"
    
  • push 回 GitHub
     (local)$ git push
    
  • SSH 進入 Server
     (local)$ ssh hostname -l username
    
  • 關閉 ai2 服務
     (server)$ sudo screen -r ai2-sys-2021
     [Ctrl + C]
     [Ctrl + A] [D] # 退出
    
  • 關閉 ai2 打包服務
     (server)$ sudo screen -r ai2-pack-2021
     [Ctrl + C]
     [Ctrl + A] [D] # 退出
    
  • ※ Server 先備份(非常重要:warning: )
     (server)$ cd /data-disk/ai2-server/
     (server)$ cp appinventor-sources-20210223 appinventor-sources-backup -R
    
  • 存檔備份
     (server)$ cd /data-disk/ai2-server/
     (server)$ cp appinventor-sources-20210223/appinventor/appengine/build/war/WEB-INF/appengine-generated AllSource/Source-appinventor-sources-20210223
    
  • Server pull 回更新
     (server)$ cd /data-disk/ai2-server/appinventor-sources-20210223
     (server)$ git pull
    
  • ant 重新建置
     (server)$ cd /data-disk/ai2-server/appinventor-sources-20210223/appinventor
     (server)$ ant clean all # 請注意,此動作會清除使用者存檔
    
  • 重啟 ai2 服務
     (server)$ sudo screen -r ai2-sys-2021 # ai2 server
     (server)$ /opt/google-cloud-sdk/bin/java_dev_appserver.sh -p 8888 -a 0.0.0.0 /data-disk/ai2-server/appinventor-sources-20210223/ainventor/appengine/build/war/
    
  • 重啟 ai2 打包服務
     (server)$ sudo screen -r ai2-pack-2021
     (server)$ cd /data-disk/ai2-server/appinventor-sources-20210223/appinventor/buildserver
     (server)$ ant RunLocalBuildServer
    
  • Reference:
    1. 怎麼跟上當初 fork 專案的進度? - 為你自己學 Git
    2. Pull 下載更新 - 為你自己學 Git

AI2 Server Web Root Path

/data-disk/ai2-server/appinventor-sources-20210223/appinventor/appengine/build/war

AI2 Server 轉址到Apache系統登入

需新增以下網址轉址至login.jsp,以免從AI2 Server登出後,看到原生登入畫面

/data-disk/ai2-server/appinventor-sources-20210223/appinventor/appengine/build/war/login.jsp

<%
response.sendRedirect("https://ai2.chsh.chc.edu.tw");
%>

AI2 Server Logo

Logo更改需更改以下6個檔案

Logo原始檔位址: https://ai2.chsh.chc.edu.tw/images/codi_long.png

https://ai2.chsh.chc.edu.tw/images/logo2.png

小圖 (AI2): AI2 Logo

小圖(英文) (AI2): AI2 Logo

大圖 (reference): AI2 Big Logo

修改請參照下方 AI2系統檔案存放位置 指示進行修改

Build Server Status (Proxy)

BuildServer 運行狀況 https://ai2.linwebs.tw/status/buildserver/health

BuildServer 即時狀況 https://ai2.linwebs.tw/status/buildserver/vars

彰中AI2 TinyWebDB

網址: https://ai2.linwebs.tw/db/

自動啟動TinyWebDB腳本位置

$ sudo vim /etc/rc.local

用root權限新增一個名稱為[ai2db]的 screen,並執行指令

AI2 Server自動啟動

自動啟動彰中AI2 Server腳本位置

$ sudo vim /etc/rc.local

用root權限新增 一個名稱為[ai2sys]的screen,執行AI2 Server
一個名稱為[ai2pack]的screen,執行LocalBuildServer
另外一個名稱為[ai2db]的 screen,是執行TinyWebDB (非必要)

screen -dmS ai2-sys sh
screen -S ai2-sys -p 0 -X stuff "/data-disk/ai2-server/appengine-java-sdk-1.9.77/bin/dev_appserver.sh -p 8888 -a 0.0.0.0 /data-disk/ai2-server/appinventor-sources-20210223/appinventor/appengine/build/war/
"

screen -dmS ai2-pack sh
screen -S ai2-pack -p 0 -X stuff "cd /data-disk/ai2-server/appinventor-sources-20210223/appinventor/buildserver/
sleep 30
ant RunLocalBuildServer address=ai2.chsh.chc.edu.tw
"

screen -dmS ai2-db sh
screen -S ai2-db -p 0 -X stuff "python2.7 /data-disk/ai2db/appengine_py/dev_appserver.py --port 9980 --host 0.0.0.0 /data-disk/ai2db/appinventordb/
"

Apache Proxy 設定

設定檔位置

/etc/httpd/conf.d/vhost-2-ai2-linwebs-tw.conf

# ai2.linwebs.tw
<VirtualHost *:80>
    ServerName ai2.linwebs.tw
    ServerAdmin admin@linwebs.tw
    Redirect permanent / https://ai2.linwebs.tw/
#    ProxyRequests Off
#    ProxyPreserveHost On
    ErrorLog logs/ai2-linwebs-error_log
    CustomLog logs/ai2-linwebs-access_log common
</VirtualHost>

# ai2.linwebs.tw SSL
<VirtualHost *:443>
    ServerName ai2.linwebs.tw
    ServerAdmin admin@linwebs.tw
    ProxyRequests Off
    ProxyPreserveHost On
    <Location /db/>
        ProxyPass http://localhost:9980/
        ProxyPassReverse http://localhost:9980/
    </Location>
    <Location /status/>
        ProxyPass http://localhost:9990/
        ProxyPassReverse http://localhost:9990/
    </Location>
    <Location />
        ProxyPass http://localhost:8888/
        ProxyPassReverse http://localhost:8888/
    </Location>
    ErrorLog logs/ai2-linwebs-ssl-error_log
    CustomLog logs/ai2-linwebs common
    SSLEngine on
    SSLProxyEngine on
    SSLProtocol ALL -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLHonorCipherOrder on
    SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    SSLCertificateFile /etc/letsencrypt/live/ai2.linwebs.tw/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/ai2.linwebs.tw/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/ai2.linwebs.tw/chain.pem
    SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
</VirtualHost>

SSL 自動更新腳本 # sudo crontab -e

每周一凌晨3:10自動更新SSL憑證

10 3 * * 1 /opt/letsencrypt/letsencrypt-auto certonly --apache --renew-by-default -d ai2.linwebs.tw && service httpd restart

AI2系統檔案存放位置

檔案存放對應路徑:
Web Path: https://ai2.linwebs.tw/static/images/codi_long.png Document Root:

/data-disk/ai2-server/appinventor-sources-20210223/appinventor/appengine/build/war/static/images

AI2 Server 更新(舊版)

切換至ai2 server目錄

$ cd /data-disk/ai2-server

取得source檔:

$ git clone https://github.com/mit-cml/appinventor-sources.git

更改source檔名稱: (yyyymmdd填入年-月-日)

$ mv appinventor-sources appinventor-sources-yyyymmdd

取得最新google app engine java 網址

$ wget https://cloud.google.com/appengine/docs/standard/java/download

解壓縮google app engine (xx填入版本號) https://cloud.google.com/appengine/docs/standard/java/download

$ unzip appengine-java-sdk-1.9.xx.zip

更改兩目錄權限為777

$ chmod 777 appengine-java-sdk-1.9.xx appinventor-sources-yyyymmdd -R

進入ai2 source目錄

$ cd appinventor-sources-yyyymmdd/

submodule update

$ git submodule update --init

進入ai2 目錄

$ cd appinventor

編譯ai2 source檔

$ ant

複製先前版本使用者資料

$ cp /data-disk/ai2-server/appinventor-sources-20180124/appinventor/appengine/build/war/WEB-INF/appengine-generated /data-disk/ai2-server/appinventor-sources-yyyymmdd/appinventor/appengine/build/war/WEB-INF/appengine-generated -r

ant MakeAuthKey

:::warning :warning: 此指令已經不須再執行了,執行會使原本的使用者都無法登入 :::

AI2 系統須有 auth key 才可運作 預設是存在執行的使用者根目錄,所以使用 sudo 執行時是放在以下資料夾內

/root/.appinventor

執行指令

$ cd /data-disk/ai2-server/appinventor-sources-yyyymmdd/appinventor/
$ ant MakeAuthKey

與原始 ai2 source 不同的檔案

以下內容撰寫中,請暫時不要使用 註: 以下 $AI2_SOURCE_PATH 的值為 /data-disk/ai2-server/appinventor-sources-yyyymmdd

  • 所有語言

    $AI2_SOURCE_PATH/appinventor/appengine/src/com/google/appinventor/client/languages.json

    • 繁「体」中文 => 繁體中文
  • 繁體中文翻譯

    $AI2_SOURCE_PATH/appinventor/appengine/src/com/google/appinventor/client/OdeMessages_zh_TW.properties

  • web 設定檔

    $AI2_SOURCE_PATH/appinventor//appengine/war/WEB-INF/appengine-web.xml

    • 登入參數
    • 靜態網址... 等

新 google-cloud-sdk

/opt/google-cloud-sdk/bin/java_dev_appserver.sh

常用資源路徑

  • logo.png
    • /appinventor/appengine/war/static/images/
  • codi_long.png
    • /appinventor/appengine/war/static/images/codi_long.png
    • /appinventor/docs/markdown/reference/blocks/images/codi_long.png
    • /appinventor/docs/markdown/reference/components/images/codi_long.png
    • /appinventor/docs/html/reference/blocks/images/codi_long.png
    • /appinventor/docs/html/reference/components/images/codi_long.png
  • 圖片 /appinventor/appengine/src/com/google/appinventor/images/
  • 語言 /appinventor/appengine/src/com/google/appinventor/client/

舊 crontab

00 4 1 4,8,12 * sh /data-disk/ai2-server/update/update.sh > /data-disk/ai2-server/update/update.log

模擬器 error code

solution: https://community.appinventor.mit.edu/t/aistarter-update-mit-ai2-companion2-to-2-58au/7587

Error from Companion: java.lang.RuntimeException: invalid syntax in eval form: :9:1: caught exception in inliner for # - java.lang.RuntimeException: no such class: com.google.appinventor.components.runtime.com.google.appinventor.components.runtime.Label gnu.bytecode.ObjectType.getReflectClass(ObjectType.java:148) gnu.bytecode.ClassType.getModifiers(ClassType.java:103) gnu.bytecode.ClassType.isInterface(ClassType.java:471) gnu.expr.InlineCalls.checkType(InlineCalls.java:56) gnu.expr.InlineCalls.visit(InlineCalls.java:49) gnu.expr.InlineCalls.visitSetExpValue(InlineCalls.java:363) gnu.expr.InlineCalls.visitSetExpValue(InlineCalls.java:28) gnu.expr.ExpVisitor.visitSetExp(ExpVisitor.java:114) gnu.expr.InlineCalls.visitSetExp(InlineCalls.java:369) gnu.expr.InlineCalls.visitSetExp(InlineCalls.java:28) gnu.expr.SetExp.visit(SetExp.java:406) gnu.expr.ExpVisitor.visit(ExpVisitor.java:55) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visitBeginExp(InlineCalls.java:272) gnu.expr.InlineCalls.visitBeginExp(InlineCalls.java:28) gnu.expr.BeginExp.visit(BeginExp.java:156) gnu.expr.ExpVisitor.visit(ExpVisitor.java:51) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visitBeginExp(InlineCalls.java:272) gnu.expr.InlineCalls.visitBeginExp(InlineCalls.java:28) gnu.expr.BeginExp.visit(BeginExp.java:156) gnu.expr.ExpVisitor.visit(ExpVisitor.java:51) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visitLetExp(InlineCalls.java:317) gnu.expr.InlineCalls.visitLetExp(InlineCalls.java:28) gnu.expr.LetExp.visit(LetExp.java:207) gnu.expr.ExpVisitor.visit(ExpVisitor.java:51) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visit(InlineCalls.java:28) gnu.expr.LambdaExp.visitChildrenOnly(LambdaExp.java:1664) gnu.expr.LambdaExp.visitChildren(LambdaExp.java:1651) gnu.expr.InlineCalls.visitScopeExp(InlineCalls.java:279) gnu.expr.InlineCalls.visitLambdaExp(InlineCalls.java:349) gnu.expr.InlineCalls.visitLambdaExp(InlineCalls.java:28) gnu.expr.LambdaExp.visit(LambdaExp.java:1640) gnu.expr.ExpVisitor.visit(ExpVisitor.java:55) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visit(InlineCalls.java:28) gnu.expr.ExpVisitor.visitAndUpdate(ExpVisitor.java:162) gnu.expr.ExpVisitor.visitExps(ExpVisitor.java:176) gnu.expr.ApplyExp.visitArgs(ApplyExp.java:416) gnu.kawa.reflect.CompileInvoke.validateApplyInvoke(CompileInvoke.java:23) java.lang.reflect.Method.invokeNative(Native Method) java.lang.reflect.Method.invoke(Method.java:521) gnu.expr.InlineCalls.maybeInline(InlineCalls.java:467) gnu.expr.QuoteExp.validateApply(QuoteExp.java:150) gnu.expr.ReferenceExp.validateApply(ReferenceExp.java:191) gnu.kawa.functions.CompilationHelpers.validateApplyToArgs(CompilationHelpers.java:66) java.lang.reflect.Method.invokeNative(Native Method) java.lang.reflect.Method.invoke(Method.java:521) gnu.expr.InlineCalls.maybeInline(InlineCalls.java:467) gnu.expr.QuoteExp.validateApply(QuoteExp.java:150) gnu.expr.ReferenceExp.validateApply(ReferenceExp.java:191) gnu.expr.InlineCalls.visitApplyExp(InlineCalls.java:119) gnu.expr.InlineCalls.visitApplyExp(InlineCalls.java:28) gnu.expr.ApplyExp.visit(ApplyExp.java:411) gnu.expr.ExpVisitor.visit(ExpVisitor.java:55) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.QuoteExp.validateApply(QuoteExp.java:162) gnu.expr.ReferenceExp.validateApply(ReferenceExp.java:191) gnu.kawa.functions.CompilationHelpers.validateApplyToArgs(CompilationHelpers.java:66) java.lang.reflect.Method.invokeNative(Native Method) java.lang.reflect.Method.invoke(Method.java:521) gnu.expr.InlineCalls.maybeInline(InlineCalls.java:467) gnu.expr.QuoteExp.validateApply(QuoteExp.java:150) gnu.expr.ReferenceExp.validateApply(ReferenceExp.java:191) gnu.expr.InlineCalls.visitApplyExp(InlineCalls.java:119) gnu.expr.InlineCalls.visitApplyExp(InlineCalls.java:28) gnu.expr.ApplyExp.visit(ApplyExp.java:411) gnu.expr.ExpVisitor.visit(ExpVisitor.java:51) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visitBeginExp(InlineCalls.java:272) gnu.expr.InlineCalls.visitBeginExp(InlineCalls.java:28) gnu.expr.BeginExp.visit(BeginExp.java:156) gnu.expr.ExpVisitor.visit(ExpVisitor.java:51) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.visit(InlineCalls.java:28) gnu.expr.LambdaExp.visitChildrenOnly(LambdaExp.java:1664) gnu.expr.LambdaExp.visitChildren(LambdaExp.java:1651) gnu.expr.InlineCalls.visitScopeExp(InlineCalls.java:279) gnu.expr.InlineCalls.visitLambdaExp(InlineCalls.java:349) gnu.expr.InlineCalls.visitLambdaExp(InlineCalls.java:28) gnu.expr.ExpVisitor.visitModuleExp(ExpVisitor.java:103) gnu.expr.ModuleExp.visit(ModuleExp.java:482) gnu.expr.ExpVisitor.visit(ExpVisitor.java:51) gnu.expr.InlineCalls.visit(InlineCalls.java:46) gnu.expr.InlineCalls.inlineCalls(InlineCalls.java:33) gnu.expr.Compilation.walkModule(Compilation.java:994) gnu.expr.Compilation.process(Compilation.java:1965) gnu.expr.ModuleInfo.loadByStages(ModuleInfo.java:330) gnu.expr.ModuleExp.evalModule1(ModuleExp.java:238) gnu.expr.ModuleExp.evalModule(ModuleExp.java:198) gnu.expr.Language.eval(Language.java:943) gnu.expr.Language.eval(Language.java:883) gnu.expr.Language.eval(Language.java:865) com.google.appinventor.components.runtime.util.AppInvHTTPD.serve(AppInvHTTPD.java:188) com.google.appinventor.components.runtime.util.NanoHTTPD$HTTPSession.run(NanoHTTPD.java:470) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561) java.lang.Thread.run(Thread.java:1096)

About

CHSH App Inventor 2 Server Source Code

Topics

Resources

License

Stars

Watchers

Forks

Languages

  • Java 75.8%
  • HTML 13.0%
  • JavaScript 5.8%
  • Python 2.0%
  • CSS 1.7%
  • Scheme 1.5%
  • Other 0.2%