{"id":18631249,"url":"https://github.com/bahamas10/sshp","last_synced_at":"2025-04-06T00:07:07.929Z","repository":{"id":45992791,"uuid":"356502202","full_name":"bahamas10/sshp","owner":"bahamas10","description":"Parallel SSH Executor","archived":false,"fork":false,"pushed_at":"2024-11-05T17:56:52.000Z","size":142,"stargazers_count":118,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-29T23:08:33.044Z","etag":null,"topics":["parallelism","ssh"],"latest_commit_sha":null,"homepage":"https://www.daveeddy.com/2021/05/20/sshp-rewrite-from-javascript-to-c/","language":"C","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/bahamas10.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-10T07:08:50.000Z","updated_at":"2025-03-24T07:18:57.000Z","dependencies_parsed_at":"2024-11-05T18:43:51.603Z","dependency_job_id":null,"html_url":"https://github.com/bahamas10/sshp","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/bahamas10%2Fsshp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fsshp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fsshp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahamas10%2Fsshp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahamas10","download_url":"https://codeload.github.com/bahamas10/sshp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247415967,"owners_count":20935388,"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":["parallelism","ssh"],"created_at":"2024-11-07T05:06:17.836Z","updated_at":"2025-04-06T00:07:07.913Z","avatar_url":"https://github.com/bahamas10.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"![sshp-logo](https://www.daveeddy.com/static/media/github/sshp/c/logo.jpg)\n\n`sshp` - Parallel SSH Executor\n==============================\n\n`sshp` manages multiple ssh processes and handles coalescing the output to the\nterminal.  By default, `sshp` will read a file of newline-separated hostnames\nor IPs and fork ssh subprocesses for them, redirecting the stdout and stderr\nstreams of the child line-by-line to stdout of `sshp` itself.\n\n- [Installation](#installation)\n- [About](#about)\n- [Examples](#examples)\n- [Tips and Tricks](#tips-and-tricks)\n- [Exit Codes](#exit-codes)\n- [Usage](#usage)\n- [Tests and Style](#tests-and-style)\n- [Comparison to Node.js sshp](#comparison-to-nodejs-sshp)\n- [License](#license)\n\nInstallation\n------------\n\nPull the source code and run `make` to compile `sshp`:\n\n``` console\n$ make\ncc -o src/fdwatcher.o -c -D USE_KQUEUE=0 -Wall -Werror -Wextra -Wpedantic -O2 src/fdwatcher.c\ncc -o sshp -Wall -Werror -Wextra -Wpedantic -O2 src/sshp.c src/fdwatcher.o\n$ ./sshp -v\nv1.0.0\n```\n\nThen optionally run `make install` to install `sshp`:\n\n``` console\n$ sudo make install\ncp man/sshp.1 /usr/local/man/man1\ncp sshp /usr/local/bin\n$ sshp -v\nv1.0.0\n```\n\n`sshp` requires a kernel that supports `epoll` or `kqueue` to run.  This has\nbeen tested on Linux, illumos, MacOS, and FreeBSD.\n\nAbout\n-----\n\n`sshp` has 3 modes of execution:\n\n- `line mode` (line-by-line output, default).\n- `group mode` (grouped by hostname output, `-g`).\n- `join mode` (grouped by unique output, `-j`).\n\nThe first 2 modes, `line` and `group`, operate in largely the same way,\ndiffering only in how data is buffered from the child processes and printed to\nthe screen.  Line mode buffers the data line-by-line, whereas group mode does\nno buffering at all and prints the data once it is read from the child.\n\nThe last mode, `join`, however, buffers *all* of the data from all of the child\nprocesses and outputs once all processes have finished.  Instead of grouping\nthe output by host, it is grouped by the output itself to show which hosts had\nthe same output.\n\nExamples\n--------\n\nGiven the following hosts file called `hosts.txt`:\n\n```\n# example hosts file\n\narbiter.rapture.com\ncifs.rapture.com\ndecomp.rapture.com\n```\n\nParallel ssh into hosts supplied by a file running `uname -v`:\n\n![line-by-line](https://www.daveeddy.com/static/media/github/sshp/c/line-by-line.jpg)\n\nPass in `-e` to get the exit codes of the commands on the remote end.  The\nlocal exit code will be 0 if all ssh processes exit successfully, or 1 if any\nof the ssh processes exit with a failure:\n\n![exit-codes](https://www.daveeddy.com/static/media/github/sshp/c/exit-codes.jpg)\n\nAlso note that the hosts file can be passed in via stdin if `-f` is not\nsupplied.\n\nRun with `-d` to get debug information making it clear what `sshp` is doing:\n\n![debug-id](https://www.daveeddy.com/static/media/github/sshp/c/debug-id.jpg)\n\nRun with `-g` (`group mode`) to group the output by hostname as it comes in.\nTo illustrate this, `-m` is set to 1 to limit the maximum number of concurrent\nchild processes to 1, effectively turning `sshp` into an `ssh` serializer:\n\n![serialize-group](https://www.daveeddy.com/static/media/github/sshp/c/serialize-group-mode.jpg)\n\nRun with `-j` (`join mode`) to join the output by the output itself and not the\nhostname:\n\n![join-mode](https://www.daveeddy.com/static/media/github/sshp/c/join-mode.jpg)\n\nSend the `sshp` process a `SIGSUR1` signal to print out process status\ninformation while it is running.  In this example, a signal was sent twice to\nthe process:\n\n![sigusr1-status](https://www.daveeddy.com/static/media/github/sshp/c/sigusr1-status.jpg)\n\nTips and Tricks\n---------------\n\nIf one or more of the hosts you want to ssh into are not in your `known_hosts`\nfile it can be really overwhelming to get all of the warning messages / prompts\nto save the host key.  You can manually accept any new keys 1-by-1 with:\n\n    sshp -f hosts.txt -m 1 true\n\nOr, accept all keys without any confirmation or validation (use at your own\nrisk):\n\n    sshp -f hosts.txt -o StrictHostKeyChecking=no true\n\nExit Codes\n----------\n\n- `0` Everything worked and all child processes exited successfully.\n- `1` Everything worked, but 1 or more children exited with a non-zero code.\n- `2` Incorrect usage - the user supplied something incorrect preventing `sshp`\n  from being able to run (unknown options, invalid host file, etc.).\n- `3` Program failure - the program experienced some failing in the system\n  preventing `sshp` from being able to run (`malloc` failure, `epoll` failure,\n  etc.).\n- `4` `sshp` killed by `SIGTERM` or `SIGINT`.\n- `*` Anything else - probably a blown assertion.\n\nUsage\n-----\n\n``` console\n$ sshp -h\n        _\n  _____| |_  _ __     Parallel SSH Executor (v1.1.0)\n (_-\u003c_-\u003c ' \\| '_ \\    Source: https://github.com/bahamas10/sshp\n /__/__/_||_| .__/    Compiled: Jun  2 2021 12:23:56 (using kqueue)\n            |_|       MIT License\n\nParallel ssh with streaming output.\n\nUSAGE:\n    sshp [-m maxjobs] [-f file] command ...\n\nEXAMPLES:\n    ssh into a list of hosts passed via stdin and get the output of uname -v.\n\n      sshp uname -v \u003c hosts\n\n    ssh into a list of hosts passed on the command line, limit max parallel\n    connections to 3, and grab the output of pgrep.\n\n      sshp -m 3 -f hosts.txt pgrep -fl process\n\n    Upgrade packages on all hosts in the list one-by-one, grouping the output\n    by host, with debugging output enabled.\n\n      sshp -m 1 -f hosts.txt -d -g pkg-manager update\n\nOPTIONS:\n  -a, --anonymous            Hide hostname prefix, defaults to false.\n  -c, --color \u003con|off|auto\u003e  Set color output, defaults to auto.\n  -d, --debug                Enable debug info, defaults to false.\n  -e, --exit-codes           Show command exit codes, defaults to false.\n  -f, --file \u003cfile\u003e          A file of hosts separated by newlines, defaults to stdin.\n  -g, --group                Group output by hostname (group mode).\n  -h, --help                 Print this message and exit.\n  -j, --join                 Join hosts together by output (join mode).\n  -m, --max-jobs \u003cnum\u003e       Max processes to run concurrently, defaults to 50.\n  -n, --dry-run              Don't actually execute subprocesses.\n  -s, --silent               Silence all output subprocess stdio, defaults to false.\n  -t, --trim                 Trim hostnames (remove domain) on output, defaults to false.\n  -v, --version              Print the version number and exit.\n  -x, --exec \u003cprog\u003e          Program to execute, defaults to ssh.\n  --max-line-length \u003cnum\u003e    Maximum line length (in line mode), defaults to 1024.\n  --max-output-length \u003cnum\u003e  Maximum output length (in join mode), defaults to 8192.\n\nSSH OPTIONS: (passed directly to ssh)\n  -i, --identity \u003cident\u003e     ssh identity file to use.\n  -l, --login \u003cname\u003e         The username to login as.\n  -o, --option \u003ckey=val\u003e     ssh option passed in key=value form.\n  -p, --port \u003cport\u003e          The ssh port.\n  -q, --quiet                Run ssh in quiet mode.\n\nMORE:\n    See sshp(1) for more information.\n```\n\nTests and Style\n----------------\n\n`sshp` comes with a very simple test suite.  It checks for just basic usage and\nsanity.  It can be run with `make test`:\n\n``` console\n$ make test\ncd test \u0026\u0026 ./runtest test_*\nrunning:  ./test_00_usage\nsshp -v  is 0 ... ok\nsshp -h  is 0 ... ok\nsshp  is 2 ... ok\nsshp -f / cmd  is 2 ... ok\nsshp -f /should-not-exist cmd  is 2 ... ok\nsshp -f /dev/null cmd  is 2 ... ok\nsshp -f ./assets/hosts/empty-hosts.txt cmd  is 2 ... ok\nsshp -m  is 2 ... ok\nsshp -m 0  is 2 ... ok\nsshp -m foo  is 2 ... ok\nsshp -m -17  is 2 ... ok\nsshp -g -j  is 2 ... ok\nsshp -n -f ./assets/hosts/simple-hosts.txt cmd  is 0 ... ok\nsshp -n -f - cmd  is 0 ... ok\nsshp -n cmd  is 0 ... ok\nsshp -n -f ./assets/hosts/long-hosts-good.txt cmd  is 0 ... ok\nsshp -n -f ./assets/hosts/long-hosts-bad.txt cmd  is 2 ... ok\n\nrunning:  ./test_10_exec\nsshp -x ./assets/cmd/true arg  is 0 ... ok\nsshp -x ./assets/cmd/true -j arg  is 0 ... ok\nsshp -x ./assets/cmd/true -g arg  is 0 ... ok\nsshp -x ./assets/cmd/false arg  is 1 ... ok\nsshp -x ./assets/cmd/false -j arg  is 1 ... ok\nsshp -x ./assets/cmd/false -g arg  is 1 ... ok\nsshp -x ./assets/cmd/hello -a arg code  is 0 ... ok\nsshp -x ./assets/cmd/hello -a arg stdout  is hello ... ok\n\nrunning:  ./test_20_signals\n../sshp -x ./assets/cmd/sleep arg TERM code  is 4 ... ok\n../sshp -x ./assets/cmd/sleep arg INT code  is 4 ... ok\n```\n\nStyle can be checked with `make check`, this does not require the program to be\ncompiled:\n\n``` console\n$ make check\n./test/check src/*.h src/*.c test/* man/*.md\nchecking:  src/fdwatcher.h\nchecking:  src/fdwatcher.c\nchecking:  src/sshp.c\nchecking:  test/check\nchecking:  test/hosts.txt\nchecking:  test/test\nchecking:  man/sshp.md\n```\n\nThe style check is *very* simple.  It ensures:\n\n1. No line exceeds 80 columns.\n2. No consecutive blank lines.\n3. Consistent use of tabs and spaces.\n\nComparison to Node.js `sshp`\n----------------------------\n\nThis program was originally written in Node.js and released as\n[node-sshp](https://github.com/bahamas10/node-sshp).  This C variant is mostly\ncompatible with the original Node.js version with some slight alterations:\n\n- `-b` has been changed to `-c off` (disable color output).\n- `-N` has been removed in favor of `-o StrictHostKeyChecking=no`.\n- `-o` has been added to allow for any ssh option to be passed in.\n- `-u` has been removed (not applicable without `npm`).\n- `-y` has been removed in favor of `-o RequestTTY=force`.\n\nFor more information on why `sshp` was ported from JavaScript to C, see [this\nblog post](https://www.daveeddy.com/2021/05/20/sshp-rewrite-from-javascript-to-c/).\n\nLicense\n-------\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahamas10%2Fsshp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahamas10%2Fsshp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahamas10%2Fsshp/lists"}