xterm.jsでキーボード入力を受け付ける方法
本記事で行うこと
- xterm.jsを利用して、キーボード入力を受け付けるhtmlを作成する。
- ※環境はnode.jsを使いますが、最後にCDNサイトを使ってhtmlファイルのみで行う方法も記載しておきます。
モチベーション
- vscodeのterminalなどで採用されているxterm.jsをつかってプロダクトを作ろうと思ったため。
- xterm.jsの使い方を開発メンバーと共有したかったため。
環境
- macbook pro/node.jsを利用
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H15 $ node -v v12.18.3
xterm.jsのインストール
versionは本記事を書いたときの最新版を利用します。
$ npm install --save xterm@4.9.0
Hello xterm.js
まず公式ページにあるとおり、html上にterminal windowを表示してみます。
github.com
<!doctype html> <html> <head> <link rel="stylesheet" href="node_modules/xterm/css/xterm.css" /> <script src="node_modules/xterm/lib/xterm.js"></script> </head> <body> <div id="terminal"></div> <script> let term = new Terminal(); term.open(document.getElementById('terminal')); term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ ') </script> </body> </html>
headのpathはインストールした場所を指定してください。
作成したhtmlファイルにブラウザでアクセスすると以下のようにterminalを表示できます。
- term.openでterminalを開いて、term.writeでterminalに文字を書き込めるようです。
この状態だとterminalに向かってキーボードを打っても何も反応しないのですが、
せっかくなのでこの状態で、Chromeの開発者モードで少し遊んで見たいと思います。
Chromeの開発者モードのConsoleを開き以下のように打ち込んで見ると画面が更新されました。
term.write("書き込んでみた")
Consoleにtermを打ち込むと何やら使えそうな関数が色々出てくるので、公式サイトで使い方を見てみます。
term
xtermjs.org Doc -> Class: Terminalを参照しいくつか試した結果を書いておきます。
- 書き込んで改行する。
term.writeln("改行する")
- 書き込んでpromptを表示する。 今後Enterを押した時に必ずこれを実行すれば良さそうです。
term.write('\r\n$ ')
- terminalに書き込まれたものをresetする。 clearが入力された時にこれを実行すれば良さそうな気がします。
term.reset()
キーボード入力を受け付けるhtmlを作成する。
公式が的供しているdemoサイトを参考に以下を作りました。 xterm.js/client.ts at master · xtermjs/xterm.js · GitHub
<!doctype html> <html> <head> <link rel="stylesheet" href="node_modules/xterm/css/xterm.css" /> <script src="node_modules/xterm/lib/xterm.js"></script> </head> <body> <div id="terminal"></div> <script> let term = new Terminal(); term.open(document.getElementById('terminal')); function runFakeTerminal() { if (term._initialized) { return; } term._initialized = true; term.prompt = () => { term.write('\r\n$ '); }; term.writeln('Welcome to xterm.js'); term.writeln('This is a local terminal emulation, without a real terminal in the back-end.'); term.writeln('Type some keys and commands to play around.'); term.writeln(''); term.prompt(); term.onKey(e => { console.log(e) const ev = e.domEvent const printable = !ev.altKey && !ev.ctrlKey && !ev.metaKey if (ev.keyCode === 13) { term.prompt(); } else if (ev.keyCode === 8) { if (term._core.buffer.x > 2) { term.write('\b \b'); } } else if (printable) { term.write(e.key); } }); } runFakeTerminal() </script> </body> </html>
これでキーボード入力を受け付けるようになりました。
少しだけ解説すると・・・
- term.prompt関数は呼ばれるとterm.write('\r\n$ ')を実行しバッファ2の『$ 』を書き込みます。
- keyCode === 13はEnter
- keyCode === 8はBackspace
- term._core.buffer.x > 2はtermのバッファが3以上の時1文字消します。
- printable = !ev.altKey && !ev.ctrlKey && !ev.metaKeyはこの条件がtrueの時の判定に利用
- else if (printable) {term.write(e.key);でprintableがtrueの時にterm.write(e.key)して入力をterminal上に書き込みます。
キーボード入力とコードの対応表 KeyboardEvent.keyCode - Web API | MDN
CDNサイト版
手っ取り早く試してみたい人は以下をhtmlファイルで保存すればnode.jsなしでも実行できます。
※CDNサイトがある限り。
<!doctype html> <html> <head> <link rel="stylesheet" href="https://unpkg.com/xterm@4.9.0/css/xterm.css"> <script src="https://unpkg.com/xterm@4.9.0/lib/xterm.js"></script> </head> <body> <div id="terminal"></div> <script> let term = new Terminal(); term.open(document.getElementById('terminal')); function runFakeTerminal() { if (term._initialized) { return; } term._initialized = true; term.prompt = () => { term.write('\r\n$ '); }; term.writeln('Welcome to xterm.js'); term.writeln('This is a local terminal emulation, without a real terminal in the back-end.'); term.writeln('Type some keys and commands to play around.'); term.writeln(''); term.prompt(); term.onKey(e => { console.log(e) const ev = e.domEvent const printable = !ev.altKey && !ev.ctrlKey && !ev.metaKey if (ev.keyCode === 13) { term.prompt(); } else if (ev.keyCode === 8) { if (term._core.buffer.x > 2) { term.write('\b \b'); } } else if (printable) { term.write(e.key); } }); } runFakeTerminal() </script> </body> </html>
alpine linuxをVMWareFusionにインストールする
本記事で行うこと
モチベーション
環境
macbook pro上でVMwareFusionを利用する
- macのversion
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H15
- VMware Fusionのversion
alpine linuxのisoファイルのダウンロード
以下のサイトからalpine linux(virtual版)のisoファイルをダウンロードします。
alpinelinux.org
ページ下に『古いリリースはここにあります。』とあるのでそこからisoファイルを選んでダウンロードします。
Index of /alpine/v3.12/releases/x86_64/
この時最新だった『alpine-virt-3.12.1-x86_64.iso』を選択します。
isoファイルで提供されているもので最も最小のvirtual版を使います。
たった40MB程度しかなく、よく利用しているCentOS7のminimal版でも7.9は約1GBもあるので、この時点で驚きです。
VMWareFusionにインストール
早速VMWareFusionしてみます。
あとでapline上でk3sを動かす予定でしたので、少し大きめの2CPU/2MBに変更します。
恐ろしく早く起動してきました。10秒もかかってないです。
rootでログインし、setup-apine scriptが用意されているので実行して各設定おwしていきます。
setup-apine の実行
ここで『setup- + TAB』を押すと候補が表示されます。
各項目を別々に設定することも可能です。
改めてsetup-apine を実行
キーボードの設定で『us』と『mac-us』を選択。
ホスト名はdefaultが『localhost』なのでそのままEnterを押します。
VMWareFusionはdefaultでdhcpでipを割り振ってくれるので、全てそのままEnterを押します。
自動的に設定されました。
rootのpasswordを設定します。
タイムゾーンを『Asia/Tokyo』に設定します。
Proxyは利用しないのでそのままEnterを押します。
NTPはchronyを利用したいのでそのままEnterを押します。
package repositoryは速いサイトを検索して設定してくれるfを入れてEnterを押します。
SSHはdefaultのopensshを使いたいのでそのままEnterを押します。
diskはsdaを入れてEnterを押します。
hddにインストールしてLinuxを使いたいのでsysモードにします。
yを入れて、Enterでフォーマットします。
しばらくして完了したら、rebootして設定完了です。
reboot後も10秒かからずに起動してきました。
今後はmacのterminalからsshして作業したいので、管理用のuserを作成します。
管理用のuserの作成
管理用のuserを作成します。
管理用のuserでsudoで管理用のコマンドを許可したいのですが、
標準のaplineにはsudoがdefaultでは入っていません。
apline公式でもユーザに管理アクセスさせたいときはsudoを入れて、wheelに入れてとありました。
docs.alpinelinux.org
ちなみに本内容とは脱線しますが、wheelというのは伝統的にユーザに管理権限を設定するためのグループのようです。
CentOS系でメディアインストールする時に管理者ユーザを作成すると自動的にwheelに入るので実は慣れ親しみがあります。
ホイール (コンピュータ) - Wikipedia
それではsudoをインストールして管理用のユーザをwheelに所属させます。
それではsudoをインストール
(なんと94MiBもありました・・・)
管理用のユーザをwheelに所属させます。
wheelグループにsudo権限を追加します。
macのterminalからsshで管理用のuser
この状態でmacからログインしてみる。
管理者でないとアクセスできないファイルにsudoでアクセスすることができました。
$ ssh adminuser@192.168.128.27 adminuser@192.168.128.27's password: Welcome to Alpine! The Alpine Wiki contains a large amount of how-to guides and general information about administrating Alpine systems. See <http://wiki.alpinelinux.org/>. You can setup the system with the command: setup-alpine You may change this message by editing /etc/motd. localhost:~$ $ ls -l /etc/sudoers.d ls: can't open '/etc/sudoers.d': Permission denied total 0 $ sudo ls -l /etc/sudoers.d [sudo] password for adminuser: total 4 -rw-r--r-- 1 root root 21 Nov 14 18:33 wheel
k3sのクイックスタートをCentOS7で試す
本記事でやること
- Rancher社が公開しているクイックスタートを試す。
- VMWareFusion上のCentOS7上でk3sのserver/agentを構築。
- nginx podを起動させ外部公開する。
- k3sをアンインストールする。
参考サイト
- k3sのgithubレポジトリ github.com
モチベーション
- kubernetesを自分の周りに教える時に、環境を用意するのが面倒だったため
- 検証ように軽量なkubernetes環境がほしかったため
k3sのアーキテクチャ
まずはじめに、k3sのアーキテクチャをさっと見ておこう。
- single processでkubernetesを再現している
- etcdの代りにSQLiteが組み込まれている。
- serverとagentはtunnel proxyでwebsocketで通信される。
- なお、CNIのdefaultとはflannelだがcanal/calicoに変更可能。
- dontainerdもdockerへ変更可能。
- SQliteもMariaDB/MySQL/etcd/ProstgreSQLに変更可能。
試す環境
- macのversion
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H15
VMware Fusionのversion
CentOS7のversiontと環境イメージ
検証目的のため本気記事はすべてrootユーザで実行した。
- serverのip addressはVMwareFusionからDHCPで設定される。
- server/agent側両方スペックは以下の通り
項目 | server | agent |
---|---|---|
OS | CentOS Linux release 7.7.1908 (Core) | CentOS Linux release 7.7.1908 (Core) |
ip address | 192.168.128.23/16 | 192.168.128.26/16 |
cpu | 1cpu | 1cpu |
memory | 2GB | 2GB |
disk | 20GB | 20GB |
クイックスタート
前置きが長かったが実行するコマンドはserver/agentでそれそれ以下のコマンドを実行するだけである。
- server側コマンド
# curl -sfL https://get.k3s.io | sh - ・・・ [INFO] systemd: Starting k3s
- しばらく待って『Starting k3s』が表示されたら、agent参加用のTOKENを取得する。
# cat /var/lib/rancher/k3s/server/node-token K107276dbacffd6b33672da6b084aed88df8f97e91fbb55789bc94da51a9868a342::server:1ba7e70e48330ce8f268d98fcbb6dc44
- agent側コマンド serverのURLとTOKENを指定して実行する
# curl -sfL https://get.k3s.io | K3S_URL=https://192.168.128.23:6443 \ K3S_TOKEN=K107276dbacffd6b33672da6b084aed88df8f97e91fbb55789bc94da51a9868a342::server:1ba7e70e48330ce8f268d98fcbb6dc44 \ sh - ・・・ [INFO] systemd: Starting k3s-agent
しばらく待って『k3s-agent』が表示されたら完了。
それでは状態を見ていこうと思う。
インストール後の確認
- server側で実施
問題なくkubernetesが検証できる環境が整っている。
# kubectl cluster-info Kubernetes master is running at https://127.0.0.1:6443 CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy Metrics-server is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. # kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k3s-server Ready master 81m v1.19.3+k3s3 192.168.128.23 <none> CentOS Linux 7 (Core) 3.10.0-1062.1.2.el7.x86_64 containerd://1.4.1-k3s1 k3s-agent Ready <none> 67m v1.19.3+k3s3 192.168.128.26 <none> CentOS Linux 7 (Core) 3.10.0-1062.1.2.el7.x86_64 containerd://1.4.1-k3s1 # kubectl get all --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system pod/metrics-server-7b4f8b595-jgnql 1/1 Running 0 81m kube-system pod/local-path-provisioner-7ff9579c6-vxf5p 1/1 Running 0 81m kube-system pod/coredns-66c464876b-9tjjs 1/1 Running 0 81m kube-system pod/helm-install-traefik-x92fq 0/1 Completed 0 81m kube-system pod/svclb-traefik-wtm4x 2/2 Running 0 80m kube-system pod/traefik-5dd496474-64zdf 1/1 Running 0 80m kube-system pod/svclb-traefik-7ztm9 2/2 Running 0 67m NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 81m kube-system service/kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP,9153/TCP 81m kube-system service/metrics-server ClusterIP 10.43.90.155 <none> 443/TCP 81m kube-system service/traefik-prometheus ClusterIP 10.43.82.77 <none> 9100/TCP 80m kube-system service/traefik LoadBalancer 10.43.143.86 192.168.128.23 80:30876/TCP,443:31599/TCP 80m NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE kube-system daemonset.apps/svclb-traefik 2 2 2 2 2 <none> 80m NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE kube-system deployment.apps/metrics-server 1/1 1 1 81m kube-system deployment.apps/local-path-provisioner 1/1 1 1 81m kube-system deployment.apps/coredns 1/1 1 1 81m kube-system deployment.apps/traefik 1/1 1 1 80m NAMESPACE NAME DESIRED CURRENT READY AGE kube-system replicaset.apps/metrics-server-7b4f8b595 1 1 1 81m kube-system replicaset.apps/local-path-provisioner-7ff9579c6 1 1 1 81m kube-system replicaset.apps/coredns-66c464876b 1 1 1 81m kube-system replicaset.apps/traefik-5dd496474 1 1 1 80m NAMESPACE NAME COMPLETIONS DURATION AGE kube-system job.batch/helm-install-traefik 1/1 62s 81m
簡単なnginx podを起動させる
- server側で実施
# kubectl run nginx --image=nginx:1.19 pod/nginx created kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 1/1 Running 0 3m19s 10.42.1.3 k3s-agent <none> <none> [root@k3s-server ~]#
agert側でpodが稼働していますね。
もう少し複雑にして * DeploymentでReplicsSetで複数podを起動し、NodePortで外部へ公開してみます。
yamlの定義は以下のようにします。
apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment spec: replicas: 3 selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: nginx-container image: nginx:1.19 --- apiVersion: v1 kind: Service metadata: name: sample-nodeport spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 8080 targetPort: 80 nodePort: 30080 selector: app: sample-app
server上で適応する
# cat <<EOF > sample-app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment spec: replicas: 3 selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: nginx-container image: nginx:1.19 --- apiVersion: v1 kind: Service metadata: name: sample-nodeport spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 8080 targetPort: 80 nodePort: 30080 selector: app: sample-app EOF # kubectl create -f sample-app.yaml deployment.apps/sample-deployment created service/sample-nodeport created # kubectl get all -n default NAME READY STATUS RESTARTS AGE pod/nginx 1/1 Running 0 11m pod/sample-deployment-85cc985d9c-zff9p 1/1 Running 0 44s pod/sample-deployment-85cc985d9c-xmmth 1/1 Running 0 44s pod/sample-deployment-85cc985d9c-44bw2 1/1 Running 0 44s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 125m service/sample-nodeport NodePort 10.43.166.238 <none> 8080:30080/TCP 44s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/sample-deployment 3/3 3 3 44s NAME DESIRED CURRENT READY AGE replicaset.apps/sample-deployment-85cc985d9c 3 3 3 44s
NodePortなのでserver/agentのip addressでアクセスすると見れます。
アンインストール
- uninstall専用のscriptが用意いるので実行する。
- がその前に念の為、delete nodeしてから実行することにします。
- server側で実施
# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k3s-agent Ready <none> 172m v1.19.3+k3s3 192.168.128.26 <none> CentOS Linux 7 (Core) 3.10.0-1062.1.2.el7.x86_64 containerd://1.4.1-k3s1 k3s-server Ready master 3h6m v1.19.3+k3s3 192.168.128.23 <none> CentOS Linux 7 (Core) 3.10.0-1062.1.2.el7.x86_64 containerd://1.4.1-k3s1 # kubectl delete node k3s-agent node "k3s-agent" deleted # kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k3s-server Ready master 3h6m v1.19.3+k3s3 192.168.128.23 <none> CentOS Linux 7 (Core) 3.10.0-1062.1.2.el7.x86_64 containerd://1.4.1-k3s1
この状態でuninstall.shを実行します。
少々長いですがコマンド結果も何をしているのかがわかるので省略せずそのままにしておきます。
* agent側
# sh /usr/local/bin/k3s-agent-uninstall.sh ++ id -u + '[' 0 -eq 0 ']' + /usr/local/bin/k3s-killall.sh + for service in '/etc/systemd/system/k3s*.service' + '[' -s /etc/systemd/system/k3s-agent.service ']' ++ basename /etc/systemd/system/k3s-agent.service + systemctl stop k3s-agent.service + for service in '/etc/init.d/k3s*' + '[' -x '/etc/init.d/k3s*' ']' + killtree + kill -9 + do_unmount /run/k3s + awk -v path=/run/k3s '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + sort -r + xargs -r -t -n 1 umount + do_unmount /var/lib/rancher/k3s + sort -r + xargs -r -t -n 1 umount + awk -v path=/var/lib/rancher/k3s '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + do_unmount /var/lib/kubelet/pods + sort -r + xargs -r -t -n 1 umount + awk -v path=/var/lib/kubelet/pods '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + do_unmount /run/netns/cni- + sort -r + xargs -r -t -n 1 umount + awk -v path=/run/netns/cni- '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + read ignore iface ignore + ip link show + grep 'master cni0' + ip link delete cni0 + ip link delete flannel.1 + rm -rf /var/lib/cni/ + grep -v KUBE- + grep -v CNI- + iptables-restore + iptables-save + which systemctl /usr/bin/systemctl + systemctl disable k3s-agent Removed symlink /etc/systemd/system/multi-user.target.wants/k3s-agent.service. + systemctl reset-failed k3s-agent + systemctl daemon-reload + which rc-update which: no rc-update in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) + rm -f /etc/systemd/system/k3s-agent.service + rm -f /etc/systemd/system/k3s-agent.service.env + trap remove_uninstall EXIT + for cmd in kubectl crictl ctr + '[' -L /usr/local/bin/kubectl ']' + rm -f /usr/local/bin/kubectl + for cmd in kubectl crictl ctr + '[' -L /usr/local/bin/crictl ']' + rm -f /usr/local/bin/crictl + for cmd in kubectl crictl ctr + '[' -L /usr/local/bin/ctr ']' + rm -f /usr/local/bin/ctr + rm -rf /etc/rancher/k3s + rm -rf /run/k3s + rm -rf /run/flannel + rm -rf /var/lib/rancher/k3s + rm -rf /var/lib/kubelet + rm -f /usr/local/bin/k3s + rm -f /usr/local/bin/k3s-killall.sh + remove_uninstall + rm -f /usr/local/bin/k3s-agent-uninstall.sh # systemctl status k3s Unit k3s.service could not be found.
- server側
# sh /usr/local/bin/k3s-uninstall.sh ++ id -u + '[' 0 -eq 0 ']' + /usr/local/bin/k3s-killall.sh + for service in '/etc/systemd/system/k3s*.service' + '[' -s /etc/systemd/system/k3s.service ']' ++ basename /etc/systemd/system/k3s.service + systemctl stop k3s.service + for service in '/etc/init.d/k3s*' + '[' -x '/etc/init.d/k3s*' ']' + killtree 1755 1817 1837 2537 2599 14783 22102 22103 22204 22425 + kill -9 1755 1782 2028 1817 1897 1952 1837 1907 2070 2537 2555 2666 2709 2599 2617 2786 14783 14803 14953 14998 22102 22154 22296 22375 22103 22139 22306 22374 22204 22222 22544 22425 22447 22791 + do_unmount /run/k3s + xargs -r -t -n 1 umount + awk -v path=/run/k3s '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + sort -r umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/f3c7d09a32ad5c8cfb3ba7c6eff2e1f1e4050513dfd337003800fc52bd12e556/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/e5c4bf68e51e2d3a96f214414e297df73f2caaf4c073a9ca55181e4c2d273513/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/be5b76cc8349acf01fcaccd4e644ad276602316314de911c0a1f9e3889ff61bf/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/a86e3ea2d0f623a3d8c82f9f5a616c18006ecd86c9f7d70209ef370454d4c62b/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/a13b1be939373049e5f44e342a26bee583b78ca3d16dac5c5ac0a25d07136c32/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/9824ef29d876d45cb62fdcb22bc06096a4ffb1cf8a5f7b2b76bb828a18d6ed8b/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/969f4e538857b36527464e403e8fd10bc4ec56148d6596f361f101c984886b62/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/87653e291576f28db869dc8f1b490606c176b3bef158626af3074ac4851e33bc/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/78d81ea5e5cfadc08735068e966bbc849e6aa401a64421f3e5837327c302077e/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/69ccc8d2185c4049903a730eee4c55f920ac9c0eb4ea58e29b5c0ce3bce171fd/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/4fe5d8afd6399e1154899fe0426d40c0705511164ed7ed9c2eaa62e754f7fd6a/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/4817814ae99b99b3245c684df553337a254276a6d1a67a6e663b3cb44e698adb/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/43018d27267e76675ccfccb5f2bff44cd958cdc1b395bafd42dd6a85e302b383/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/416f18f95852af17b264bc2edad06e81bc31080d32eb82e93eabd95531b23349/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/3c8ce42af2d1a12043e7a68b915527077279035f4a89a0014ae465fd17e10847/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/2fc4283627fa75a98c0bc69d2b361bc7ee0bb4ac9a1a5ac46b6baefbd7476cda/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/2ad25f4eb64a1e8a90ef742ae18ee1b00c3f553af249782c14854d4c8f6bfae0/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/23c1b6c10d4d712e5c0ae05b29302293cf17864f559cf2fea92b8228d771f974/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/1f560c4ba2ae8180c7e6d33c259b8a1eb80a0edbc4928a29cb1d4a6b8c228039/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/0e50784f76761f20b65825b85de24aaea7c8c9aec0ff9414e5d0e0ffccd3c75d/rootfs umount /run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/0135f4349da8468c78c2b49da084e95c061a764a0829bf8e733edcf0d998ded5/rootfs umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/f3c7d09a32ad5c8cfb3ba7c6eff2e1f1e4050513dfd337003800fc52bd12e556/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/e5c4bf68e51e2d3a96f214414e297df73f2caaf4c073a9ca55181e4c2d273513/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/be5b76cc8349acf01fcaccd4e644ad276602316314de911c0a1f9e3889ff61bf/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/a13b1be939373049e5f44e342a26bee583b78ca3d16dac5c5ac0a25d07136c32/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/969f4e538857b36527464e403e8fd10bc4ec56148d6596f361f101c984886b62/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/87653e291576f28db869dc8f1b490606c176b3bef158626af3074ac4851e33bc/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/78d81ea5e5cfadc08735068e966bbc849e6aa401a64421f3e5837327c302077e/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/4817814ae99b99b3245c684df553337a254276a6d1a67a6e663b3cb44e698adb/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/23c1b6c10d4d712e5c0ae05b29302293cf17864f559cf2fea92b8228d771f974/shm umount /run/k3s/containerd/io.containerd.grpc.v1.cri/sandboxes/1f560c4ba2ae8180c7e6d33c259b8a1eb80a0edbc4928a29cb1d4a6b8c228039/shm + do_unmount /var/lib/rancher/k3s + xargs -r -t -n 1 umount + awk -v path=/var/lib/rancher/k3s '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + sort -r + do_unmount /var/lib/kubelet/pods + sort -r + xargs -r -t -n 1 umount + awk -v path=/var/lib/kubelet/pods '$2 ~ ("^" path) { print $2 }' /proc/self/mounts umount /var/lib/kubelet/pods/f8e18350-11ba-441d-afed-db25934f906e/volumes/kubernetes.io~secret/coredns-token-b9ffd umount /var/lib/kubelet/pods/b92fc364-7ba1-44d2-b82a-a1f6c0e64bbe/volumes/kubernetes.io~secret/default-token-79pl6 umount /var/lib/kubelet/pods/8c656086-8f4e-4abc-bfe9-9634b411cf73/volumes/kubernetes.io~secret/default-token-79pl6 umount /var/lib/kubelet/pods/8c2c9c75-8a2c-443b-a8e0-7664855087b8/volumes/kubernetes.io~secret/default-token-m2jcp umount /var/lib/kubelet/pods/4206b991-ff8f-40df-ab59-4793dc29a351/volumes/kubernetes.io~secret/kubernetes-dashboard-token-sw429 umount /var/lib/kubelet/pods/340715e3-b520-4527-b00a-4ca397373a45/volumes/kubernetes.io~secret/traefik-token-56jkz umount /var/lib/kubelet/pods/340715e3-b520-4527-b00a-4ca397373a45/volumes/kubernetes.io~secret/ssl umount /var/lib/kubelet/pods/1db035d9-a420-468e-9425-9f2c280494e3/volumes/kubernetes.io~secret/kubernetes-dashboard-token-sw429 umount /var/lib/kubelet/pods/1db035d9-a420-468e-9425-9f2c280494e3/volumes/kubernetes.io~secret/kubernetes-dashboard-certs umount /var/lib/kubelet/pods/1d5efe23-b957-4b69-8fd1-6b773332ca12/volumes/kubernetes.io~secret/local-path-provisioner-service-account-token-vrfsd umount /var/lib/kubelet/pods/1ccfdee1-81d7-4e95-99c8-9ab0eead01f5/volumes/kubernetes.io~secret/metrics-server-token-jhj89 umount /var/lib/kubelet/pods/0a0bcfb6-61f0-4a33-9480-40a5a75c147d/volumes/kubernetes.io~secret/default-token-79pl6 + do_unmount /run/netns/cni- + xargs -r -t -n 1 umount + awk -v path=/run/netns/cni- '$2 ~ ("^" path) { print $2 }' /proc/self/mounts + sort -r umount /run/netns/cni-c2f82672-1b96-e506-ac5b-1f07f25800c2 umount /run/netns/cni-c2ae6350-5039-18f5-798d-be09a81a04bf umount /run/netns/cni-b85f6a5d-5612-9a93-3fc1-23a91b90c8be umount /run/netns/cni-a9b294a8-f0ae-09c4-e895-c8f0056468fe umount /run/netns/cni-8ebfe16d-21fd-222b-5ef1-3af9c784c636 umount /run/netns/cni-8a29a30a-bfcd-d92f-c99f-d71c9ad49d83 umount /run/netns/cni-7b94dacb-da32-0005-9108-1e2c2de9b491 umount /run/netns/cni-2d6ca6ae-b776-e142-a137-70f7fffa8f9f umount /run/netns/cni-153e782e-7177-ad88-e329-7a0733806f46 umount /run/netns/cni-06406680-9ae5-f815-95cb-9f7cf4cbd6e4 + read ignore iface ignore + ip link show + grep 'master cni0' + iface=veth9e8235f0 + '[' -z veth9e8235f0 ']' + ip link delete veth9e8235f0 + read ignore iface ignore + iface=vethda58bd85 + '[' -z vethda58bd85 ']' + ip link delete vethda58bd85 + read ignore iface ignore + iface=veth425cb97f + '[' -z veth425cb97f ']' + ip link delete veth425cb97f + read ignore iface ignore + iface=vethba67606f + '[' -z vethba67606f ']' + ip link delete vethba67606f Cannot find device "vethba67606f" + read ignore iface ignore + iface=veth33673995 + '[' -z veth33673995 ']' + ip link delete veth33673995 Cannot find device "veth33673995" + read ignore iface ignore + ip link delete cni0 + ip link delete flannel.1 + rm -rf /var/lib/cni/ + grep -v KUBE- + grep -v CNI- + iptables-restore + iptables-save + which systemctl /usr/bin/systemctl + systemctl disable k3s Removed symlink /etc/systemd/system/multi-user.target.wants/k3s.service. + systemctl reset-failed k3s + systemctl daemon-reload + which rc-update which: no rc-update in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) + rm -f /etc/systemd/system/k3s.service + rm -f /etc/systemd/system/k3s.service.env + trap remove_uninstall EXIT + for cmd in kubectl crictl ctr + '[' -L /usr/local/bin/kubectl ']' + rm -f /usr/local/bin/kubectl + for cmd in kubectl crictl ctr + '[' -L /usr/local/bin/crictl ']' + rm -f /usr/local/bin/crictl + for cmd in kubectl crictl ctr + '[' -L /usr/local/bin/ctr ']' + rm -f /usr/local/bin/ctr + rm -rf /etc/rancher/k3s + rm -rf /run/k3s + rm -rf /run/flannel + rm -rf /var/lib/rancher/k3s + rm -rf /var/lib/kubelet + rm -f /usr/local/bin/k3s + rm -f /usr/local/bin/k3s-killall.sh + remove_uninstall + rm -f /usr/local/bin/k3s-uninstall.sh # systemctl status k3s Unit k3s.service could not be found.
出力結果をみると結構きれいに消してくれました。
次回は軽量なalpine Linux上のインストールにして、
CNIもCanalに変更してkubernetesの検証環境を作ってみたいと思います。
oracle db接続可能で一番簡単なweb clientは多分metabase
本記事でやること
モチベーション
- oracle dbをとりあえず構築したあと、SQLでuser作成したり、table作成したいがsqlplusだとややめんどくさい。
- SQL Developerで繋げばいいが、例えばLinux Server上では使えない。
- web clientで利用できればみんな使える。
環境
- macのversion
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H15
- docker for macのversion
$ docker --version Docker version 19.03.5, build 633a0ea
- なおOracleDBはdockerで構築済の19.3.0-eeを利用する。
- dockerでOracleDB 19.3.0-eeを構築する方法は今度記載する。
metabase containerの起動
- metabaseの公式イメージをpullし実行する。 https://hub.docker.com/r/metabase/metabase
$ docker pull metabase/metabase $ docker run -d -p 3000:3000 --name metabase metabase/metabase # 少し時間がかかるが以下のメッセージが表示されれば起動完了。 $ docker logs -f metabase ・・・ 2020-11-12 11:47:46,094 INFO metabase.core :: Metabase Initialization COMPLETE
- 以下のURLにブラウザでアクセスするとmetabaseを利用できる。
ここで画面に従って初期設定をするのだが、通常のmetabaseだとoracle接続するメニューが出てこないので先にojdbcのjarをcontainer上にコピーする。
ojdbcのダウンロードとcontainerへコピー
- 以下oracleのサイトからojdbc8.jarをダウンロードする。
- ダウンロードするのにアカウントを作る必要があるが適当に作る。(作りたくない)
https://www.oracle.com/database/technologies/jdbc-ucp-122-downloads.html
ダウンロードしたらojdbc8.jarを起動中のcontainer内にコピーし、再起動する。
$ docker cp ./ojdbc8.jar metabase:/plugins/ojdbc8.jar $ docker restart metabase # 起動logを見ると読み込んでいることがわかる。 $ docker logs metabase |grep oracle ・・・ 2020-11-12 12:13:39,313 INFO driver.impl :: Registered driver :oracle (parents: [:sql-jdbc]) 🚚
oracle dbへmetabaseから接続
- 現在oracle dbとmetabaseのcontainerを実行している状態。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9db58c841a00 metabase/metabase "/app/run_metabase.sh" 34 minutes ago Up 8 minutes 0.0.0.0:3000->3000/tcp metabase c3ef73e5ecdc oracle/database:19.3.0-ee "/bin/sh -c 'exec $O…" 2 weeks ago Up 38 minutes (healthy) 0.0.0.0:1521->1521/tcp, 0.0.0.0:5500->5500/tcp orcl
- あとでmetabaseから接続するようにcontainerのip addressを見ておく。
$ docker exec orcl hostname -i 172.17.0.2
- ちなみに接続パラメータはこんな感じだ。
$ docker exec orcl env | grep ORACLE ORACLE_SID=orclcdb ORACLE_PDB=orclpdb1 ORACLE_PWD=orclcdbpassword ORACLE_CHARACTERSET=AL32UTF8 ORACLE_BASE=/opt/oracle ORACLE_HOME=/opt/oracle/product/19c/dbhome_1
- service name
$ docker exec orcl lsnrctl status LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 12-NOV-2020 12:26:20 Copyright (c) 1991, 2019, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 19.0.0.0.0 - Production Start Date 12-NOV-2020 11:42:52 Uptime 0 days 0 hr. 43 min. 28 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora Listener Log File /opt/oracle/diag/tnslsnr/c3ef73e5ecdc/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=c3ef73e5ecdc)(PORT=5500))(Security=(my_wallet_directory=/opt/oracle/admin/ORCLCDB/xdb_wallet))(Presentation=HTTP)(Session=RAW)) Services Summary... Service "ORCLCDB" has 1 instance(s). Instance "ORCLCDB", status READY, has 1 handler(s) for this service... Service "ORCLCDBXDB" has 1 instance(s). Instance "ORCLCDB", status READY, has 1 handler(s) for this service... Service "b2956b7549370d16e053020011ac022f" has 1 instance(s). Instance "ORCLCDB", status READY, has 1 handler(s) for this service... Service "orclpdb1" has 1 instance(s). Instance "ORCLCDB", status READY, has 1 handler(s) for this service... The command completed successfully
- この状態で設定画面にいくと、通常は出てこないがoracleが選択できるようになってる。
以下のように設定する。(他は適当で良い)
- いい感じですね。
ちなみに
- cpしてrestartするの面倒だなと思ったときはimageから作っても良い。
FROM metabase/metabase COPY ojdbc8.jar /plugins/ojdbc8.jar
あとがき
Linuxでchmod -R 777 /した時なぜsudoとかできなくなるのか?
まえがき
- Linuxでroot directoryから『chmod -R 777 /』実行してしまい障害になったケースはよく聞く。
- 最近自分の周りでもこうした障害が発生したのだが、当時sudoコマンドとかが使えなくなったという。
- なぜ使えなくなったのかを調べてみる。
問題のコマンド
rootユーザで以下コマンドを本番環境で実行すると少しハイな気持ちになれます。
# chmod -R 777 /
まずsudoのそもそものパーミッションをCentOS7で確認してみるとsuidがついている。
# ls -l /usr/bin/sudo ---s--x--x. 1 root root 147336 4月 1 2020 /usr/bin/sudo
実際は4511なので777だとパーミッションが足りないことがわかる。
いや777なら行けそうじゃんと思うが、sudoの実行時にsuidのチェックが実行されるのでNGとなる。
sudoのソースコードを見てみたけど多分この部分でチェックが入っている。
https://github.com/sudo-project/sudo/blob/72df19088b57b32a20a92d97fa4b1181439d49b0/src/sudo.c#L192
suidは一般ユーザが実行時にroot権限で実行できる仕組み。
詳しくはredhat者がちゃんと書いてくれているので以下を見ておくといいかも。
https://www.redhat.com/sysadmin/suid-sgid-sticky-bit
同じくsuidの他にsgidもあるがこれらも同じくそういう制御が入っているはずなので、777にすると動かない 以下でfindするとそこそこある passwdとか確かにsuidの動きだわーと思った。
# find / \( -perm -4000 -or -perm -2000 \) -type f -exec ls -la {} \; -r-xr-sr-x. 1 root tty 15344 6月 10 2014 /usr/bin/wall -rws--x--x. 1 root root 23968 4月 1 2020 /usr/bin/chfn -rws--x--x. 1 root root 23880 4月 1 2020 /usr/bin/chsh -rwsr-xr-x. 1 root root 32128 4月 1 2020 /usr/bin/su -rwsr-xr-x. 1 root root 27856 4月 1 2020 /usr/bin/passwd -rwsr-xr-x. 1 root root 32096 10月 31 2018 /usr/bin/fusermount -rwsr-xr-x. 1 root root 73888 8月 9 2019 /usr/bin/chage -rwsr-xr-x. 1 root root 78408 8月 9 2019 /usr/bin/gpasswd -rwsr-xr-x. 1 root root 41936 8月 9 2019 /usr/bin/newgrp -rwsr-xr-x. 1 root root 44264 4月 1 2020 /usr/bin/mount -rwsr-xr-x. 1 root root 23576 4月 1 2020 /usr/bin/pkexec -rwsr-xr-x. 1 root root 31984 4月 1 2020 /usr/bin/umount -rwsr-xr-x. 1 root root 57656 8月 9 2019 /usr/bin/crontab ・・・・
ちなみに/etc/ssh/sshd_configは600じゃないとだめって決まってるがその理由は多分これで、同じくパーミッションのチェックが入ってる。
https://github.com/openssh/openssh-portable/blob/2f2ffa4fbe4b671bbffa0611f15ba44cff64d58e/auth.c#L509
sticky bit系のファイルも777にすると誰でも消せるようになるのであんまし良くない。
drwxrwxrwt. 6 root root 4096 11月 10 20:06 2020 tmp