CLI素人さんに、簡易ボタンでsystemctl restart nginxを自分でやってもらう方法

# え？嫌なんですけど・・・

**「今日の夜１１時から緊急リリースになった。WEBサーバーの再起動をお願いしたいんだけど・・・」**

と、終業時間10分前にいきなりの依頼。

**「え？嫌なんですけど・・・」**

と言いたい、、、
この後予定も入れちゃっているし無理・・・

こんなシチュエーションってないですか？

「手順教えるんで、自分でやってください」と、言えたとして
いざ相手にCLI作業をしてもらおうとすると、

* ターミナルソフトをインストールしてもらい、
* サーバーにアカウントを作って、
* SSH鍵を登録して、
* 手順を書いて
* ・・・

と、今日の今日で、自分でやってもらうのは現実的ではありません。

無理にやってもらって、オペミスでもされたらリカバリが大変です、
結局、自分でやるしかないと、諦めてしぶしぶ引き受けていませんか？

そんな時、

* **使い捨ての簡易ボタン作って、セルフでオペレーションしてもらう**

こんな選択肢が持てたらどうでしょう。


# 使い捨ての簡易ボタン

今回であれば、こんな簡易ボタンがあれば十分です。

![2018-05-31 10_10_24-qiita-restart-menu - draw.io.png](https://qiita-image-store.s3.amazonaws.com/0/133603/a1ee8910-f3bf-377b-ddce-9e43e9e66219.png)


* 誰でもボタンが押せては困るので、アクセス制限はつけます
* 操作メニュー画面でボタンが押せるようにして、ボタンを押すと対応するコマンドが実行され、結果が表示される。
    * **restart**　が押されたら `sudo systemctl restart nginx; sudo systemctl status nginx`
    * **status**　が押されたら `sudo systemctl status nginx`
    * **stop**　が押されたら `sudo systemctl stop nginx`
    * **start**　が押されたら `sudo systemctl start nginx`

これがあれば、今回の要求には十分応えられます。オペミスの心配もいりません。

じゃ、さっそくこれを作ろう！

これを作るには、

* 自由に使えるサーバーを見つけて
* ウェブサーバをセットアップして
* 簡易ボタンのプログラムを書いて
* アクセス制限設定して
* ・・・

といろいろ準備が必要です。
また、サーバー構築とアプリ開発の経験も必要です。
経験者ならできなくはないけど、それなりの時間がかかります。今回のシチュエーションでこのアプローチは現実的ではありません。


# FrontOps(フロント・オプス)

こんな時に、持っていると重宝するアプリが**FrontOps(フロント・オプス)**です。

これを使うと、
サーバー構築やアプリ開発の経験がなくても、（あれば、より簡単に）

* HTMLのformタグが使える
* SSHでログインしてCLI操作ができる
* ExcelやPowerPointで図形で作図できる

ができれば簡易ボタンアプリが作れます。

サーバーマシンや、ウェブサーバーの準備・設定は不要です。
PCの上でアプリを動かし、インターネットからアクセス制限付きで利用させることができます。


これを使って、作った簡易ボタンアプリがこれ。

![2018-05-31 10_12_10-restart-menu.json - FrontOps.png](https://qiita-image-store.s3.amazonaws.com/0/133603/0917bd8a-e5ae-3ce2-8965-c281a90c62ad.png)

部品を線でつないで、設定して、動作確認したら、
メニューからインターネットに公開しておしまいです。

![2018-06-01 09_42_57-restart-menu.json - FrontOps.png](https://qiita-image-store.s3.amazonaws.com/0/133603/f73ae29a-c8de-8c1e-70b4-b60c8e12be34.png)

作成所要時間は、テスト含めて10分です。

# まとめ

**FrontOps**を使うと、簡易ボタンが、使い捨て出来る手軽さで簡単に用意できました。

これなら、

* 使い捨ての簡易ボタン作って、セルフでオペレーションしてもらう

が選択肢にできるのではないでしょうか


# おわりに

**「今日の夜１１時から緊急リリースになった。WEBサーバーの再起動をお願いしたいんだけど・・・」**

と、終業時間10分前にいきなりの依頼。

**「え、わかりました。簡易ボタンを用意しておきますね。後でURLと認証情報を送るので、これでアクセスして再起動してください。」**

・・・

さて、URLと認証情報も送ったし、ちょうど定時だ。予定の待ち合わせ場所に向かおう・・・


# Appendix

* FrontOps
  * https://frontops.exhands.org
  * FREEプランで1回7時間まで使えます。普段使いにはFREEプランで十分です。


* 簡易ボタンフロー

```json
[{"id":"189ab287.5f63ad","type":"http in","z":"6f8972d6.2050fc","name":"","url":"/menu","method":"get","upload":false,"swaggerDoc":"","x":140,"y":220,"wires":[["3d422806.1b4ab8"]]},{"id":"4a7d240b.ce7f6c","type":"http response","z":"6f8972d6.2050fc","name":"","statusCode":"","headers":{},"x":630,"y":220,"wires":[]},{"id":"c1a1380b.448ff8","type":"template","z":"6f8972d6.2050fc","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<h3>操作メニュー</h3>\n<form method='POST' action='/order'>\n<input type='submit' name='cmd' value='restart'>\n<input type='submit' name='cmd' value='status'>\n<input type='submit' name='cmd' value='stop'>\n<input type='submit' name='cmd' value='start'>\n</form>","output":"str","x":480,"y":220,"wires":[["4a7d240b.ce7f6c"]]},{"id":"de4f0ca6.b61","type":"http in","z":"6f8972d6.2050fc","name":"","url":"/order","method":"post","upload":false,"swaggerDoc":"","x":150,"y":340,"wires":[["3819882a.b94318"]]},{"id":"896214d6.13e3c8","type":"command","z":"6f8972d6.2050fc","connectionconfig":"f25716d3.d04208","command":"sudo systemctl status nginx","timer":"","oldrc":false,"env":"","pty":false,"trim":false,"stdin":false,"field":"payload","fieldType":"msg","name":"","x":680,"y":320,"wires":[["5a0b9a4f.92ec74"]]},{"id":"5a0b9a4f.92ec74","type":"template","z":"6f8972d6.2050fc","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<pre>\n{{{payload.code}}}\n{{{payload.stdout}}}\n{{{payload.stderr}}}\n</pre>\n<a href=\"/menu\">back</a>\n","output":"str","x":900,"y":340,"wires":[["7f1f3f64.f5e9a"]]},{"id":"7f1f3f64.f5e9a","type":"http response","z":"6f8972d6.2050fc","name":"","statusCode":"","headers":{},"x":1030,"y":340,"wires":[]},{"id":"49577dc7.07a874","type":"switch","z":"6f8972d6.2050fc","name":"","property":"payload.cmd","propertyType":"msg","rules":[{"t":"eq","v":"restart","vt":"str"},{"t":"eq","v":"status","vt":"str"},{"t":"eq","v":"stop","vt":"str"},{"t":"eq","v":"start","vt":"str"}],"checkall":"false","repair":false,"outputs":4,"x":470,"y":340,"wires":[["50ab20bd.6216b"],["896214d6.13e3c8"],["622f2c04.864574"],["31d56bcf.2a1b24"]]},{"id":"50ab20bd.6216b","type":"command","z":"6f8972d6.2050fc","connectionconfig":"f25716d3.d04208","command":"sudo systemctl restart nginx;\nsudo systemctl status nginx","timer":"","oldrc":false,"env":"","pty":false,"trim":false,"stdin":false,"field":"payload","fieldType":"msg","name":"","x":770,"y":280,"wires":[["5a0b9a4f.92ec74"]]},{"id":"3d422806.1b4ab8","type":"node-red-contrib-httpauth","z":"6f8972d6.2050fc","name":"","file":"","cred":"","authType":"Basic","realm":"normal","username":"guest","password":"guest","hashed":false,"x":320,"y":220,"wires":[["c1a1380b.448ff8"]]},{"id":"3819882a.b94318","type":"node-red-contrib-httpauth","z":"6f8972d6.2050fc","name":"","file":"","cred":"","authType":"Basic","realm":"normal","username":"guest","password":"guest","hashed":false,"x":320,"y":340,"wires":[["49577dc7.07a874"]]},{"id":"622f2c04.864574","type":"command","z":"6f8972d6.2050fc","connectionconfig":"f25716d3.d04208","command":"sudo systemctl stop nginx","timer":"","oldrc":false,"env":"","pty":false,"trim":false,"stdin":false,"field":"payload","fieldType":"msg","name":"","x":670,"y":360,"wires":[["5a0b9a4f.92ec74"]]},{"id":"31d56bcf.2a1b24","type":"command","z":"6f8972d6.2050fc","connectionconfig":"f25716d3.d04208","command":"sudo systemctl start nginx","timer":"","oldrc":false,"env":"","pty":false,"trim":false,"stdin":false,"field":"payload","fieldType":"msg","name":"","x":670,"y":400,"wires":[["5a0b9a4f.92ec74"]]},{"id":"f25716d3.d04208","type":"connection","z":"","name":"cham-house.tk","host":"cham-house.tk","username":"sakazuki"}]
```