7 ms·
Show HN: Sshsync – CLI tool to run shell commands across multiple remote servers
I built a CLI tool called `sshsync` to run shell commands and transfer files across multiple servers over SSH concurrently.
It was inspired by tools like `pssh`, but I wanted something more modern, intuitive, and Pythonic.
What it does:
- Run shell commands on multiple servers (in parallel)
- Push/pull files or directories with progress bars
- Uses `~/.ssh/config` and lets you group hosts with YAML
- Supports `--dry-run` mode to preview actions without executing
- Outputs results using `rich` (tables, colors)
- Built with `Typer`, `asyncssh`, and `rich`
There’s no daemon or extra setup, it reads your existing SSH config and just runs.
Would love feedback on general use and especially if there are ways to improve the `--dry-run` output.
- andrewchilds 1y agoI built (and still use) a similar tool called Overcast 10 years ago: https://github.com/andrewchilds/overcast https://github.com/andrewchilds/overcast
- blackmamoth 1y agoDude, your tool does so much than just run ssh commands. I just took a quick glance at your project, just wanted to know does this have support for vultr?
- andrewchilds 1y agoIt does not support Vultr currently, but it likely wouldn't be difficult to add. There's an open issue for it: https://github.com/andrewchilds/overcast/issues/58 https://github.com/andrewchilds/overcast/issues/58
- andrewchilds 1y agoPR to add Vultr support: https://github.com/andrewchilds/overcast/pull/61 https://github.com/andrewchilds/overcast/pull/61
- baalimago 1y agoVery cool project! But it's a quite saturated market. Any sysadmin/similar who needs this sort of functionality have most likely already found an solution (5-20 years ago). Personally, I'm a tmux synchronized-panes kind of guy, so that I can see the result of each output immediately.
- jasongill 1y agoIn a past life, this is an interview question that I would ask people: "We have thousands of servers, and you need to run the same command on 10 of them, what's one way you would do it?" and follow up with "What if you wanted to run the command on hundreds or thousands - what problems would you expect with this approach, and what might you do differently?" I didn't really expect them to write code on the spot (hate that in interviews), but just to describe a possible solution; there were no wrong answers. Seeing how people came up with a quick hack for 10 and then being able to evolve their thinking for thousands was the point of the question and it could be enlightening to see. I had a lot of people come up with things that I never even thought of, such as SSH'ing in to all 10 machines and then using a terminal feature to type into all of the windows at once.
- Alifatisk 1y agoIs there a standard way of doing this that comes shipped with GNU/Linux?
- olddustytrail 1y agoI'd just use Ansible for that.
- Alifatisk 1y agoJust found out about pssh through the comments
- yjftsjthsd-h 1y agoI dunno about standard, but it's been done a bunch. * As sibling notes, there's ansible (or chef/puppet/salt/...) * The traditional solution was https://github.com/duncs/clusterssh https://github.com/duncs/clusterssh which opens an xterm to each target plus a window that you type into to mirror input to all of them * I do the same-ish in tmux with bind-key a set-window-option synchronize-panes and I expect screen and such have equivalent features * Likewise, there are terminal emulators that let you do splits and then select a menu option to mirror input to all of them
- bandie91 1y agohttp://guichaz.free.fr/polysh/ http://guichaz.free.fr/polysh/
- Alifatisk 1y agoIf I connect thousands of machines, will my terminal be flooded? Or have they thought of this?
- johng 1y agoI used to love using csshx on Mac but it appears to be broken on Homebrew now and not really updated on other sources. Pity, I reallyliked it.
- flysand7 1y agoI'm curious what happens with output. Is it one line per each computer you've connected to or does it get merged until it diverges, kinda like in that Rick and Morty episode with timeline splits?
- blackmamoth 1y agoHaven't set a limit to how many connections are shown, once all the commands are executing, each result (success/failure) is shown at once. So if you connect to 1000 computers, your shell will be flooded with progress bars first and then the output. Maybe I should set a limit or let the user set a limit to how many results should be shown once the process is completed. Showing m and n results from the start and end
- jasonm23 1y ago`pssh`
- igetspam 1y agoI’m surprised no one has mentioned pdsh yet. Piped to dshbak and output was grouped by response. I’d probably use a config management tool for anything more than simple commands now but that tool was indispensable for managing our fleet, when we used to actually connect to machines.
- lcall 1y agoDitto. I posted (here: https://news.ycombinator.com/item?id=42881123 https://news.ycombinator.com/item?id=42881123 ) about them and other options: To send the same command to multiple servers, use pdsh: https://linux.die.net/man/1/pdsh https://linux.die.net/man/1/pdsh To collect all the results and show which ones are the same or different, use dshbak (i.e., "pdsh <parameters including servers>|dshbak"): https://linux.die.net/man/1/dshbak https://linux.die.net/man/1/dshbak Similar things, sometimes more convenient but less efficient for a large number of servers, are to use the konsole terminal program and link multiple window tabs together so the same typed command goes to all, and quickly view the results across the tabs; or to use tmux and send the same commands to multiple windows (possible useful "man tmux" page terms: link-window, pipe-pane, related things to those, activity, focus, hooks, control mode). And others that I haven't used but which also look possibly interesting for platforms where pdsh and dshbak might not be available (like OpenBSD at least): - https://github.com/duncs/clusterssh/wiki https://github.com/duncs/clusterssh/wiki (available on OpenBSD as a package) - https://www.gnu.org/software/parallel/ https://www.gnu.org/software/parallel/ (also available as a package on OpenBSD 7.6: named "parallel-20221122"; might relate to "pdksh") - Also clusterit.
- strzibny 1y agoIf you deploy with Kamal you practically get this, except maybe the file push, that's a nice touch.
- ahofmann 1y agoThis looks great. I've used ansible in the past, is this tool like a stripped down (and thus simpler to use) version of ansible?
- blackmamoth 1y agoTo be completely honest, I didn't even think about ansible when creating this (probability because I haven't yet used it), I looked at pssh and clusterssh and just decided to build one myself.
- XorNot 1y agoGiven that ansible can be installed via "pip install ansible" I'm not sure how much simpler you can get? Like a basic list of servers can also have this done via "ansible -m shell -a 'echo something' <server group>"
- N2yhWNXQN3k9 1y agoyeah, ansible is very nice also in that it can have multiple inventories across cloud providers for running whatever, with minimal setup, and without needing to modify your ssh host config
- gitroom 1y ago[dead]
- mkayokay 1y agoHow are commands handled, that require user input? E.g. password for sudo in your example: sshsync group web-servers "sudo systemctl restart nginx" I like that you included a demo in the README, but it is too long for a gif, as I can't pause/rewind/forward. So splitting into multiple short gifs or converting into a video (if GitHub supports them) could improve the experience.
- blackmamoth 1y agoAs of now there is no way to take user input in transit, so either the user is required to have the privilege to execute the specified command or have passwordless sudo available. And Yeah, now that you've mentioned it multiple shorter gifs would be better.
- mrbluecoat 1y agoOr https://asciinema.org/ https://asciinema.org/ instead of gifs
- blackmamoth 1y agoI did use asciinema for creating the demo, but since there is no support for it to play in markdown, I went ahead and created a gif using agg.
- nasretdinov 1y agoAround 10 years ago I was supporting infrastructure at a PHP shop and we needed a similar thing, but for ~3000 servers, and the library that we were using (libpssh) didn't support async SSH agent authentication, so I built this small tool in Go to allow to implement such tooling in any language (PHP, Python, whatever) in a simple way: https://github.com/YuriyNasretdinov/GoSSHa https://github.com/YuriyNasretdinov/GoSSHa It's main advantage is that it allows you to do SSH agent forwarding that actually works at scale, since it limits concurrency when talking to SSH agent to a configurable amount (by default 128, the default connection backlog in OpenSSH ssh-agent)
- blackmamoth 1y agoHey man that's really cool, I never really thought of making this interactive.
- gamedna 1y agoCurious to understand the need to create this over using tools like pssh, etc. https://linux.die.net/man/1/pssh https://linux.die.net/man/1/pssh
- deleted 1y ago[deleted]
- blackmamoth 1y agoI was getting bored, this seemed like a cool project to work on outside of work, that's why. One of my colleagues found it useful for his needs, so I figured there might be other people who'd find this useful too.
- deva502 1y agoThe lack of research, the AI-generated README and comments, and the "Pythonic" approach (while Ansible exists) made me laugh. I guess it's a good CS50 project, but it's not presentable at all and doesn't have real-world usage.
- blackmamoth 1y agoHey, yeah I admit i should've written the README myself, but I'm kinda lazy , so I let gpt handle both readme and the post. And I do know there are other tools way better than this and battle tested, but I just built this for fun and not to compete with any of them.
- monster_truck 1y agoHave you looked at what powershell does? Invoke-Command (and the Job stuff it meshes perfectly with via AsJob) is really nice I only needed a very small fraction of what it can do to bail a client out of a problem their customer caused on several hundred computers the night before an event, but it absolutely saved the day and a lot of money.
- blackmamoth 1y agoHaven't really used powershell for my tasks and I'm not as experienced as you are, but what you said sounds absolutely cool, I'll check it out
- N2yhWNXQN3k9 1y agoThe dry-run option is nice, but you can do this easily in a normal environment without special tooling (GNU parallel, etc). I have made scripts to do this with filter parameters over VMs on cloud providers, which is very valuable. Maybe you can extend this to have those options, so potential users are more attracted to it?
- blackmamoth 1y agoHey, I missed your comment earlier. And yes, I'd love to hear about those parameters and how they'd be useful
- proxysna 1y agoansible my_servers -m shell -a 'fortune && reboot' -b I know it is easy to be a hater, but sincerely do not see a reason to use something like that over Ansible or just pure sh, ssh and scp. All you have to do is to set up keys and the inventory. Takes 10 minutes, even if you are doing it for the first time. And you can expand it if you need it.
- liamkearney 1y agoAnsible is one of the best examples of needless complexity I’ve ever interacted with.
- proxysna 1y agoAnsible is the easiest tool for configuration management to onboard and start using. Great documentation, large community. It is as complex as you want it to be and it's complexity scales with your infra. ofc YMMV.
- pod_krad 1y agoI disagree. It requires to know Python, YAML, Jinja2, own set of commands. It requires careful developing of playbooks. It is slow. It is complicated for non-standard cases where you don't have ready for using modules. Is there a better approach? I think yes. This is Pyinfra - just pure Python, no additional DSLs. Also for configuration there is Terraform (but there are also some limitations).
- alerighi 1y agoI use pssh often (not this tool, but as I understand is similar). The reasons I find it over Ansible are: - takes the same syntax and options as plain SSH, just run over multiple hosts. So if you already know SSH, you know how to use pssh that is an extension of the command. Ansible requires to study it. The configuration format is trivial, just a file that contains on each line one host, no need to study complex formats like Ansible - doesn't require dependencies on the target machine. Ansible, as far as I know, requires a python3 installation on the target machine. Something that, for example, is not granted in all settings (e.g. embedded devices, that are not strictly GNU/Linux machines, for example consider a lot of network devices that espose an SSH server, like Microtik devices, with PSSH is possible to configure them in batch), or in some settings you maybe need to work on legacy machines that have an outdated python version. - sometimes simpler tool that just do one thing are just better. Especially for tools like pssh that are to me like a swiss army knife, the kind of tool that you use obviously when you are bodging something up to make something work because you are in an hurry and saves your day Of course if you already use Ansible to manage your infrastructure you may as well use it to run a simple command. But if you have to run a command on some devices, that were not previously setup for Ansible, and devices trough which you may not have a lot of control (e.g. a bunch of embedded devices of some sort), pssh is a tool that can come handy.
- darrenf 1y agoSee also: fabric. https://docs.fabfile.org/en/latest/ https://docs.fabfile.org/en/latest/
- shaunpud 1y agoSee also: pyinfra. https://docs.pyinfra.com/en/latest/ https://docs.pyinfra.com/en/latest/
- kachapopopow 1y agoThis would only be interesting if it wasn't written in python, but native instead.
- blackmamoth 1y agoOriginally I was going to write the prototype in python and than later reimplement it in Golang, but right now I'm not sure if it's needed
- Joker_vD 1y agoLooks interesting; my klunky script for doing something similar has been something along the lines of printf 'started: %s\n' "$(utcdate)" ( trap 'kill 0' SIGINT for REMOTE in "${REMOTES[@]}" do ssh -- "$REMOTE" "$COMMAND" "$@" & done wait ) printf 'ended: %s\n' "$(utcdate)" but twiddling with it has been quite annoying, so I'll look into this tool.
- JulianWasTaken 1y agoTo me GNU parallel is the top of the line here (as it is for most things parallel). For the most common cases I have it aliased to just `p`: https://github.com/Julian/dotfiles/blob/main/.config/zsh/commands.zsh#L24 https://github.com/Julian/dotfiles/blob/main/.config/zsh/com... Or https://github.com/Julian/dotfiles/blob/4d36e6b17e9804a887bade1cab34923df9046032/.config/zsh/functions/ssp#L2 https://github.com/Julian/dotfiles/blob/4d36e6b17e9804a887ba...
- cbm-vic-20 1y ago[flagged]
- naikrovek 1y agowhat is the use case? why wouldn't you use something else (like ansible or puppet or something)? I do not understand why someone would do things like this.
- deleted 1y ago[deleted]
- johnisgood 1y agoWhy would anyone use Ansible or Puppet for running shell commands on remote servers? Such an overkill.
- naikrovek 1y agowell usually it's already in place, right? maybe at home it wouldn't be, but at work, that stuff would already be in place on the stock OS install. and I would be afraid to run SSH commands on multiple machines at once in case one of them errored out and needed manual intervention. ansible or puppet would let me know about that stuff.
- johnisgood 1y agoIf it is already in place, then sure, why not. Not using what is already there would just be a waste, IMO.