🤖

xterm.jsでCloudShellっぽいものを作る

2023/07/31に公開

xterm.jsを使って自前のCloudShellみたいなものを作ったのでその記録です。

webptyの動作アニメーション

背景

AWS CloudShellGoogle Cloud Shellを使うと、Webブラウザ上ですぐにLinuxコマンドを実行できる環境が確保できます。
AWSアカウントやGoogle Cloudの認証情報だけで利用でき、SSHクライアントやSSHキーなどを用意する必要がないのでとても強力で便利です。

一方で強力で便利な分、コンソールログを残す仕組みがなかったり、サーバーでCloud Shellからの接続を許可したい場合にかなり広い範囲のアクセス許可が必要になるなど、セキュリティポリシー上の不都合もあります。

やったこと

自前でCloudShellと同じ用にWebブラウザからアクセスできるシェルコンソールを作成しました。

https://github.com/ikedam/webpty

動かすとアプリケーションが動作しているDockerコンテナ内で動作するbashにWebブラウザからアクセスできます。
docker compose exec server /bin/bash をしたのと同じことがWebブラウザからできることになります。

使用したもの

xterm.jsを使うとほぼそのまま目的のものが作れます。
今回はWebブラウザ上で動作するxterm.jsの入出力と、サーバーでbashを動かした仮想ターミナルの入出力をWebsocketでつなぎました。
Webブラウザとサーバー間の接続

※今回 Angular や Echo を使っている意義はあんまりない。

処理概要

終了処理

以下が起きると終了処理を行います。

  • Websocketからの入力が終了した(フロントエンドで処理を終了した)
  • bashプロセスが終了した(バックエンドで処理を終了した。ただし実際にはフロントエンドでexitを入力した場合が該当)

終了時には以下を行います。

  • bashプロセスにSIGHUPを送信してbashプロセスを強制終了。
    • ちなみにSIGTERM等では終了しない。
  • Websocketを切断。

課題事項など

検証程度の実装のため、この仕組みを実際の環境で利用するには以下の考慮が必要です。
xterm.jsには多数のアドオンがあるので、それを使うと解決するものもあると思います:

  • 日本語文字の入出力ができない。
  • less などを使った感じ、どうもちゃんとターミナルサイズを設定できていない様子。
  • 子プロセスを起動したままクライアントを閉じた場合に子プロセスを停止する処理が必要。

Discussion