JSON-RPC経由でシェルコマンドを実行したい事があって、以下のようなRubyスクリプトを書きました。
以下のようなリクエストに対して、
1
2
3
4
5
6
7
8
9
| {
"jsonrpc":"2.0",
"id": "1",
"method":"shell",
"params": [
{ "command": "ls -a" },
{ "command": "pwd" }
]
}
|
次のようなレスポンスを返します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| {
"jsonrpc": "2.0",
"result": [
{
"command": "ls -a",
"stdout.json": null,
"stdout": ".\n..\n.git\n.gitignore\n.ruby-version\nDockerfile\nGemfile\nGemfile.lock\nREADME.md\napp.rb\n",
"stderr": "",
"status": {
"exitstatus": 0,
"pid": 73595
}
},
{
"command": "pwd",
"stdout.json": null,
"stdout": "/Users/tumf/work/shell-jsonrpc\n",
"stderr": "",
"status": {
"exitstatus": 0,
"pid": 73596
}
}
],
"id": "1"
}
|
スクリプトは以下のような感じです
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| require 'bundler/setup'
require 'jimson'
require 'json'
require "open3"
class MyHandler
extend Jimson::Handler
def shell *params
params.collect { |param|
c = param["command"]
o, e, s = Open3.capture3(c, stdin_data: param["stdin"])
json = JSON.parse(o) rescue nil
{ command: c, "stdout.json": json, stdout: o, stderr: e, status: { exitstatus: s.to_i, pid: s.pid } }
}
rescue =>e
p e
p e.backtrace
raise
end
end
server = Jimson::Server.new(MyHandler.new)
server.start # serve with webrick on http://0.0.0.0:8999/
|
ソース一式はgithub: https://github.com/tumf/shell-jsonrpc
DockerイメージはDockerHubに公開してあります。
1
| $ docker push tumf/shell-jsonrpc
|
起動
デフォルトで8999番ポートをListenするので、curlで試すなら以下のようにしてください。
1
| $ curl http://0.0.0.0:8999 -d '{"jsonrpc":"2.0", "id": "1", "method":"shell", "params": [{ "command": "ls -a" }, {"command": "pwd"}] }' |jq .
|