{"id":20331153,"url":"https://github.com/comcast/ssh-to","last_synced_at":"2025-09-15T03:43:58.462Z","repository":{"id":138469639,"uuid":"71506944","full_name":"Comcast/ssh-to","owner":"Comcast","description":"Easily manage dozens or hundreds of machines via SSH","archived":false,"fork":false,"pushed_at":"2020-09-01T19:11:10.000Z","size":28,"stargazers_count":58,"open_issues_count":0,"forks_count":10,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-11T21:07:30.827Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Comcast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2016-10-20T21:46:19.000Z","updated_at":"2024-05-26T23:56:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"14dbea39-73a3-4851-8c6e-d98b817504a1","html_url":"https://github.com/Comcast/ssh-to","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Comcast/ssh-to","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fssh-to","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fssh-to/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fssh-to/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fssh-to/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Comcast","download_url":"https://codeload.github.com/Comcast/ssh-to/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Comcast%2Fssh-to/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275202199,"owners_count":25423008,"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-09-15T02:00:09.272Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","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":[],"created_at":"2024-11-14T20:18:59.899Z","updated_at":"2025-09-15T03:43:58.428Z","avatar_url":"https://github.com/Comcast.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ssh-to\n\nHey software engineers! Do you manage servers?  Lots of servers?  Hate copying and pasting IP addresses?  Need a way to execute a command on each of a group of servers that you manage?\n\n\n## Installation\n\n```\nbrew tap comcast/opensource https://github.com/Comcast/homebrew-opensource.git\nbrew install ssh-to\n```\n\n\n## TL;DR\n\nTurn this:\n```\n$ ssh hadop02.sys.comcast.net ^C\n# Oops, I made a typo!\n```\n\nInto this:\n```\n$ ssh-to hadoop 2\n# \n# SSHing to 10.100.200.2 (hadoop02.sys.comcast.net)...\n# \nLast login: Wed Mar  9 17:00:23 2016 from 10.36.122.137\n[dmuth200@hadoop02.sys.comcast.net ~]$ \n```\n\nOr turn this:\n\n```\n$ for I in $(seq -w 1 20) do; ssh hadoop{$I}.sys.comcast.net \"COMMAND\"; done\n# Reasonable, but requires a lot of typing and manual commands\n```\n\nInto this:\n\n```\n$ ssh-to hadoop --loop \"COMMAND\"\n# \n# Looping over group 'hadoop'...\n# \n# \n# SSHing to hadoop01.sys.comcast.net...\n# \n\n# All hosts in this group will be SSHed to and have the above command executed.\n```\n\n\n## Requirements\n\nYou must have \u003ca href=\"https://stedolan.github.io/jq/\"\u003ejq\u003c/a\u003e installed on your system so that\nthe list of servers can be parsed.  If jq is not found, ssh-to will complain and exit.\n\n\n## Getting Started\n\nIn order to use this script, you'll need to create a servers.json file:\n\n`./ssh-to --create`\n\nThis will create a sample `servers.json` in the current directory.  You *may* want to then move that\nfile to `$HOME/.ssh-to-servers.json` so that ssh-to can be run from any directory in the filesystem.\n\nNext, to add hosts and hostgroups to the servers.json file:\n\n`./ssh-to --edit`\n\nThis will bring up $EDITOR to edit the file.  After you are done editing, exit the editor, and the \nvalidity of the JSON will be checked.  If the JSON fails to validate, you'll be prompted to hit\nENTER to go back into the editor or ctrl-C to abort.\n\nAn exmample `servers.json` file \u003ca href=\"servers.json.example\"\u003ecan be found here\u003c/a\u003e.\n\n\n## Usage\n\nSyntax: `ssh-to [ --dump | --loop ] group [ host_number ] [ ssh_args ]`\n\n- If no group if specified, all groups will be printed.\n- `--dump` Dump the IP address of the target host. Useful in automation.\n- `--loop` Loop through the target group and execute the same command on each host.\n\n\nExample: \n```\n$ ssh-to\n# \n# Please re-run me with a group name to see a list of servers in that group.\n# \n# Available group names:\n# \n#       hadoop\n#       kafka\n#       splunk\n#       zookeeper\n# \n# \n# Exmample: ssh-to group_name\n# \n```\n\n\nIf no index is specified, all servers in that group will be displayed and \nthe user will be prompted to pick one in the next invocation.\n\nExample:\n```\n$ ssh-to hadoop\n# \n# Please re-run me with an index number of which server to SSH into.\n# \n# Available hosts in group 'hadoop': \n# \n# 1)     10.100.200.1  hadoop01.sys.comcast.net\n# 2)     10.100.200.2  hadoop02.sys.comcast.net\n# 3)     10.100.200.3  hadoop03.sys.comcast.net\n# 4)     10.100.200.4  hadoop04.sys.comcast.net\n# \n# Example: /Users/dmuth200/bin/ssh-to hadoop 1\n# \n```\n\nIf a group name and index are specified, SSH will be launched:\n```\n$ ssh-to hadoop 2\n# \n# SSHing to 10.100.200.2 (hadoop01.sys.comcast.net)...\n# \nLast login: Wed Mar  9 17:00:23 2016 from 10.36.122.137\n[dmuth200@hadoop01.sys.comcast.net ~]$ \n```\n\nThat was easy! :-)\n\n\n## Usage in Automated Environments\n\nWant to use this script in an automated environment?  No problem, just use the optional `--dump` parameter:\n\n```\n$ ssh-to hadoop 1 --dump\n10.100.200.1\n```\n\nThis can be used within other commands like so:\n- `ssh otherusername@$(ssh-to hadoop 1 --dump)`\n- `scp file $(ssh-to hadoop 1 --dump):.`\n- etc.\n\nIt can also be used in shell scripting as in the following example\n```\nfor HOST in $(ssh-to --dump hadoop)\ndo\n   scp file.txt ${HOST}:/path/to/destination/\ndone\n```\n\n### Passing Options to SSH\n\nIf your SSH key isn't on the remote server, you're using prompted for a password.\nThis can be a problem in automated environments.  Instead, try using the $SSH_OPTS \nenvironment variable. That will let you pass options into the SSH command line.\n\nExample:\n\n`SSH_OPTS=-oBatchMode=yes ssh-to hadoop --loop hostname`\n\nThis will print hostnames of hosts in the `hadoop` group that you can SSH into.\n\n\n## Tmux Support\n\nYes, we have Tmux support. (how cool is that!?)\n\nWhen a SSH connection is launched, the current window you are in will be renamed to the human-readable\nname of the target host.  When you disconnect, the name will change back to what it was before.\n\nThis is useful to help you keep track of when SSH sessions get disconnected.\n\n\n## Looping Through Many Hosts\n\nNow let's say you have dozens (or even hundreds) of hosts, and you want to execute a command on all of them.\nThis can be done with the `--loop` parameter:\n\n```\nssh-to hadoop --loop \"hostname\"\n# \n# Looping over group 'hadoop'...\n# \n# \n# SSHing to hadoop01.sys.comcast.net...\n# \n# Executing command: hostname\n# \nhadoop01.sys.comcast.net\n# \n# SSHing to hadoop02.sys.comcast.net...\n# \n# Executing command: hostname\n# \nhadoop02.sys.comcast.net\n# \n# SSHing to hadoop03.sys.comcast.net...\n# \n# Executing command: hostname\n# \nhadoop03.sys.comcast.net\n# \n# SSHing to hadoop04.sys.comcast.net...\n# \n# Executing command: hostname\n# \nhadoop04.sys.comcast.net\n```\n\nExecution happens serially.\n\nThe `--loop` mode is quite useful for things like maintenance or upgrades.\n\nNaturally, you can chain multiple commands with `--loop`, do inline shell script, etc.  For example:\n\n`ssh-to hadoop --loop \"puppet agent --test; service nginx start; nc -vz localhost 80\"`\n\n\nOr lets say you want to do rolling upgrades of your Splunk platform:\n\n`ssh-to splunk --loop \"yum install -y splunk; /opt/splunk/bin/splunk stop; /opt/splunk/bin/splunk start --answer-yes --no-prompt\"`\n\nThat's literally all there is to it!  And I've literally (not figuratively) done this in production.\n\n\n## Development\n\nI have a rudimentary unit test at `./ssh-to-test` which should be run before any commits are made.\n\nFuture list of things for testing:\n- A better script\n- A `Dockerfile`\n- A script to drive building said Docker container and the unit test\n\n\n## Author\n\u003ca name=\"author\"\u003e\u003c/a\u003e\n\nDouglas Muth \u003cdouglas_muth@cable.comcast.com\u003e\n\nBugs can be filed here or emailed directly to me.\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomcast%2Fssh-to","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomcast%2Fssh-to","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomcast%2Fssh-to/lists"}