{"id":13508730,"url":"https://github.com/rubencaro/sshex","last_synced_at":"2025-10-21T19:02:10.815Z","repository":{"id":27190469,"uuid":"30660727","full_name":"rubencaro/sshex","owner":"rubencaro","description":"Simple SSH helpers for Elixir. SSH is useful, but we all love SSHEx !","archived":true,"fork":false,"pushed_at":"2024-10-04T05:13:03.000Z","size":70,"stargazers_count":160,"open_issues_count":3,"forks_count":26,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-11-01T08:33:51.487Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rubencaro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-11T17:40:42.000Z","updated_at":"2024-10-27T03:21:27.000Z","dependencies_parsed_at":"2022-08-17T17:11:05.942Z","dependency_job_id":null,"html_url":"https://github.com/rubencaro/sshex","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fsshex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fsshex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fsshex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fsshex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rubencaro","download_url":"https://codeload.github.com/rubencaro/sshex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246314013,"owners_count":20757451,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T02:00:57.621Z","updated_at":"2025-10-21T19:02:05.521Z","avatar_url":"https://github.com/rubencaro.png","language":"Elixir","funding_links":[],"categories":["Networking"],"sub_categories":[],"readme":"----\nThe actively maintained version of SSHEx is now in https://github.com/witchtails/sshex\n\nThis repo has been archived.\n----\n\n# SSHEx\n[![Build Status](https://travis-ci.org/rubencaro/sshex.svg?branch=master)](https://travis-ci.org/rubencaro/sshex)\n[![Hex Version](http://img.shields.io/hexpm/v/sshex.svg?style=flat)](https://hex.pm/packages/sshex)\n[![Hex Version](http://img.shields.io/hexpm/dt/sshex.svg?style=flat)](https://hex.pm/packages/sshex)\n\nSimple SSH helpers for Elixir.\n\nLibrary to unify helpers already used on several applications. It uses low level Erlang [ssh library](http://www.erlang.org/doc/man/ssh.html).\n\nThe only purpose of these helpers is to avoid repetitive patterns seen when working with SSH from Elixir. It doesn't mean to hide anything from the venerable code underneath. If there's an ugly crash from `:ssh` it will come back as `{:error, reason}`.\n\n## Installation\n\nJust add `{:sshex, \"2.2.1\"}` to your deps on `mix.exs` and run `mix deps.get`\n\n## Use\n\nThen assuming `:ssh` application is already started with `:ssh.start` (hence it is listed on deps), you should acquire an SSH connection using `SSHEx.connect/1` like this:\n\n1.You can use `ssh-copy-id myuser@123.123.123.123.123` to copy ssh key to remote host and then connect using this line:\n```elixir\n{:ok, conn} = SSHEx.connect ip: '123.123.123.123', user: 'myuser'\n```\n2.You can supply the password:\n```elixir\n{:ok, conn} = SSHEx.connect ip: '123.123.123.123', user: 'myuser', password: 'your-password'\n```\n\nThen you can use the acquired `conn` with the `cmd!/4` helper like this:\n\n```elixir\nSSHEx.cmd! conn, 'mkdir -p /path/to/newdir'\nres = SSHEx.cmd! conn, 'ls /some/path'\n```\n\nThis is meant to run commands which you don't care about the return code. `cmd!/3` will return the output of the command only, and __will raise any errors__. If you want to check the status code, and control errors too, you can use `run/3` like this:\n\n```elixir\n{:ok, _, 0} = SSHEx.run conn, 'rm -fr /something/to/delete'\n{:ok, res, 0} = SSHEx.run conn, 'ls /some/path'\n{:error, reason} = SSHEx.run failing_conn, 'ls /some/path'\n```\n\nYou can pass the option `:separate_streams` to get separated stdout and stderr. Like this:\n\n```elixir\n{:ok, stdout, stderr, 2} = SSHEx.run conn, 'ls /nonexisting/path', separate_streams: true\n```\n\nYou will be reusing the same SSH connection all over.\n\n\n## Streaming\n\nYou can use `SSHEx` to run some command and create a [`Stream`](http://elixir-lang.org/docs/stable/elixir/Stream.html), so you can lazily process an arbitrarily long output as it arrives. Internally `Stream.resource/3` is used to create the `Stream`, and every response from `:ssh` is emitted so it can be easily matched with a simple `case`.\n\nYou just have to use `stream/3` like this:\n\n```elixir\nstr = SSHEx.stream conn, 'somecommand'\n\nEnum.each(str, fn(x)-\u003e\n  case x do\n    {:stdout, row}    -\u003e process_stdout(row)\n    {:stderr, row}    -\u003e process_stderr(row)\n    {:status, status} -\u003e process_exit_status(status)\n    {:error, reason}  -\u003e process_error(reason)\n  end\nend)\n```\n\n## Alternative keys\n\nTo use alternative keys you should save them somewhere on disk and then set the `:user_dir` option for `SSHEx.connect/4`. See [ssh library docs](http://www.erlang.org/doc/man/ssh.html) for more options.\n\n\n## TODOs\n\n* Add tunnelling helpers [*](http://erlang.org/pipermail/erlang-questions/2014-June/079481.html)\n\n## Changelog\n\n### 2.2.1\n\n* Add new possible exit_signal message format\n\n### 2.2.0\n\n* Add ability to specify ssh key and known hosts\n* Make it Elixir string friendly\n\n### 2.1.2\n\n* Remove Elixir 1.4 warnings\n\n### 2.1.1\n\n* Close channel after stream\n\n### 2.1.0\n\n* Add `connect/1` to improve testability by easier mocking\n\n### 2.0.1\n\n* Avoid some Elixir 1.2.0 warnings\n* Adjust the SSH flow control window to handle long outputs (fixes #4).\n\n### 2.0.0\n\nBackwards incompatible changes:\n* Remove every `raise`, get clean controlled `{:error, reason}` responses\n* Put every optional parameter under a unique Keyword list\n\n### 1.3.1\n\n* Fix Elixir version requested. Use \u003e= 1.0 now.\n\n### 1.3\n\n* Support streaming via `stream/3`\n* Stop using global mocks (i.e. `:meck`)\n\n### 1.2\n\n* Uniform `raise` behaviour on `:ssh` errors.\n* Document and test `:ssh` error handling\n\n### 1.1\n\n* Add support for separate stdout/stderr responses.\n\n### 1.0\n\n* Initial release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubencaro%2Fsshex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frubencaro%2Fsshex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubencaro%2Fsshex/lists"}