LoginSignup
5
5

More than 5 years have passed since last update.

goでオリジナルのコンソールを作る

Last updated at Posted at 2018-01-21

誰もがみな幼い頃はアプライアンスのようなオリジナルのコンソールを作りたいと夢見たものです。
と、言うことでGoを使ってオリジナルのコンソールを作ってみる方法を簡単にメモっておきます。

目的

  • Goを使ってインタラクティブシェルを作成する
  • Linuxユーザーのデフォルトをシェルを変更してSSH接続する
  • Goで作ったシェルでオリジナルコマンドが叩けることを確認する

環境

項目 内容
CentOS 7.4
Go 1.9.2

ishell

ここでは、Goでインタラクティブなシェルを作成できる ishell を使ってみたいと思います。

GitHub

https://github.com/abiosoft/ishell

ドキュメント

https://godoc.org/github.com/abiosoft/ishell

やってみる

ソース

orishell.go
package main

import (
    "fmt"

    "github.com/abiosoft/ishell"
)

func hello(a []string) {
    for _, i := range a {
        fmt.Printf("Hello, %s\n", i)
    }
}

func main() {
    // create new shell.
    shell := ishell.New()

    // shell prompt. default: ">>>"
    shell.SetPrompt("(orishell)# ")

    // display message.
    shell.Println("Start Shell")

    // command
    shell.AddCmd(&ishell.Cmd{
        Name: "greet",
        Help: "greet user",
        Func: func(c *ishell.Context) {
            hello(c.Args)
        },
    })
    shell.Run()
}

ビルドする

[root@localhost ~]# go build orishell.go
[root@localhost ~]# mv orishell /usr/local/bin

ユーザーを作成してデフォルトのシェルにする

ここでは example と言うユーザーを作成してデフォルトシェルを orishell にします。

[root@localhost ~]# useradd example
[root@localhost ~]# passwd example
[root@localhost ~]# chsh example
example のシェルを変更します。
新しいシェル [/bin/bash]: /usr/local/bin/orishell
chsh: Warning: "/usr/local/bin/orishell" is not listed in /etc/shells.
シェルを変更しました。

動作確認

こんな感じにログインするとorishellが起動して入力待ちになります。
Tabを押すことで補完が効きます。

ishell_1.gif

モード変更という概念を取り入れてみる

イメージとしてはスイッチとかだと特権モードへ移行する enable です。
ここでは greet モードを作ってみます。
簡単に言うと greetFunc で同じようにコマンドを作ります。
ネストしていくイメージですね。

ソース

orishell.go
package main

import (
    "fmt"

    "github.com/abiosoft/ishell"
)

func goodMorning(a []string) {
    for _, i := range a {
        fmt.Printf("Good Morning, %s\n", i)
    }
}

func hello(a []string) {
    for _, i := range a {
        fmt.Printf("Hello, %s\n", i)
    }
}

func goodEvening(a []string) {
    for _, i := range a {
        fmt.Printf("Good Evening, %s\n", i)
    }
}

func main() {
    // create new shell.
    shell := ishell.New()

    // shell prompt. default: ">>>"
    shell.SetPrompt("(orishell)# ")

    // display message.
    shell.Println("Start Shell")

    // command
    shell.AddCmd(&ishell.Cmd{
        Name: "greet",
        Help: "greet user",
        Func: func(c *ishell.Context) {
            //hello(c.Args)
            subshell := ishell.New()
            subshell.SetPrompt("(greet)# ")
            subshell.Print("greet mode\n")

            // sub commands
            subshell.AddCmd(&ishell.Cmd{
                Name: "goodMorning",
                Help: "print Good Morning",
                Func: func(c *ishell.Context) {
                    goodMorning(c.Args)
                },
            })
            subshell.AddCmd(&ishell.Cmd{
                Name: "hello",
                Help: "print hello.",
                Func: func(c *ishell.Context) {
                    hello(c.Args)
                },
            })
            subshell.AddCmd(&ishell.Cmd{
                Name: "goodEvening",
                Help: "print Good Evening.",
                Func: func(c *ishell.Context) {
                    goodEvening(c.Args)
                },
            })
            subshell.Run()
        },
    })
    shell.Run()
}

動作確認

こんな感じです。

ishell_2.gif

まとめ

ishell を使うことで簡単にインタラクティブシェルな環境を作ることができました。
他にもマルチ選択やチェックリスト、プログレスバーなど実装されているので使える範囲は広いと思います。
これで、コマンドの制御やオリジナルアプライアンスのコンソール実装など面白い事ができそうです。
pythonとかであれば標準の code cmd モジュールとか python-prompt-toolkit とか使えばインタラクティブな環境はすぐ作れそうです。(今度やってみよう)
ただ python-prompt-toolkit のドキュメントをパッと見た限りコマンドのパース処理などはなさそう...

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5