{"id":17047442,"url":"https://github.com/djmgit/pexec","last_synced_at":"2025-08-12T16:43:06.366Z","repository":{"id":104035674,"uuid":"262596347","full_name":"djmgit/Pexec","owner":"djmgit","description":"A lightweight CLI based tool and library for remote command execution","archived":false,"fork":false,"pushed_at":"2020-08-03T13:56:33.000Z","size":36706,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-28T10:24:06.279Z","etag":null,"topics":["automation","ci","cloud","devops"],"latest_commit_sha":null,"homepage":"","language":"Go","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/djmgit.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":"2020-05-09T15:06:55.000Z","updated_at":"2022-03-28T08:40:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"deb8d1d9-2935-4d05-9aa0-864b75fc7cdd","html_url":"https://github.com/djmgit/Pexec","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djmgit%2FPexec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djmgit%2FPexec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djmgit%2FPexec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/djmgit%2FPexec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/djmgit","download_url":"https://codeload.github.com/djmgit/Pexec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245052651,"owners_count":20553163,"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":["automation","ci","cloud","devops"],"created_at":"2024-10-14T09:49:31.274Z","updated_at":"2025-03-23T03:44:16.935Z","avatar_url":"https://github.com/djmgit.png","language":"Go","readme":"# PExec\n\nPExec is a lightweight CLI based tool and libray for executing commands on remote servers. It allows you to execute\ncommands on a list of remote hosts both sequentially - one after the other, parallely - execute the command on all the\nhosts simultaneously all at once to speed up the process and lastly to group the list of servers into batches and execute\nthe command on the servers present in those individual batches in parallel.\n\nAdditionally, PExec also allows you to **discover**  instances from cloud (as of now only **AWS**) and execute commands on them.\nOnce PExec is provieded with the neccessary constraints and parameneters - for example : auto scaling group name in AWS or a tag key\nand its corresponding value, PExec will use those provided information to discover the IPs of the desired instances, connect to\nthem over SSH on the desired port and execute the given command.\n\nPExec can be used for automating usual tasks, or as a part of a bigger tool or CI/CD where you want to execute commands remotely\nand you want to make it fast.\n\nAs of now PExec only provided integration with AWS for auto discovery of instances.\n\n## QuickStart\n\n### Using PExec as a library\n\n**Executing command remotely on all the instances of an AWS Autoscaling group using automatic service discovery**\n\n```\npackage main\n\nimport (\n\tpexec \"github.com/djmgit/pexec/lib\"\n\t\"fmt\"\n)\n\nfunc main() {\n\n\tproviderOptions := map[string]string{\n\t\t\"region\": \"aws_region_name\",\n\t\t\"addrType\": \"public_v4\",\n\t\t\"tagKey\": \"aws:autoscaling:groupName\",\n\t\t\"tagValue\": \"\u003caws_asg_name\u003e\",\n\t\t\"accessKeyId\": \"\u003caws_access_key_id\u003e\",\n\t\t\"secretAccessKey\": \"\u003caws_secret_access_key\u003e\",\n\t}\n\n\tpClient := pexec.PexecClient{\n\t\tParallel: true,\n\t\tBatchSize: 0,\n\t\tUser: \"ubuntu\",\n\t\tPort: 22,\n\t\tProvider: \"AWS\",\n\t\tProviderOptions: providerOptions,\n\t\tKeyPath: \"\u003cpath_to_ssh_key_trusted_by_the_target_insatnces\u003e\",\n\t}\n\n\tresponse, err := pClient.Run(\"echo 'Hellow World'\")\n\n\tif err != nil {\n\t\tfmt.Println(err.Error())\n\t} else {\n\t\tfmt.Println(\"In main...\")\n\t\tfor _, commandResponse := range response {\n\t\t\tfmt.Println(commandResponse.Host + \" : \" + commandResponse.CommandResponse.StdOutput)\n\t\t}\n\t}\n}\n\n```\n\nIn the above example, the tagKey field's value can be changed to some other valid key and the corresponding tagvalue can be provided\nto filter desired instances.\nIn the above Pexec client configuration, parallel is set to ```true``` and batchSize is set to ```0``` which means, command will be executed\nsimultaneously on all the discovered servers. Setting the batchSize to non-zero, for example ```2``` would distribute the discovered servers\ninto groups of ```2``` servers and the command would be executed in parallel on all the individual servers of a group but each group will be processed\nsequentially.\n\nFor example : if there were 4 servers and batchSize would be set to 2. then PExec would distribute the 4 discovered servers into 2 grousp of two\nservers each, it would iterate sequentially over each group and execute the command on both the servers of the current group in parallel.\nThis can be usefull when you dont want to execute your command on all the servers at once but still want to speed up the process. For example you\nwant to restart apache or redis slaves, but you dont want to take down all of them at once but in batches.\n\nRight now there is no way to configure a delay between the processing of two groups, but that will be added soon.\n\nIn case you do not want PExec to execute the command in parallel on all the servers, you can set ```Parallel``` to ```false```. Doing that\nwill cause PExec to iterate sequentially over the list of discovered servers and execute the provided command.\n\n**Executing command remotely on custom provided servers**\n\nPExec also allows you to provide host IPs manually for remote command execution.\n\n```\npackage main\n\nimport (\n\tpexec \"github.com/djmgit/pexec/lib\"\n\t\"fmt\"\n)\n\nfunc main() {\n\n\tpClient := pexec.PexecClient{\n\t\tTargetServers : []pexec.Server{\n\t\t\t{\n\t\t\t\tHost: \"52.87.231.249\",\n\t\t\t\tPort: 22,\n\t\t\t},\n\t\t\t{\n\t\t\t\tHost: \"35.174.213.9\",\n\t\t\t\tPort: 22,\n\t\t\t},\n\t\t},\n\t\tParallel: true,\n\t\tBatchSize: 0,\n\t\tUser: \"ubuntu\",\n\t\tProvider: \"CUSTOM\",\n\t\tKeyPath: \"\u003cpath_to_ssh_key_trusted_by_the_target_insatnces\u003e\",\n\t}\n\n\tresponse, err := pClient.Run(\"echo 'Hello World'\")\n\n\tif err != nil {\n\t\tfmt.Println(err.Error())\n\t} else {\n\t\tfmt.Println(\"In main...\")\n\t\tfor _, commandResponse := range response {\n\t\t\tfmt.Println(commandResponse.Host + \" : \" + commandResponse.CommandResponse.StdOutput)\n\t\t}\n\t}\n}\n\n```\n\nIn order to execute command on custom list of hosts, the list of hosts has to be provided as the ```TargetServers``` field. The list consists of\nstructs of type ```pexec.Server``` which has only two fields : ```Host``` and ```Port```. Remaining all the other field have the same meaning.\n\nIn both the examples presented above, the field ```Provider``` as of now can be either of ```AWS``` or ```CUSTOM```.\n\nAlso it is to be noted that PExec executes commands on the remote servers using ```SSH``` and it allows SSH only via key based authentication and\nnot password. So you need to provide you ```private key``` path or path to your ```pem``` file in ```keyPath``` field of ```PexecClient``` struct.\nAlso the key you are providing should be trusted by the target hosts. If you omit the ```keyPath``` field then the path to the current users\nSSH RSA key will be used.\n\n### Using PExec as a CLI based tool\n\n**Executing command remotely on all the instances of an AWS Autoscaling group using automatic service discovery**\n\n```\n./pexec -provider=AWS -port=22 \\\n\u003e -asg=[aws_asg_name] -region=[aws_region] \\\n\u003e --access_key_id=[aws_access_key_id] -secret_access_key=[aws_secret_access_key] \\\n\u003e -key=[path_to_ssh_key] \\\n\u003e  -user=ubuntu -cmd=\"echo 'Hello World'\"\n```\n\nIf you want to provide custom tag key and tag value for filtering instances, you can do so by using ```tag_key``` and ```tag_value``` parameters.\n\n**Executing command remotely on custom provided servers**\n\n```\n./pexec -provider=CUSTOM \\\n\u003e -key=[path_to_ssh_key] \\\n\u003e -user=ubuntu \\\n\u003e -cmd=\"echo 'Hello World'\" \\\n\u003e -servers=52.87.231.249:22,35.174.213.9:22\n```\n\n## Installing PExec for using it as a CLI tool\n\n### Using prebuilt binary\n\nYou can use the prebuilt binary from github :\n\n- Download the compressed prebuilt binary from \u003ca href=\"https://github.com/djmgit/Pexec/releases/download/v0.0.1/pexec-v0.0.1.tar.xz\"\u003ehere\u003c/a\u003e\n- Extract the binary using ```tar -xvf pexec.tar.xz```\n- Copy the binary to your path for example ```/usr/local/bin```\n- Open terminal and execute ```pexec -h```, it should print all the relevant options.\n\n### Building PExec from source\n\nyou can build PExec from source:\n\n- Clone this repository or download the code from \u003ca href=\"https://github.com/djmgit/Pexec/archive/v0.0.1.tar.gz\"\u003ehere\u003c/a\u003e\n- Extract the source if requited and enter into the source root.\n- You will require the **go toolchain** for this, preferably version\u003e=1.11\n- From the project root execute ```go build -o ./cmd/pexec cmd/pexec.go```\n- You will find the binary at cmd/\n- Run ```./pexec -h```, it should show you all the relevant options.\n- Optionally you can copy it to your path.\n\n\n## PExec library reference\n\nGiven below is the ```PexecClient``` struct you will have to initialise in order to use PExec as a library.\nNot all fields are required to be used as they will be assigned a default value.\n\n```\ntype PexecClient struct {\n\n\tTargetServers []Server\n\n\tPort int\n\n\tProviderOptions map[string]string\n\n\tProvider string\n\n\tParallel bool\n\n\tBatchSize int\n\n\tUser string\n\n\tKeyPath string\n\n\tDebug bool\n\n\tLogger *log.Logger\n}\n```\n\n- TargetServers is a list of structs of type Server. You will have to initialise this in case you want to execute commands\n  remote custom provided hosts. Server is struct is as shown below:\n  \n  ```\n  type Server struct {\n\tHost string\n\n\tPort int\n  }\n  ```\n- Port : Port to use for ssh, this will be used when you are using a provider other than **CUSTOM**. Default will be **22**. For custom provided\n  list of servers, you will have to provided port for the individual servers.\n  \n- ProviderOptions: Options to be used when using a provider (AWS as of now). Options required as of now:\n\t- region\n\t- addrType\n\t- tagKey\n\t- tagValue\n\t- accessKeyId\n\t- secretAccessKey\n\n- Provider : This can be either of **CUSTOM** or **AWS** as of now. If nothing is provided then it will be set to CUSTOM.\n\n- Parallel : If set to **true** then command will be executed in parallel in all the provided/discovered servers or else it will be executed\n             sequentially\n\t \n- BatchSize : If set to non-zero value and if **Parallel** is set to true, then teh list of provided/discovered hosts will be distributed in batches\n              of the provided number of hosts and command will be executed parallely on the members of the individual groups. It is to be noted that the\n\t      groups themselves will be iterated upon sequentially. Please see the example in the **QuickStart** section above for further explaination.\n\t      \n- User : User to be used by PExec for openning SSH connection. Default will be **root**\n\n- KeyPath : The path to SSH key to be used for SSH. It can be a pem file containing the key or the key itself trusted by the target servers.\n\n- Debug : If set to true, PExexc will generate debug statements.\n\n- Logger : This can be custom provided logger. However if Debug is set to true, then a logger will be created and assigned to this field.\n\nApart from the above fields the struct also contains some other fileds which are used internally by PExec.\n\n## PExec CLI tool refernce\n\nThe follow options are provided by the CLI tool:\n\n```\nUsage of ./pexec:\n  -access_key_id string\n    \tAWS Access key id\n  -addr_type string\n    \tCommand to execute on the servers (default \"public_v4\")\n  -asg string\n    \tAWS Auto scaling group name\n  -batch_size int\n    \tIf more than one, then batches of that many servers will be executed in parallel\n  -cmd string\n    \tCommand to execute on the servers\n  -debug\n    \tEnable debugging, by default false\n  -key string\n    \tIf not provided then default key path for rsa key will be used - /home/\u003cuser\u003e/.ssh/id_rsa\n  -parallel\n    \tIf true then commands will be exected in parallel on the discovered or provided servers (default true)\n  -port int\n    \tPort to override for all\n  -provider string\n    \tProvider of servers - can be one of CUSTOM | AWS (default \"CUSTOM\")\n  -region string\n    \tAWS region if provider is aws, default is us-east-1 (default \"us-east-1\")\n  -secret_access_key string\n    \tAWS secret access key\n  -servers string\n    \tServer ip and port in format \u003cIP\u003e:\u003cPORT\u003e, multuple values can be separated by ','. If port is not provided then 22 will be used as default SSH port\n  -tag_key string\n    \ttag key name\n  -tag_value string\n    \ttag value\n  -user string\n    \tUser which will be used to login to the server (default \"root\")\n\n```\n\nMost of the options directly refers to a field in the PexecClient struct as already described in the previous section.\n\n## Contributing to PExec\n\t     \nContribution to PExec are most welcome. If you have found a bug or if you have any feature in mind or if you want to\nhelp in integrating other cloud platforms or other providers/prchestrators like Consul, DCOS, etc, please create an issue\nsend a PR. I would be extremely happy to review it.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjmgit%2Fpexec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdjmgit%2Fpexec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdjmgit%2Fpexec/lists"}