コンテンツにスキップ

small shell Advanced

アプリ開発

small shellはそれ自体がシェルのため、Linux上で動きうるどんなものも呼びだすことができ、操作することができます。Application Shellの基本構造を理解することで、生成したScratch APPにLinuxコマンドでそのまま処理を追加でき、データを結合、加工することができます。本コースではScratch APPの生成とカスタマイズの流れをご説明します。それでは早速Scratch APPを生成してApplication Shellの構造を読み解いていきましょう

Scratch APPを使って作成するアプリケーションのシナリオは以下のとおりです

WEBアプリシナリオ
1. アプリへはパスコードもしくは専用URL(QRコード化も可能)でアクセスする
2. 認証が成功した場合、アプリはイベントの詳細情報を表示する
3. 管理者はTeam APPでイベント管理をする

Team APPの生成

small shell基礎#2にてTeam APPはすでに作成済みかと思いますが、もし生成していない場合はTeam APPのinstallを参照のうえ生成してください

スクラッチアプリ生成

早速 Scratch APPを生成してみましょう、ここでもgen dialogでのアプリケーション生成を行います。前提としてsmall-shell基礎#1で作成したBase APPが作られている必要がありますのでsmall-shell基礎#1を参照して生成しておいてください。

生成コマンド
sudo /usr/local/small-shell/adm/gen -app

対話が始まりますが、ここではアプリケーションの名前は21DOJOとします、pass codeは任意の4桁の数字を入力しています

実行例
$ sudo /usr/local/small-shell/adm/gen -app
Type of APP (1.BASE | 2.FORM | 3.SCRATCH): 3
APP Name: 21DOJO
Type of Authentication (1.shared pass | 2.user key | 3.other | 4.none): 1
Shared Passcode: XXXX
Primary databox: events
Do you want to enable IP whitelisting for this APP? (yes | no): no
前章同様、アプリはshared passを選択しますがもちろん他の認証方式も選択可能です。 databoxの指定までできると最終確認をもとめられますので、yesと回答しましょう

ログイン画面の確認

アプリケーションが生成されたのでアクセスしてみましょう
(アクセスURLはスクラッチアプリ生成後に出力されます)

Screenshot

APP shell基本構造

アプリケーションシェルの構造を理解して、スクラッチアプリを更新していきましょう。スクラッチアプリ作成時に以下のようにコードを含むファイルが生成されたと思いますが、それぞれのコードは更新して機能を作りこんでいくことができます、本コースではあくまで構造の外観を説明するのみですので詳細はsmall shell公式サイトのAPP shellも参考にしてください

生成されたファイル
------------------------------------------------------------
SCRATCH APP is successfully generated
Access URL: http://{サーバアドレス}/21DOJO
------------------------------------------------------------
Following is generated codes that you can update.
You can also update portal page on Base APP #21DOJO.UI.md.def using markdown.
/var/www/cgi-bin/auth.21DOJO
/var/www/cgi-bin/21DOJO
/var/www/cgi-bin/21DOJO_css
/var/www/bin/21DOJO_del.sh      /var/www/bin/21DOJO_get.sh             /var/www/bin/21DOJO_main.sh            /var/www/bin/21DOJO_set.sh
/var/www/bin/21DOJO_dl.sh       /var/www/bin/21DOJO_log_viewer.sh  /var/www/bin/21DOJO_page_links.sh  /var/www/bin/21DOJO_table.sh
/var/www/descriptor/21DOJO_auth_form.html.def     /var/www/descriptor/21DOJO_get_new_master_failed.html.def  /var/www/descriptor/21DOJO_log_viewer.html.def
/var/www/descriptor/21DOJO_del_err.html.def       /var/www/descriptor/21DOJO_get_ro.html.def                 /var/www/descriptor/21DOJO_main.html.def
/var/www/descriptor/21DOJO_get_err.html.def       /var/www/descriptor/21DOJO_get_rw.html.def                 /var/www/descriptor/21DOJO_main.html.incmd.def
/var/www/descriptor/21DOJO_get_new.html.def       /var/www/descriptor/21DOJO_get_rw_incf.html.def            /var/www/descriptor/21DOJO_set_err.html.def
/var/www/descriptor/21DOJO_get_new_incf.html.def  /var/www/descriptor/21DOJO_get_rw_master_failed.html.def   /var/www/descriptor/21DOJO_table.html.def

ディレクトリ構造

コードは以下のとおり1.cgi-bin 2.bin 3.descriptorに格納されますが、処理の順序も同様の並びとなります。クライアントから要求があるとcgi-bin配下のコントローラーが要求を受け付け、bin配下のアクションスクリプトを呼び出し、アクションスクリプトがdescription配下のHTML定義を読み込みながら応答をクライアントに返すという順序で処理がされます

1. /var/www/cgi-bin     # アプリケーション全体をコントロールするcontrollerプログラムを配置
2. /var/www/bin         # 応答処理をAction scriptとして記述、DataBoxへの接続や分岐処理をする
3. /var/www/descriptor  # HTML及びCSSの定義を配置

URL構造

先ほど作成した21DOJOアプリのアクセス用URLは/21DOJOとなっているはずですが、これはauth.21DOJOというプログラムへサーバ側でリダイレクト(転送)され認証画面が表示されますのでアプリ生成時に設定したパスコードを入力してください

http://{サーバアドレス}/21DOJO --> 転送 --> http://{サーバアドレス}/cgi-bin/auth.21DOJO

認証が成功した場合、コントローラーへ自動で接続されます。ログイン後のURLをブラウザからコピーしてみてみましょう、URLはsession情報やsessionを保証するpinコードを含んでいます。また、req=mainという記述も確認できると思いますが、これはmainページのリクエストを意味します

コピーしたURL(例)
http://{サーバアドレス}/cgi-bin/21DOJO?session=26a289bf7eedac7dfe4e26aa33a912bd36745e158c3592728446f9e57cf1b117&pin=13913&req=main

QUERY STRING

QUERY STRING(クエリーストリング)とはURLに付加するパラメーターですが、プログラムの後に?を付けてパラメーターを記述することでプログラムに値を渡すことができます。上記req=mainというパラメーターはsmall shelフレームワーク上でreqという変数に格納されるmainという値として展開します、また&を付けることで複数のQUERY STRINGをURLに連結していくことができます

コントローラー

コントローラーはcgi-bin配下に置かれ、認証後のセッションの維持やrequest毎にbin配下のactionスクリプトへのルーティングを記述しています。21DOJOアプリのコントローラーの中身を見てみましょう。cgi-bin配下には設定したアプリケーション名がそのままプログラムとして生成され、コントローラーとして機能します

ルーティング

cgi-bin配下の21DOJOをcatで確認するとルーティングがコード自体に埋め込まれていることが確認できます。req変数(上述のURLではmainが格納された)に入っている内容に応じてcase分で分岐処理を行いますが、small shellフレームワークではこのcase文をルーティングと呼んでいます。また、ルーティングに際してコントローラーはQUERY STRINGとして渡されたパラメーターを変数に格納して後続処理に渡します

実行例
$ sudo tail -48 /var/www/cgi-bin/21DOJO

#----------------------------
# routing to action scripts
#----------------------------

case "$req" in

  "main")
    /var/www/bin/21DOJO_main.sh session:$session pin:$pin user_name:$user_name remote_addr:${remote_addr};;

  "get")
    # master param must be loaded on ./descriptor/.small-shell.conf
    if [ ! "$master" ];then
      /var/www/bin/21DOJO_get.sh session:$session pin:$pin user_name:$user_name id:$id duplicate:$duplicate
    else
      sync=`${small_shell_path}/bin/extension_auth app:21DOJO sync:${session}@${master}`
      if [ "$sync" = "synced" ];then
        redirect=yes
      else
        redirect=no
      fi
      /var/www/bin/21DOJO_get.sh session:$session pin:$pin user_name:$user_name id:$id duplicate:$duplicate redirect:$rediret
    fi
    ;;

  "set")
    /var/www/bin/21DOJO_set.sh session:$session pin:$pin user_name:$user_name id:$id ;;

  "del")
    /var/www/bin/21DOJO_del.sh databox:$databox session:$session pin:$pin id:$id ;;

  "table")
    table_command="`echo $table_command | $SED "s/ /{%%space}/g"`"
    /var/www/bin/21DOJO_table.sh session:$session pin:$pin user_name:$user_name id:$id page:$page table_command:$table_command line:$line ;;

  "log_viewer")
    /var/www/bin/21DOJO_log_viewer.sh session:$session pin:$pin user_name:$user_name id:$id ;;

  "file")
    /var/www/bin/21DOJO_dl.sh session:$session pin:$pin user_name:$user_name id:$id ;;

  # sub app routing section

  *)
    echo "error: wrong request";;

esac

exit 0

Parse (パース)

ルーティングに至る前処理としてクライアントから送信(POST) された要求を解析するプログラムとしてparse.shが使用されます。controllerに、例えばitem.dbというデータボックスの主keyであるitem_nameの値をPOSTした場合、controllerは/var/www/tmp/$session配下にitem_nameというファイルを作り、そこにPOSTされたアイテム名を格納します。$sessionは要求の都度生成されるsession値が入ります。詳細はparseを翻訳して確認してください

Note

QUERY STRINGとPOSTはともにサーバにクライアントからデータを渡しますがそれぞれ方法が異なります。QUERY STRINGは前述のとおりURLに埋め込まれていますが、POSTデータは主にフォームを通じてデータ送信されます

アクションスクリプト

コントローラーがルーティングを通じて呼び出すのがアクションスクリプトですが、ユーザーへの応答を返すのはアクションスクリプトになります。主な処理としてはデータシェルへ接続して特定のidを持つデータを抽出したうえで所定のHTML descriptorのHTMLファイルに動的な情報を埋め込んで返します。その際、動的情報の埋め込みとしては%%タグ(印)をsedで置き換えるという処理を行っています。

データシェルへの接続部分はget.shの中の以下処理となります

DATA_shellへの接続とデータの抽出
$ grep DATA_SHELL /var/www/bin/21DOJO_get.sh | grep html
    $DATA_SHELL databox:$databox action:get id:$id keys:$keys format:html_tag > /var/www/tmp/$session/dataset

また、HTMLを還す際は以下のようにsedで%%datasetタグの中に上記で抽出した情報を埋め込みます

タグへの情報の埋め込み
$ sudo tail -18 /var/www/bin/21DOJO_get.sh

# render HTML
cat /var/www/descriptor/${view} | $SED -r "s/^( *)</</1" \
| $SED "/%%common_menu/r /var/www/descriptor/common_parts/21DOJO_common_menu" \
| $SED "/%%common_menu/d" \
| $SED "/%%dataset/r /var/www/tmp/$session/dataset" \
| $SED "s/%%dataset//g"\
| $SED "/%%history/r /var/www/tmp/$session/history" \
| $SED "s/%%history//g"\
| $SED "s/%%id/$id/g" \
| $SED "s/%%pdls/session=$session\&pin=$pin\&req=get/g" \
| $SED "s/%%session/session=$session\&pin=$pin/g" \
| $SED "s/%%params/session=$session\&pin=$pin/g"

if [ "$session" ];then
  rm -rf /var/www/tmp/$session
fi

exit 0

HTML descriptor

アクションスクリプトが呼び出しているHTML descriptorも見てみましょう。HTMLの以下%%dataset部分にアクションスクリプトがデータを埋め込みます

HTML内の%%datasetタグ
$ cat /var/www/descriptor/21DOJO_get_rw.html.def  | grep -2 %%dataset | sed -r "s/^(.*)</</g"

<form method="post" action="./21DOJO?%%params&req=set&id=%%id" onclick="document.charset='utf-8';">
<ul>
        %%dataset
</ul>
</button>

アプリのカスタマイズ

大枠の構造を理解いただいたところで、さっそくアプリのカスタマイズを行っていきましょう。

keyの再定義

まずは今回の目的に応じてDataBoxを拡張しましょう。Team APPのデフォルトのevents定義から今回作成したアプリに適したコンテンツになるよう、genコマンドで再定義していきましょう

新規イベント登録画面

Screenshot

keyの追加削除にはgenコマンドを使用します。不要なkeyをまずは消しましょう。

実行例
$ sudo /usr/local/small-shell/adm/gen -delcol
Databox Name: events
column's key name: description 
Do you want to delete more column from dataset ? (yes | no) : no 

続いて必要なkeyを追加していきます

実行例
$ sudo /usr/local/small-shell/adm/gen -addcol
Databox Name: events
key(col7) name: url
key (col7) label: イベントURL
Data Type (text | select | radio | checkbox | email | num | tel | date | date-time | url | textarea | file | pdls | mls): url
Require to input each time? (yes | no): no
Do you want to add more column to dataset ? (yes | no) : yes
key(col8) name: detail
key (col8) label: イベント詳細
Data Type (text | select | radio | checkbox | email | num | tel | date | date-time | url | textarea | file | pdls | mls): textarea
Require to input each time? (yes | no): no
Do you want to add more column to dataset ? (yes | no) : no
最終確認が求められますので問題なければyesと解答してkeyの追加を完了しましょう。genコマンドが完了次第、再度イベント登録画面にいくとフィールドが更新されていることを確認しましょう。その後、テスト用のeventを登録してください

更新後のイベント追加画面

Screenshot

ポータルのアップデート

続いて21DOJOへのログイン時に最初に表示されるポータルページに最新のイベント情報が出てくるようにしましょう

HTML編集

今回のポータルページはより構造的な情報を表示したいため、markdownでは記述せずHTMLを記述しましょう。Base APPログイン後、21DOJO.md.defデータボックスを選択して定義を更新しましょう。 以下の通りdescriptionを全て消して以下を貼り付けて更新してください。 Screenshot

サンプルHTMLコード
<div class="flex-box">
  <div class="potal-description">
    <h2>21世紀IT塾公開講義の最新情報をご確認ください</h2>
    <h2>記載のURLからご参加いただければと思います</h2>
    <a href="./21DOJO?%%params&req=table"><button class="button">SEARCH</button></a>
  </div>
  <div class="event">
    <div class="app-form">
%%event
    </div>
  </div>
</div>

以下が更新後の画面です、現時点で%%eventタグが埋め込まれていないためそのまま%%eventタグが表示されています、またeventの位置があまりよくないためcssをつかって位置を調整しましょう Screenshot

アプリ毎のcss定義については直接編集が可能です

sudo nano /var/www/descriptor/21DOJO.css.def

nanoでファイルを開いたら以下コードを一番下に貼り付けましょう、ctrl + Vでページを進むことができます

追加コード
.flex-box {
  display:flex;
  flex-wrap:wrap;
} 

.event {
  padding-left: 48px;
}   
位置が以下のように調整できたことを確認してください Screenshot

main.sh

続いて21DOJOのmain.shにて%%eventタグの変換処理をいれます。”#以下行を追加”とある処理を追加し、"#以下行をコメントアウト"と記載のある箇所はコメントアウトしてください。 具体的な処理としてはdataboxの最新の1行目のエントリーをhead -1でサーチして、idを取得、データをeventファイルに書き出したのちsedで%%eventを上書しています

実行例
$ sudo nano /var/www/bin/21DOJO_main.sh

--対象コード--
# SET BASE_COMMAND
META="${small_shell_path}/bin/meta"
DATA_SHELL="${small_shell_path}/bin/DATA_shell session:$session pin:$pin app:21DOJO"

# 以下行を追加
id=`$DATA_SHELL databox:events command:head_-1 format:none | $AWK -F "," '{print $1}'`
$DATA_SHELL databox:events action:get id:$id keys:name,start,end,url,detail format:html_tag > ../tmp/$session/event

# -----------------
# render HTML
# -----------------

# 以下行をコメントアウト
#cat /var/www/descriptor/21DOJO_main.html.def | $SED -r "s/^( *)</</1" \
#| $SED "/%%common_menu/r /var/www/descriptor/common_parts/21DOJO_common_menu" \
#| $SED "s/%%common_menu//g"\
#| $SED "s/%%user_name/$user_name/g" \
#| $SED "s/%%session/session=$session\&pin=$pin/g" \
#| $SED "s/%%params/session=$session\&pin=$pin/g"


# 以下行を追加
cat /var/www/descriptor/21DOJO_main.html.def | $SED -r "s/^( *)</</1" \
| $SED "/%%common_menu/r /var/www/descriptor/common_parts/21DOJO_common_menu" \
| $SED "s/%%common_menu//g"\
| $SED "s/%%user_name/$user_name/g" \
| $SED "/%%event/r ../tmp/$session/event" \
| $SED "s/%%event//g" \
| $SED "s/%%session/session=$session\&pin=$pin/g" \
| $SED "s/%%params/session=$session\&pin=$pin/g"

完成したポータルはこちらになります Screenshot

Note

イベントが何も登録されていないときは"error: please input id"というメッセージが表示されるため、イベントを登録して下さい

Read onlyへの変更

21DOJOはshared passのためシステムユーザーしかもちませんが、このユーザーをread onlyに変更することでアプリ全体が読み取り権限のみとなり書き込みができなくなります

実行例
$ sudo /usr/local/small-shell/adm/ops set.attr:21DOJO.app{ro} app:21DOJO
successfully set attr peremission 21DOJO/21DOJO.app{ro}"

閲覧keyの制限

管理目的以外で使用しないkeyは21DOJOアプリからは閲覧できないようkeys=allをコメントアウトして閲覧可能なkeyを制限しましょう。

以下はkey制限前のテーブルイメージです Screenshot

keyを制限するため、/bin配下のアクションスクリプトを編集します

実行例
sudo nano /var/www/bin/21DOJO_table.sh
--対象コード--
#keys=all
keys=name,start,end,url,detail
---------

実行例
sudo nano /var/www/bin/21DOJO_get.sh
--対象コード--
#keys=all
keys=name,start,end,url,detail
---------

コード編集後にkeyが制限されたことを確認してください Screenshot

チケットURL整備

より簡易的なアクセスができるよう、URL自体にpass codeを埋め込みアクセスしてみましょう、そうすることで認証画面なしで自動ログインが可能です

URLデザイン

以下はWSL環境でpass codeとして1234を設定したアプリにQUERY STRINGを利用してログインするためのURLの例です。アプリをインターネット公開している場合はこのURLをQRコード生成サイトなどでQRコード化すればスマホなどでアクセスと自動ログインが可能になります

http://{サーバアドレス}/cgi-bin/auth.21DOJO?app_pass=1234

その他の高度な機能

Graph生成

pyshellを使うことで容易にGraph生成ができます、まずはsmall shell公式サイトを確認してpython及びlibraryのインストールをしてください。公式サイトはChromeの翻訳機能を使えば日本語での閲覧が可能です

pyshell

公式サイトの手順通りにpyshellのセットアップが完了しているか確認しましょう、以下ではenv設定が適切に実施されpython3.12がインストールされていることを確認します

$ cat /usr/local/small-shell/util/pyshell/env | grep PYTHON
PYTHON="/usr/local/bin/python3.12"
$ ls /usr/local/bin/python3.12
/usr/local/bin/python3.12

日本語を扱えるようにフォントをインストールしてフォント定義を変更しましょう

# フォントインストール
$ sudo apt install fonts-ipaexfont
$ sudo vi /usr/local/small-shell/util/pyshell/env
--code--
font_family="IPAexGothic" 
--------

# キャッシュの削除
$ sudo -u small-shell rm /home/small-shell/.cache/matplotlib/fontlist-*.json

Snapshot Graph

pyshell環境が適切に設定できていたら、utility scriptであるcountup.shを使ってスナップショットグラフを作成しましょう。スナップショットグラフとはpyshell実行時点のデータを集計し、記録したグラフです。スナップショット以外にデータ蓄積を前提としたhourly, daily, monthlyのグラフの作成が可能です。以下はsmall-shell基礎#1でアンケート集計のために作成したsurvey.boxを"良い"、"普通"、"悪い"でそれぞれデータを集計するコマンド例になります

実行例
$ sudo -u small-shell /usr/local/small-shell/util/scripts/countup.sh databox:survey.box key:impression filters:良い,普通,悪い type:pie frequency:snapshot

タイトルを入れたい場合はtitleも入力してください、ここではタイトルにスペースを使わず"2024-12-02_調査結果"としています

実行例
$ sudo -u small-shell /usr/local/small-shell/util/scripts/countup.sh databox:survey.box key:impression filters:良い,普通,悪い title:2024-12-02_調査結果 type:pie frequency:snapshot

Note

countup.shは指定のDataBoxのデータに対し指定のwordで検索をかけ、その件数を集計しグラフにします

Graphの確認

countup.shの実行がエラーなく完了したらconsoleでgraphを確認しましょう、command lineに#statsと打ち込めば作成されたグラフの一覧が出てきます。

Screenshot

Title付きのグラフをクリックしてみましょう、グラフがポップアップで表示されます

Screenshot

Graphの削除

Graphを削除したい場合は、統計データを蓄積しているstatisticsディレクトリで直接データを消してください

実行例
$ ls /usr/local/small-shell/util/statistics/graph
countup_s_20241202_db_survey.box_impression_filtered.png countup_s_20241202_db_survey.box{2024-12-02_調査結果}impression_filtered.pn

$ sudo rm /usr/local/small-shell/util/statistics/graph/countup_s_20241202_db_survey.box_impression_filtered.png
$ sudo rm /usr/local/small-shell/util/statistics/rawdata/countup_s_20241202_db_survey.box_impression_filtered.csv

定期ジョブの登録

定期ジョブを用いて、提携処理を自動で実行することができます。ここではグラフを定期取得するためのジョブを登録しましょう、small shellでは対話を通じたcronへのジョブ登録が可能です

ジョブの生成と登録

以下では先ほど実行したcountup.shを毎日0時0分に実行するジョブを登録しています

実行例
$ sudo /usr/local/small-shell/adm/gen -job
job name: gen_survey_graph
Type of job (1.job automation | 2.file exchange) : 1
--Define schedule--
Month [ any | 1-12 ]: any
Date  [ any | 1-31 ]: any
Hour  [ any | 0-23 ]: 0
Min   [ any | 0-59 ]: 0
Week  [ any | mon - sun ]: any
Exec command or batch script: /usr/local/small-shell/util/scripts/countup.sh databox:survey.box key:impression filters:良い,普通,悪い type:pie frequency:snapshot

Note

genコマンドで登録されるジョブは自動でsmall-shellユーザー権限で実行されます

バッチスクリプトを指定すると最終確認が求められますので問題なければyesと入力しましょう

事項例(続き)
job will be generated by following order, please check it
-----------------------------------------------------------------

jobtype: 1.job automation
job_name: gen_survey_graph
min: 0
hour: any
date: any
month: any
week: any
exec_command: /usr/local/small-shell/util/scripts/countup.sh databox:survey.box key:impression filters:良い,普通,悪い type:pie frequency:snapshot

-----------------------------------------------------------------
Is it OK ? (yes | no): yes
ジョブ登録が完了したメッセージが表示されます。defにジョブ定義がありますので事後で編集することも可能です
実行例(続き)
Succesfully generated. job definition is here
def: /usr/local/small-shell/util/e-cron/def/gen_survey_graph.def
Please enable job "sudo -u small-shell /usr/local/small-shell/bin/e-cron enable.gen_survey_graph"
上記状態ではジョブは有効かされていないため有効化しましょう

実行例
$ sudo -u small-shell /usr/local/small-shell/bin/e-cron enable.gen_survey_graph
gen_survey_graph is succesfully enabled
有効化後はジョブの手動実行も可能です、以下はジョブの一覧を確認しgen_survey_graphを実行し結果を確認する例になります
実行例
$ sudo -u small-shell /usr/local/small-shell/bin/e-cron ls
--------------------------------------------------------------
job definition: /usr/local/small-shell/util/e-cron/def
--------------------------------------------------------------
del_session.enabled
del_util_log.enabled
gen_survey_graph.enabled
$ sudo -u small-shell /usr/local/small-shell/bin/e-cron exec.gen_survey_graph
gen_survey_graph successfully completed
$ sudo -u small-shell /usr/local/small-shell/bin/e-cron stat
--------------------------------------------------------
LATEST STATUS OF JOB
--------------------------------------------------------
2022-03-30 21:27:53 del_session successfully completed
2022-04-19 20:22:18 gen_survey_graph successfully completed
WSLをお使いの場合はcronは無効になっているので、windows再起動の都度以下コマンドを実行してcrondを起動してください

sudo service cron start

e-cronを用いるとさらに高度なジョブの登録や、他のホストとのメッセージ交換やデータ交換ができるようになります。詳細はsmall shell公式サイトのe-cron tourをご確認ください。chromeで翻訳して閲覧することをお勧めします。

さらなる学習のために

small shell公式サイトにはより詳細で高度なドキュメントが公開されていますので是非読み解いて下さい。また、21世紀IT塾公開講座へ参加いただければさらに実用的なスキルもつけていただけます。次章では21世紀のデジタル化社会を生きる上で必要不可欠な耐性として考慮されるDigital耐性についてご説明します