|
| 1 | +defaults = [user: "deploy", password: "deploy", silently_accept_hosts: true] |
| 2 | + |
| 3 | +hosts = |
| 4 | + [{"127.0.0.1", port: 2222}, {"127.0.0.1", port: 2223}] |
| 5 | + |> Enum.map(fn {name, options} -> {name, Keyword.merge(defaults, options)} end) |
| 6 | + |
| 7 | +conns = Enum.map(hosts, fn {name, options} -> |
| 8 | + {:ok, conn} = SSHKit.connect(name, options) |
| 9 | + conn |
| 10 | +end) |
| 11 | + |
| 12 | +label = fn conn -> Enum.join([conn.host, conn.port], ":") end |
| 13 | + |
| 14 | +tasks = |
| 15 | + Enum.map(conns, fn conn -> |
| 16 | + Task.async(fn -> |
| 17 | + {:ok, chan} = SSHKit.run(conn, "uptime") |
| 18 | + |
| 19 | + chan |
| 20 | + |> SSHKit.stream() |
| 21 | + |> Enum.reduce(nil, fn |
| 22 | + {:stdout, chan, output}, acc -> |
| 23 | + IO.write("[#{label.(chan.connection)}] (stdout) #{output}") |
| 24 | + acc |
| 25 | + |
| 26 | + {:stderr, chan, output}, acc -> |
| 27 | + IO.write("[#{label.(chan.connection)}] (stderr) #{output}") |
| 28 | + acc |
| 29 | + |
| 30 | + {:exit, _, status}, _ -> |
| 31 | + status |
| 32 | + |
| 33 | + _, acc -> |
| 34 | + acc |
| 35 | + end) |
| 36 | + end) |
| 37 | + end) |
| 38 | + |
| 39 | +okay? = fn status -> status == 0 end |
| 40 | + |
| 41 | +results = Enum.map(tasks, &Task.await/1) |
| 42 | + |
| 43 | +unless Enum.all?(results, okay?) do |
| 44 | + results |
| 45 | + |> Enum.with_index() |
| 46 | + |> Enum.filter(fn {status, _} -> !okay?.(status) end) |
| 47 | + |> Enum.each(fn {status, index} -> |
| 48 | + conn = Enum.at(conns, index) |
| 49 | + IO.puts("[#{label.(conn)}] exited with status #{status}") |
| 50 | + end) |
| 51 | +end |
| 52 | + |
| 53 | +:ok = Enum.each(conns, &SSHKit.close/1) |
0 commit comments