{"id":17992850,"url":"https://github.com/leostera/try","last_synced_at":"2025-04-04T04:45:57.236Z","repository":{"id":141535012,"uuid":"61627604","full_name":"leostera/try","owner":"leostera","description":":recycle: A portable Go utility to retry commands with backoff","archived":false,"fork":false,"pushed_at":"2016-09-12T12:33:51.000Z","size":19,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-09T16:16:38.552Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/leostera.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2016-06-21T11:10:29.000Z","updated_at":"2018-11-30T07:48:41.000Z","dependencies_parsed_at":"2023-08-15T23:51:35.432Z","dependency_job_id":null,"html_url":"https://github.com/leostera/try","commit_stats":null,"previous_names":["leostera/try"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Ftry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Ftry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Ftry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Ftry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leostera","download_url":"https://codeload.github.com/leostera/try/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247123099,"owners_count":20887259,"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":[],"created_at":"2024-10-29T20:09:26.043Z","updated_at":"2025-04-04T04:45:57.217Z","avatar_url":"https://github.com/leostera.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# try [![Travis-CI](https://api.travis-ci.org/ostera/try.svg)](https://travis-ci.org/ostera/try)\n:recycle: A portable Go utility to retry commands with backoff\n\n## Installation\n\nGet your preferred binary flavour from the [releases page](https://github.com/ostera/try/releases).\n\nOr if you have a go environment:\n\n```\ngo get github.com/ostera/try\n```\n\nFrom source just run `make` and put the `try` executable somewhere handy.\n\n## Usage\n\n```\n~ λ try\n\n   Usage: try [options] \u003ccmd\u003e\n\n   Sample: try -i=10s -r=10 docker pull ubuntu:latest\n\n           Run the command up to 10 times, with the start interval of 10 seconds,\n           doubling the interval on every iteration.\n\n   Options:\n\n     -i, --interval             start interval time (default to 1s)\n     -r, --retries              amount of retries (default to 10)\n     -f, --factor               multiply interval by this factor (default to 2)\n\n     -h, --help                 this help page\n     -v, --version              print out version\n\n```\n\n## Motivation\n\nThe main pain point was re-running commands that are affected by transient errors.\n\n`curl`-ing an HTTP endpoint, `docker pull`-ing an image, any remote ssh transfers.\nAll of these are typically vulnerable to transient network errors.\n\nIt's fairly straightforward to do a while loop in bash to repeat the command if it\nfails, but you don't want it to run infinitely, and you also want to see the output\nas it executes, and it should capture command failures gracefully and not explode.\n\nAs complexity arises, `bash` syntax gets more and more cryptic.\n\nMy interim solution for it was this:\n\n```bash\n#!/bin/bash\n\nreadonly COMMAND=$*\necho About to run: $COMMAND\n\nlet COUNTER=10\nlet COMMAND_STATUS=0\n\ntrap 'exit $COMMAND_STATUS;' EXIT;\n\nexec 3\u003e\u00261\nexec 4\u003e\u00262\n\nfor i in $(seq 0 $COUNTER); do\n  eval $COMMAND 1\u003e\u00263 2\u003e\u00264\n  COMMAND_STATUS=$?\n  if [[ $COMMAND_STATUS == 0 ]]; then\n    exit 0\n  fi\n  echo \"Retry: $i\"\n  sleep $(($i*2))\ndone\n```\n\nHacky, but does the job. Now it's time I have a version I can run anywhere without\nthinking of pipe alias syntax, or sub-shell trapping.\n\n## Contributing\n\nIf you don't have it yet, you can install `watch` to continuously build the project:\n\n```\nrepos/try λ watch make\n/Users/leostera/.go/bin/gometalinter @.gometalinter\n/usr/local/bin/go vet\n/usr/local/bin/go build -o ./watch\n/usr/local/bin/go test\nPASS\nok      _/Users/leostera/repos/watch    0.013s\n/usr/local/bin/go test -bench .\nPASS\nBenchmarkRunSuccessfully-4           500           3860598 ns/op\nBenchmarkRunExit-4                   300           3834855 ns/op\nok      _/Users/leostera/repos/watch    3.908s\nexit: 0\n```\n\n## Next Steps\n\nSee the [issues page](https://github.com/ostera/try/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) for a list of planned enhancements and features.\n\n## License\n\nSee [LICENSE.md](https://github.com/ostera/try/blob/master/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleostera%2Ftry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleostera%2Ftry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleostera%2Ftry/lists"}