2年くらい前からちょこちょこ作ってたツールがある程度形になってきて、個人的に結構便利に使えるようになったので(ここんとこ忙しくて書くこともないし)紹介してみる。

lssh』という名称でGolangで書いたsshクライアントコマンドで、設定ファイルの内容をもとに接続先を選択できる様になっている。 コマンドなのでMacOS XやLinuxで動くのと、WindowsでもWSL(2018.03のアップデートが適用されてる必要あり)で動作を確認してる(ssh接続処理も全部Golangで書いてるので、多分Windows単体でも動くと思うけど未確認)。 実際に使ってる画面はこんな感じ(gifファイル)。

WSLの場合だとこんな感じ。

lssh(sshクライアント)とlscp(scpクライアント)の2つのコマンドがあって、どちらも同じ設定ファイルを参照している。 helpの出力はこんな感じ。

blacknon@MAIN-DESKTOP:~/lssh_0.5.1_linux_amd64$ lssh --help
NAME:
    lssh - TUI list select and parallel ssh client command.
USAGE:
    lssh [options] [commands...]

OPTIONS:
    --host value, -H value  connect servernames
    --list, -l              print server list from config
    --file value, -f value  config file path (default: "/home/blacknon/.lssh.conf")
    --term, -t              run specified command at terminal
    --parallel, -p          run command parallel node(tail -F etc...)
    --generate              (beta) generate .lssh.conf from .ssh/config.(not support ProxyCommand)
    --help, -h              print this help
    --version, -v           print the version

COPYRIGHT:
    blacknon(blacknon@orebibou.com)

VERSION:
    0.5.1

USAGE:
    # connect ssh
    lssh

    # parallel run command in select server over ssh
    lssh -p command...
blacknon@MAIN-DESKTOP:~/lssh_0.5.1_linux_amd64$ lscp --help
NAME:
    lscp - TUI list select and parallel scp client command.
USAGE:
    lscp [options] (local|remote):from_path... (local|remote):to_path

OPTIONS:
    --host value, -H value  connect servernames
    --list, -l              print server list from config
    --file value, -f value  config file path (default: "/home/blacknon/.lssh.conf")
    --permission, -p        copy file permission
    --help, -h              print this help
    --version, -v           print the version

COPYRIGHT:
    blacknon(blacknon@orebibou.com)

VERSION:
    0.5.1

USAGE:
    # local to remote scp
    lscp /path/to/local... /path/to/remote

    # remote to local scp
    lscp remote:/path/to/remote... /path/to/local

lssh/lscpは、デフォルトで.lssh.confという、下のサンプルのようなtmuxファイルを参照してリストを作成するようにしている。

~/.lssh.conf
# ターミナルログの設定 [log] enable = true # ターミナルログの取得の有効/無効 timestamp = true # ターミナルログの行頭にタイムスタンプをつけるかどうか dirpath = "/path/to/logdir" # ターミナルログの取得先ディレクトリ # サーバの共通設定(server.hoge内の内容で上書きされる)。 # includeで指定してる外出しファイル別に設定できる [common] port = "22" user = "test" # 外出ししたファイルのPATH [include.Name] path = "/path/to/include/file" # サーバ別の設定(server.hogehogeはユニークである必要あり) [server.PasswordAuth_ServerName] addr = "192.168.100.101" pass = "Password" note = "パスワード認証サーバ" [server.KeyAuth_ServerName] addr = "192.168.100.102" user = "test-user" key = "/path/to/private_key" note = "鍵認証接続の場合" [server.KeyAuth_ServerName_withPassphase] addr = "192.168.100.103" user = "test-user" key = "/path/to/private_key" keypass = "KeyPassphase" note = "鍵認証接続の場合(鍵にパスフレーズがかかってる場合)" [server.LocalCommand_ServerName] addr = "192.168.100.104" user = "test-user" key = "/path/to/private_key" keypass = "KeyPassphase" pre_cmd = "ssh接続前にローカルマシンで実行するOSコマンド" post_cmd = "ssh接続終了後にローカルマシンで実行するOSコマンド" note = "ssh接続前/後でローカルでコマンドを実行させる" [server.sshProxyServer] addr = "192.168.100.200" key = "/path/to/private_key" note = "ssh proxyとして動作するサーバ(仮定)" [server.sshProxyServer2] addr = "192.168.10.10" key = "/path/to/private_key" note = "sshProxyServer経由で接続するサーバ" proxy = "sshProxyServer" [server.sshProxyServer3] addr = "192.168.10.100" key = "/path/to/private_key" note = "sshProxyServer→sshProxyServer2を経由して接続するサーバ" proxy = "overProxyServer" [server.overHttpProxy] addr = "over-http-proxy.com" key = "/path/to/private_key" note = "httpプロキシを経由して接続する設定例" proxy = "HttpProxy" proxy_type = "http" [server.overSocks5Proxy] addr = "192.168.10.101" key = "/path/to/private_key" note = "socks5プロキシを経由して接続する設定例" proxy = "Socks5Proxy" proxy_type = "socks5" # httpプロキシサーバ設定例 [proxy.HttpProxy] addr = "example.com" port = "8080" # socks5プロキシサーバ設定例 [proxy.Socks5Proxy] addr = "example.com" port = "54321"
~/.lssh.test
[common] port = "22" pre_cmd = 'printf "\033]50;SetProfile=プロファイル名\a"' pre_cmd = 'printf "\033]50;SetProfile=Default\a"' [server.test-server] addr = "192.168.5.10" user = "test" pass = "test" note = "testサーバ"

以下、個人的に使ってる機能を紹介してみる。

1. 普通にssh/scp接続する

オプションなしでlsshを実行すると、上のサンプルのように記述されている\~/.lssh.confを参照しリストを表示するので、接続したいサーバを選択する。 このとき、キーワードを入力するとそのワードをもつ行のみに絞れるようにしている(スペース区切り。残念ながら正規表現とかそういう機能は現状用意してない(´・ω・`))。

画像はちょっと前のバージョンのやつ。

また、sshコマンドと同じように引数としてコマンドを渡すことで、そのコマンドを選択したサーバで実行できるようになっている。 このとき、Tabキーで複数のサーバを選択できるようにしている(Ctrl-Aで表示されているサーバを全選択)。

lssh command...

lscpは、以下のようにform(複数指定),toのpathを指定する。 リモートを指定する際は「remote(もしくはr):/path/to/remote」、ローカルのときは「local(もしくはlか省略):/path/to/local」で指定する。

lscp /path/to/from ... /path/to/local

lscpはローカル→リモート、リモート→ローカル、リモート→リモートでのscpが行えるようになっている。 lscpも、remoteについてはTabキー、Ctrl-Aで複数選択ができるようになっている(リモートからリモートにscpする際はfromのみ可能)。

2. http/socks5プロキシやsshプロキシ(多段)を使って接続する

lssh/lscpでは、.lssh.confに記述することでhttp/socks5プロキシやsshプロキシ(多段)での接続ができるようにしている。 (http/socks5プロキシはクライアントからの直接接続先としてのみ指定可能。)

↓のような感じで設定ファイルを記述してやる。

~/.lssh.conf
[server.sshProxyServer] addr = "192.168.100.200" key = "/path/to/private_key" note = "ssh proxyとして動作するサーバ(仮定)" [server.sshProxyServer2] addr = "192.168.10.10" key = "/path/to/private_key" note = "sshProxyServer経由で接続するサーバ" proxy = "sshProxyServer" [server.sshProxyServer3] addr = "192.168.10.100" key = "/path/to/private_key" note = "sshProxyServer→sshProxyServer2を経由して接続するサーバ" proxy = "overProxyServer" [server.overHttpProxy] addr = "over-http-proxy.com" key = "/path/to/private_key" note = "httpプロキシを経由して接続する設定例" proxy = "HttpProxy" proxy_type = "http" [server.overSocks5Proxy] addr = "192.168.10.101" key = "/path/to/private_key" note = "socks5プロキシを経由して接続する設定例" proxy = "Socks5Proxy" proxy_type = "socks5" # httpプロキシサーバ設定例 [proxy.HttpProxy] addr = "example.com" port = "8080" # socks5プロキシサーバ設定例 [proxy.Socks5Proxy] addr = "example.com" port = "54321"

3. ssh接続時にターミナルの色や背景画像を変更する

ssh接続時前後にローカルマシンでコマンドを実行させることで、iTermのプロファイルやtmuxのカラーを変更することができる。 (一応、UbuntuのGnome端末でもできるはできる。)

以下、iTerm2の場合。 iTerm2では、以下のようにprintfなどでANSIエスケープを使ってプロファイルを変更できるので、それを利用している。

printf "printf "\033]50;SetProfile=プロファイル名\a""

なので、これをpre_cmd/post_cmdに指定することで、サーバごとにssh接続時に任意のプロファイルを利用できる。

pre_cmd = 'printf "\033]50;SetProfile=プロファイル名\a"'
pre_cmd = 'printf "\033]50;SetProfile=Default\a"'

4. 複数台のサーバにパラレルでコマンドを実行する

lscpで複数台のサーバにコマンドを実行させる際、オプションなしだと一台ずつ接続してコマンドを実行するようにしているが、-pオプションを付与することでパラレルで実行させられるようにしている。 各サーバに接続して tail -f する際などは、このオプションをつけるとログをサーバ別に一つの端末上で確認できる。

5. ローカルのbashrcやvimrcをリモートの環境にファイルを配置せずに使用する(bashのみ)

リモートサーバではbashしか使えないのだけど、前に書いたこれを利用して、ローカルマシンにおいてあるbashrcやvimrcをリモートで利用することもできる(vimrcはbashの関数化する必要がある)。 リモートサーバにはファイルは置かずに、接続セッションでのみ利用するようにしているので、リモートサーバの環境には変更を加えないようにしている。 (そのため、今のところ.bashrc内でsourceしているファイルは読めない。あと、今のバージョンだと各設定ファイルの最後に空行が必要。)

# 個人的にbashrcを分けてるので、その例を使用
[server.UseLocalBashrc_ServerName]
addr = "192.168.100.110"
key  = "/path/to/private_key"
note = "ローカルのbashrcを使って接続する例"
local_rc = 'yes'
local_rc_file = [
    ,"~/dotfiles/bash_prompt"
    ,"~/dotfiles/sh_alias"
    ,"~/dotfiles/sh_export"
    ,"~/dotfiles/sh_function"
]

vimrcを使う場合、リモートのファイルを汚さないために以下の様な関数を使ってローカルのvimrcをbase64化して読み込むようなラッパー関数を作成して、それをaliasで置き換えることで利用できる。

# lvim関数(リモートでローカルの.vimrcを使うための関数)のfunction更新用関数
function update_lvim() {
    echo -n "function lvim() { \\\\vim -u <(echo " $(cat ~/.vimrc|base64) "|base64 -d) \$@ ; }\n" > ~/dotfiles/sh_function_lvim
}

if [ -z "${SSH_CLIENT}" ];then
    # ローカルの場合
    alias vim='vim -u ~/.vimrc'
else
    # リモートの場合
    alias vim=lvim
fi