{"id":29693783,"url":"https://github.com/dennyzhang/remote-commands-servers","last_synced_at":"2025-07-23T08:05:45.861Z","repository":{"id":67456276,"uuid":"102540470","full_name":"dennyzhang/remote-commands-servers","owner":"dennyzhang","description":":family: Run remote ssh commands on multiple servers","archived":false,"fork":false,"pushed_at":"2018-07-11T22:45:44.000Z","size":32,"stargazers_count":9,"open_issues_count":0,"forks_count":14,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-05T21:06:06.094Z","etag":null,"topics":["devops","python","ssh"],"latest_commit_sha":null,"homepage":"https://www.dennyzhang.com/jenkins_run_ssh","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dennyzhang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-05T23:43:19.000Z","updated_at":"2025-02-27T07:38:52.000Z","dependencies_parsed_at":"2023-06-11T02:47:22.956Z","dependency_job_id":null,"html_url":"https://github.com/dennyzhang/remote-commands-servers","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dennyzhang/remote-commands-servers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennyzhang%2Fremote-commands-servers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennyzhang%2Fremote-commands-servers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennyzhang%2Fremote-commands-servers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennyzhang%2Fremote-commands-servers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dennyzhang","download_url":"https://codeload.github.com/dennyzhang/remote-commands-servers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dennyzhang%2Fremote-commands-servers/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266640829,"owners_count":23960809,"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","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["devops","python","ssh"],"created_at":"2025-07-23T08:04:37.029Z","updated_at":"2025-07-23T08:05:45.844Z","avatar_url":"https://github.com/dennyzhang.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://github.com/DennyZhang?tab=followers\"\u003e\u003cimg align=\"right\" width=\"200\" height=\"183\" src=\"https://raw.githubusercontent.com/USDevOps/mywechat-slack-group/master/images/fork_github.png\" /\u003e\u003c/a\u003e\n\n[![Build Status](https://travis-ci.org/dennyzhang/remote-commands-servers.svg?branch=master)](https://travis-ci.org/dennyzhang/remote-commands-servers) [![LinkedIn](https://raw.githubusercontent.com/USDevOps/mywechat-slack-group/master/images/linkedin.png)](https://www.linkedin.com/in/dennyzhang001) [![Github](https://raw.githubusercontent.com/USDevOps/mywechat-slack-group/master/images/github.png)](https://github.com/DennyZhang) [![Twitter](https://raw.githubusercontent.com/USDevOps/mywechat-slack-group/master/images/twitter.png)](https://twitter.com/dennyzhang001) [![Slack](https://raw.githubusercontent.com/USDevOps/mywechat-slack-group/master/images/slack.png)](https://mywechat.slack.com/join/shared_invite/enQtMjQ0Mjg4ODk2Mjc2LTk1MTQyNTE2ZjEyNGZjZDkyOTY5ODEzMDY5ZGJkODY1OTNlYTllZTFjMGY2YzhjYjM0M2FiM2Y0OGQ5NGI3Y2U)\n\n- File me [tickets](https://github.com/DennyZhang/remote-commands-servers/issues) or star [the repo](https://github.com/DennyZhang/remote-commands-servers)\n\n# remote-commands-servers\nRun remote ssh commands on multiple servers\n\nYou can:\n1. Choose whether to run sequentially or in parallel. By default, it's sequential.\n2. When sequentially, it will abort immediately if any node has failed. Customize by **--avoid_abort**.\n\nAssumptions:\n- All ssh servers accept the same username\n- All ssh servers accept the same ssh private key\n\n# remote-commands-servers usage\n```\nDenny: mac$ python ./remote-commands-servers.py --help\nusage: remote-commands-servers.py [-h] --server_list SERVER_LIST [--command_list COMMAND_LIST] [--command_file COMMAND_FILE]\n                                  [--ssh_username SSH_USERNAME] --ssh_key_file SSH_KEY_FILE [--key_passphrase KEY_PASSPHRASE]\n                                  [--enable_parallel] [--avoid_abort]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --server_list SERVER_LIST\n                        A list of ip-port. Separated by comma\n  --command_list COMMAND_LIST\n                        A list of commands to run\n  --command_file COMMAND_FILE\n                        File to host bash command. If --command_list no given, use this one\n  --ssh_username SSH_USERNAME\n                        SSH username\n  --ssh_key_file SSH_KEY_FILE\n                        SSH private key file. Here we assume the same key file works for all servers\n  --key_passphrase KEY_PASSPHRASE\n                        Key passphrase for SSH private key file. If not given, key file is in plain text\n  --enable_parallel     By default, it's sequential. If enabled, we will run commands in all nodes simultaneously\n  --avoid_abort         When sequentially, whether to keep going if some nodes have failed\n```\n\n# Different Scenarios\n- Paralell\n```\npython ./remote-commands-servers.py \\\n    --server_list \"45.33.88.175:2702, www.dennyzhang.com:23, test.dennyzhang.com:2703\" \\\n    --command_list \"date \u0026\u0026 hostname\" --ssh_username \"root\" \\\n    --enable_parallel \\\n    --ssh_key_file \"/Users/mac/.ssh/id_rsa\" --key_passphrase \"mykeypass\"\n```\n\n- Sequential\n```\npython ./remote-commands-servers.py \\\n    --server_list \"45.33.88.175:2702, www.dennyzhang.com:23, test.dennyzhang.com:2703\" \\\n    --command_list \"date \u0026\u0026 hostname\" --ssh_username \"root\" \\\n    --ssh_key_file \"/Users/mac/.ssh/id_rsa\" --key_passphrase \"mykeypass\"\n```\n\n- Sequential, abort if any errors\n```\npython ./remote-commands-servers.py \\\n    --server_list \"45.33.88.175:2702, www.dennyzhang.com:23, test.dennyzhang.com:2703\" \\\n    --command_list \"date; false \u0026\u0026 hostname\" --ssh_username \"root\" \\\n    --ssh_key_file \"/Users/mac/.ssh/id_rsa\" --key_passphrase \"mykeypass\"\n```\n\n- Sequential, avoid fast fail\n```\npython ./remote-commands-servers.py \\\n    --server_list \"45.33.88.175:2702, www.dennyzhang.com:23, test.dennyzhang.com:2703\" \\\n    --command_list \"date; false \u0026\u0026 hostname\" --ssh_username \"root\" \\\n    --avoid_abort \\\n    --ssh_key_file \"/Users/mac/.ssh/id_rsa\" --key_passphrase \"mykeypass\"\n```\nCode is licensed under [MIT License](https://www.dennyzhang.com/wp-content/mit_license.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdennyzhang%2Fremote-commands-servers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdennyzhang%2Fremote-commands-servers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdennyzhang%2Fremote-commands-servers/lists"}