{"id":16582809,"url":"https://github.com/ojroques/python-sshcontroller","last_synced_at":"2025-10-29T07:31:55.644Z","repository":{"id":57470823,"uuid":"313736162","full_name":"ojroques/python-sshcontroller","owner":"ojroques","description":"A Python package to easily run SSH commands","archived":false,"fork":false,"pushed_at":"2023-12-27T09:47:12.000Z","size":25,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-03T20:07:13.390Z","etag":null,"topics":["paramiko","python-package","python-ssh","ssh"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/sshcontroller/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ojroques.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,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-11-17T20:33:26.000Z","updated_at":"2024-05-20T21:31:12.000Z","dependencies_parsed_at":"2024-01-17T01:35:47.952Z","dependency_job_id":"c8d5a48d-e9a5-4654-9e13-689cfd9b73ea","html_url":"https://github.com/ojroques/python-sshcontroller","commit_stats":{"total_commits":14,"total_committers":3,"mean_commits":4.666666666666667,"dds":0.2857142857142857,"last_synced_commit":"0325ec3747b4bb65f588e3f5852ec96a0314c0cc"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojroques%2Fpython-sshcontroller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojroques%2Fpython-sshcontroller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojroques%2Fpython-sshcontroller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ojroques%2Fpython-sshcontroller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ojroques","download_url":"https://codeload.github.com/ojroques/python-sshcontroller/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219858147,"owners_count":16556048,"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":["paramiko","python-package","python-ssh","ssh"],"created_at":"2024-10-11T22:34:15.938Z","updated_at":"2025-10-29T07:31:49.503Z","avatar_url":"https://github.com/ojroques.png","language":"Python","readme":"# python-sshcontroller\n\nThis small package implements a simple interface to communicate and exchange\ndata with remote hosts via SSH. It is essentially a wrapper around the\nextensive SSH library [paramiko](https://github.com/paramiko/paramiko/).\n\n## Installation\nRun:\n```\npip3 install --user sshcontroller\n```\n\nNote that the package has been exclusively tested on Python 3.6+.\n\n## Usage\n\nAll code snippets can also be found at\n[demo.py](https://github.com/ojroques/python-sshcontroller/blob/main/examples/demo.py).\n\n#### 1. Create a new SSH controller from a SSH key\n```python\nimport sshcontroller\n\nHOST_IP = \"93.184.216.34\"  # an IPv4 or IPv6 address\nKEY_PWD = \"password\"\n\nssh_controller = sshcontroller.SSHController(\n    host=HOST_IP,\n    user=\"olivier\",\n    key_path=\"~/.ssh/id_rsa\",  # if omitted, look for keys in SSH agent and in ~/.ssh/\n    key_password=KEY_PWD,      # optional\n    key_type=\"rsa\",            # rsa (default), dsa, ecdsa or ed25519\n    port=22,                   # 22 is the default\n)\n```\n\n#### 2. Connect to remote host\n```python\nssh_controller.connect()\n```\n\n#### 3. Run a command\n```python\nexit_code, output = ssh_controller.run(\n    command=\"echo 'Hello world!' \u003e /tmp/hello.txt\",\n    display=True,          # display output, disabled by default\n    capture=True,          # save output, disabled by default\n    shell=True,            # request a shell to run the command, enabled by default\n    combine_stderr=False,  # combine stderr into stdout when shell=False, disabled by default\n    timeout=10,            # command timeout in seconds, None (wait indefinitely) by default\n)\nprint(f\"exit code: {exit_code}, output: {output}\")\n```\n\n#### 4. Transfer data with SFTP\nAll functions from paramiko's `SFTPClient` are available through the\n`SSHController` object. Check\n[paramiko's documentation](http://docs.paramiko.org/en/stable/api/sftp.html#paramiko.sftp_client.SFTPClient)\nfor a complete list.\n\nIn addition, the package implements additional methods:\n* `exists(path)`: check that a file or a directory exists on the remote host\n* `list_dirs(path)`: return the list of directories present in `path`\n* `list_files(path)`: return the list of files present in `path`\n\n```python\nprint(f\"hello.txt exists: {ssh_controller.exists('/tmp/hello.txt')}\")\nprint(f\"bonjour.txt exists: {ssh_controller.exists('/tmp/bonjour.txt')}\")\n\nssh_controller.get(\"/tmp/hello.txt\", \"/tmp/bonjour.txt\")\n\nwith open(\"/tmp/bonjour.txt\", 'r') as bonjour:\n    for line in bonjour:\n        print(line, end='')\n```\n\n#### 5. Disconnect\n```python\nssh_controller.disconnect()\n```\n\n#### 6. Use a SSH password instead of a key\n```python\nimport sshcontroller\n\nHOST_IP = \"93.184.216.34\"  # an IPv4 or IPv6 address\nSSH_PWD = \"password\"\n\nssh_controller = sshcontroller.SSHController(\n    host=HOST_IP,\n    user=\"olivier\",\n    ssh_password=SSH_PWD\n)\nssh_controller.connect()\n```\n\n#### 7. Run a command until an event is set\nIf the argument `stop_event` (a `threading.Event` object) is set when\ncalling `run()`, the controller ignores `timeout` and stops when the given\nevent is triggered instead. This is especially useful when using threads.\n\nThe example below starts two threads with an event attached to each one:\none is pinging `localhost`, the other sleeps for 10s. When the sleeping thread\nhas finished, events are triggered to also stop the pinging thread.\n\n```python\nimport logging\nimport queue\nimport sshcontroller\nimport threading\nimport time\n\n# ... set up ssh_controller here ...\n\noutput = queue.Queue()  # a queue to store the ping command output\nstop_event_sleep = threading.Event()\nstop_event_ping = threading.Event()\n\nkwargs_sleep = {\n    \"command\": \"echo 'thread sleep: sleeping for 10s' \u0026\u0026 sleep 10s\",\n    \"display\": True,\n    \"stop_event\": stop_event_sleep,\n}\nkwargs_ping = {\n    \"command\": \"echo 'thread ping: starting ping' \u0026\u0026 ping localhost\",\n    \"display\": True,\n    \"capture\": True,\n    \"stop_event\": stop_event_ping,\n}\n\n# call run() and store the command output in the queue\ndef wrapper(kwargs):\n    return output.put(ssh_controller.run(**kwargs))\n\nthread_sleep = threading.Thread(\n    target=ssh_controller.run, name=\"thread_sleep\", kwargs=kwargs_sleep)\nthread_ping = threading.Thread(\n    target=wrapper, name=\"thread_ping\", args=(kwargs_ping, ))\n\nthread_ping.start()\nthread_sleep.start()\n\ntry:\n    thread_sleep.join()\nexcept KeyboardInterrupt:\n    logging.info(\"KeyboardInterrupt\")\nfinally:\n    logging.info(\"Stopping threads\")\n    stop_event_sleep.set()\n    stop_event_ping.set()\n    time.sleep(2)\n\nexit_code, ping_output = output.get()\nlogging.info(f\"thread ping exit code: {exit_code}\")\nlogging.info(f\"thread ping output length: {len(ping_output)}\")\n\nssh_controller.disconnect()\n```\n\n## License\n[GNU Lesser General Public License v2.1](https://github.com/ojroques/python-sshcontroller/blob/main/LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fojroques%2Fpython-sshcontroller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fojroques%2Fpython-sshcontroller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fojroques%2Fpython-sshcontroller/lists"}