※ 2024/01/20 websh を停止しました。現在は静的 HTML を返却する画面だけになっています。
目次
- 画面を表示する
- 画面左のtextareaにシェルを入力する
- 画面左のRunボタンを押す
- 結果が画面右のtextareaにセットされる
- やりたかったらTweetボタンでつぶやく
実体はフロントエンドのHTMLからAPIリクエストして実行結果を受け取ってるだけです。 なので普通にcurlでPOSTリクエスト送れば画面がなくても動きます。
以下のようなリクエストを送ればコマンドラインからwebshを使用できます。
curl -X POST -d '{"code":"echo hello", "images":[]}' 'https://websh.jiro4989.com/api/shellgei'
images にbase64エンコードした画像ファイルを含めるとwebsh上の /media 配下にア ップロードしたファイルがbase64デコードされて配置されます。
詳細なAPI仕様は https://jiro4989.github.io/websh/swagger.html を参照してください 。
3rd partyのコマンドラインツールが存在します。多謝。
Bashライクの操作体系でWebshのAPI経由でシェルを実行するプロンプト。
コマンドラインでWebshのAPI経由でシェルを実行するCLI。
- https://github.com/Khronos31/scripts/blob/master/bin/websh
- https://github.com/eggplants/websh.sh
- https://github.com/sheepla/websh-cli
- https://github.com/yuu528/sgb
一応自前で作ったコマンドラインツールもある。
PCのChrome最新版のみサポートしています。
Chrome以外のブラウザでも動くかもしれないですが、動かなくなっても知らないです。 スマホも動作確認してないので動くかもしれないですし、動かないかもしれないです。
PCのChromeで操作してください。
シェル芸Bot のWeb移植の SGWeb というWebアプリがある。
最新のシェル芸botに追従してなかったので、試しに自分が最新のシェル芸botに追従する Webアプリ作って公開してみるか、と思ったから。 あとWebアプリを作る勉強もかねて。
アプリはすべてDockerコンテナ上で動作する。
ブラウザの画面からシェルを実行するとコンテナ上のNginxへリクエストが流れる。 Nginxはリバースプロキシし、コンテナ上のAPIサーバがリクエストを受ける。
APIサーバはホストネットワーク上のDockerAPIを使用して、 シェル芸Botコンテナを操作する。
画像ファイルなどを配置する一時ディレクトリの後始末は APIサーバからは行わず、removerコンテナが非同期に削除する。
flowchart TD
u[developer] --> n[nginx]
subgraph PC
n --> s[websh_server]
subgraph Application
s --> fs[file_system]
r[websh_remover] --> fs
end
sgb[ShellGeiBot] --> fs
end
Infrastructure as Code (Ansible) している。 ソースコードは infra リポジトリ(非公開)で管理。
監視には netdata を使っている。
以前はサーバ上にGrafanaLokiと各種PrometheusExporterを入れて、ローカルのGrafana+ Prometheusコンテナから監視していたけれど、大掛かり過ぎて外した。あとたまに GrafanaLokiのCPUが張り付いて困っていたのもある。
ブラウザからPOSTリクエストを受け、POSTの内容を取得し、Dockerコンテナ内でシェルを実行する。
コンテナは状態を保持しないようにする。 一度リクエストをしたあと、再度コンテナにリクエストをしても、前回実行した結果はコンテナ内に残らないようにする。 リクエストの都度、コンテナを破棄して生成するようにする。
ただしコンテナの破棄と生成はAPIサーバプロセス自体は実施しない。 コンテナの破棄と起動には時間がかかり、合計で約2秒ほどかかってしまう。 レスポンスタイム向上のため、コンテナの破棄と生成は別プロセスが引き受けるようにする。 APIサーバはコンテナの破棄のトリガーを生成するのみに留める。
コンテナの起動はインフラ側のsupervisorが引受ける。 コンテナや画像ファイルの破棄は別APIサーバとは別プロセスが引き受ける。
以上を踏まえて、Webからのリクエストを受けてレスポンスを返すまでの一連の処理フローは以下の通り。
以下のツールがインストールされている必要があります。
- Nim
- Docker
- Docker-compose
Path | Description |
---|---|
docs | READMEの画像ファイルなど |
nginx | ローカル開発用のnginxの設定 |
websh_front | フロントエンドのプログラム |
websh_server | バックエンドのAPIサーバのプログラム |
websh_remover | バックエンドの後始末を行うプログラム |
Dockerfile | アプリのDockerイメージ |
docker-compose.yml | ローカル開発でのみ使用する開発環境設定 |
DockerをAPIで操作できるようにする必要がある。 Linux環境ではSystemdでDockerを起動しているはず。 docker.serviceを以下のように修正する。
/lib/systemd/system/docker.service
# ここを
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# こう修正
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H fd:// --containerd=/run/containerd/containerd.sock
以下のコマンドをリポジトリディレクトリ配下で実行する。
# シェル芸botのイメージを取得 (巨大なので注意)
docker pull theoldmoon0602/shellgeibot
docker-compose build
docker-compose up
サーバを起動して待機状態になったら、ブラウザで以下のページにアクセスする。
以下の5種類のブランチを使う。
Branch name | Description |
---|---|
master | 本番用 |
feature/#xx-desc | 新機能、UI改善 |
hotfix/#xx-desc | バグ修正 |
chore/#xx-desc | CIやローカル開発環境の整備など、アプリに影響しない雑多なもの |
feature, hotfix, choreのブランチ名のプレフィックスは、PR作成時のラベル自動付与にも使用している。 よって、必ずブランチ命名規則を守ること。
1つずつリリースしたいので各ブランチからmasterにPRを出す。 複数の改修をまとめてリリースしたい時だけdevelopブランチを使う。
ドキュメントの更新だけの場合はmasterブランチから直接pushする。 この時は必ずコミットログに [skip ci] を含めなければならない。 masterブランチのCIが走るとリリースドラフトが生成されてしまうため。 詳細は CI のセクションを参照。
websh_frontディレクトリ配下のREADME を参照。
websh_serverディレクトリ配下のREADME を参照。
public ディレクトリ配下にWebshのAPI仕様を定義している。 API仕様が変わった場合は、こちらも合わせて更新する。 API仕様はOpenAPI 3.0.2を使用している。 API仕様はGitHub Pagesで閲覧できる。masterブランチが更新されると自動で反映される。
更新したswagger.yamlをローカルで確認する場合は、以下のコマンドを実行してローカル でサーバを起動して確認する。
$ cd public
$ python3 -m http.server
サーバを起動したら http://localhost:8000/swagger.html を開いて画面が期待通り描画 されるかを確認する。
.github ディレクトリ配下にワークフローを定義している。 ビルド、テスト、デプロイのフローは .github/workflows/main.yml に定義している。
CIのジョブフローは以下。
masterブランチでのpush、margeの場合は create-tag-draft が実行される。
create-tag-draft ではタグのドラフトを作成する。 タグのドラフトは、PRの説明から自動でセットされる。 Feature/BugFixなどの分類は、 PR時のラベルでカテゴライズされる。
PR時のラベルはブランチのプレフィックスから自動でセットされる。 ブランチ命名規則については <<開発,ブランチ運用>> を参照。
タグドラフトをpublishすると deploy が実行され、サーバ上にmasterのビルド成果物をデプロイする。
前述のCIの通り、リリースを作成すると自動でデプロイされる。
リリースの下書きはGitHub Actionsが下書きを作成する。 下書きをpublishすると、GitHub Actionが起動して、デプロイされる。 以下はデプロイのフロー。
デザインとか超手抜きですので、プルリクエストお待ちしてます。
Apache License