{"id":20947751,"url":"https://github.com/alphahydrae/tcpwait","last_synced_at":"2026-04-29T04:32:12.579Z","repository":{"id":57553998,"uuid":"180447199","full_name":"AlphaHydrae/tcpwait","owner":"AlphaHydrae","description":"Wait for TCP endpoints to be reachable (e.g. wait for a database in a Docker container)","archived":false,"fork":false,"pushed_at":"2019-04-30T11:47:40.000Z","size":62,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-19T22:15:07.191Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/AlphaHydrae.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-09T20:49:17.000Z","updated_at":"2019-04-30T11:47:41.000Z","dependencies_parsed_at":"2022-09-26T18:51:03.864Z","dependency_job_id":null,"html_url":"https://github.com/AlphaHydrae/tcpwait","commit_stats":null,"previous_names":["alphahydrae/probetcp"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaHydrae%2Ftcpwait","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaHydrae%2Ftcpwait/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaHydrae%2Ftcpwait/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlphaHydrae%2Ftcpwait/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlphaHydrae","download_url":"https://codeload.github.com/AlphaHydrae/tcpwait/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243345570,"owners_count":20275869,"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-11-19T00:12:56.458Z","updated_at":"2025-12-29T04:49:07.074Z","avatar_url":"https://github.com/AlphaHydrae.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tcpwait\n\nWait for TCP endpoints to be reachable (e.g. wait for a database in a Docker container).\n\n```\n$\u003e tcpwait --retries 10 --timeout 1000 db.example.com:5432 -- rails server\n```\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n\n- [Installation](#installation)\n  - [Dockerfile](#dockerfile)\n  - [Homebrew](#homebrew)\n  - [Download binary](#download-binary)\n- [Usage](#usage)\n  - [Timeout](#timeout)\n  - [Retrying](#retrying)\n  - [Multiple endpoints](#multiple-endpoints)\n  - [Executing a command](#executing-a-command)\n  - [Environment variable interpolation](#environment-variable-interpolation)\n    - [Dockerfile](#dockerfile-1)\n  - [Quiet](#quiet)\n  - [TL;DR](#tldr)\n- [Exit codes](#exit-codes)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n[![version](https://img.shields.io/badge/Version-v2.2.0-blue.svg)](https://github.com/AlphaHydrae/tcpwait/releases/tag/v2.2.0)\n[![build status](https://travis-ci.org/AlphaHydrae/tcpwait.svg?branch=master)](https://travis-ci.org/AlphaHydrae/tcpwait)\n[![license](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt)\n\n\n\n## Installation\n\n### Dockerfile\n\n```\nRUN wget -O /usr/local/bin/tcpwait \\\n  https://github.com/AlphaHydrae/tcpwait/releases/download/v2.2.0/tcpwait_v2.2.0_linux_amd64 \u0026\u0026 \\\n  chmod +x /usr/local/bin/tcpwait\n```\n\n### Homebrew\n\n```\nbrew install alphahydrae/tools/tcpwait\n```\n\n### Download binary\n\n* **Linux**\n\n  ```\n  wget -O /usr/local/bin/tcpwait \\\n    https://github.com/AlphaHydrae/tcpwait/releases/download/v2.2.0/tcpwait_v2.2.0_linux_amd64 \u0026\u0026 \\\n    chmod +x /usr/local/bin/tcpwait\n  ```\n* **Linux (arm64)**\n\n  ```\n  wget -O /usr/local/bin/tcpwait \\\n    https://github.com/AlphaHydrae/tcpwait/releases/download/v2.2.0/tcpwait_v2.2.0_linux_arm64 \u0026\u0026 \\\n    chmod +x /usr/local/bin/tcpwait\n  ```\n* **macOS**\n\n  ```\n  wget -O /usr/local/bin/tcpwait \\\n    https://github.com/AlphaHydrae/tcpwait/releases/download/v2.2.0/tcpwait_v2.2.0_darwin_amd64 \u0026\u0026 \\\n    chmod +x /usr/local/bin/tcpwait\n  ```\n* **Windows**\n\n  ```\n  wget -O /usr/local/bin/tcpwait \\\n    https://github.com/AlphaHydrae/tcpwait/releases/download/v2.2.0/tcpwait_v2.2.0_windows_amd64 \u0026\u0026 \\\n    chmod +x /usr/local/bin/tcpwait\n  ```\n\n\n\n## Usage\n\n**tcpwait** will attempt to establish a TCP connection to an endpoint and exit successfully if that endpoint can be reached:\n\n```\n$\u003e tcpwait google.com:80\nReached \"google.com:80\" in 0.008598s\n\n$\u003e echo $?\n0\n```\n\nIf the connection cannot be established, **tcpwait** will exit with a non-zero code:\n\n```\n$\u003e tcpwait google.com:12345\nError: could not reach \"google.com:12345\" after 1.000910s\n\n$\u003e echo $?\n3\n```\n\n### Timeout\n\n**tcpwait** uses a connection timeout of 1000 milliseconds by default.\n\nUse the `-t, --timeout \u003cvalue\u003e` option to change it. For example, this command\nwill wait for one minute before determining that it cannot connect:\n\n```\n$\u003e tcpwait -t 60000 google.com:12345\nError: could not reach \"google.com:12345\" after 60.004512s\n```\n\nNote that the timeout does not increase the duration of successful connection\nattempts.  In this example, the command will return immediately even though the\ntimeout is high, because it stops as soon as the connection can be made:\n\n```\n$\u003e tcpwait -t 60000 google.com:80\nReached \"google.com:80\" in 0.007431s\n```\n\n### Retrying\n\nWith the `-r, --retries \u003cvalue\u003e` option, **tcpwait** will retry to connect to\nthe TCP endpoint if it fails. The value of the option is the number of times to\nretry:\n\n```\n$\u003e tcpwait -r 4 google.com:12345\nWaiting for google.com:12345 (1)...\nWaiting for google.com:12345 (2)...\nWaiting for google.com:12345 (3)...\nWaiting for google.com:12345 (4)...\nError: could not reach \"google.com:12345\" after 5.019876s\n```\n\n\u003e Note that the total number of attemps is equal to the number of retries plus\n\u003e one, in this example 5, because retries are made in addition to the initial\n\u003e connection attempt.\n\nThe `-i, --interval \u003cvalue\u003e` option can be used to introduce a delay between\neach connection attempt:\n\n```\n$\u003e tcpwait -i 500 -r 4 google.com:12345\nWaiting for google.com:12345 (1)...\nWaiting for google.com:12345 (2)...\nWaiting for google.com:12345 (3)...\nWaiting for google.com:12345 (4)...\nError: could not reach \"google.com:12345\" after 7.032964s\n```\n\nIn this case, the total duration is 7 seconds instead of 5 like the previous\nexample, because the command waited for 500 additional milliseconds between each\nconnection attempt.\n\n### Multiple endpoints\n\nYou may provide **tcpwait** with multiple TCP endpoints to attempt to connect\nto. It will do so in parallel and return successfully as soon as all endpoints\nhave been successfully reached:\n\n```\n$\u003e tcpwait github.com:22 github.com:80 github.com:443\nReached \"github.com:443\" in 0.030656s\nReached \"github.com:22\" in 0.030723s\nReached \"github.com:80\" in 0.030755s\n\n$\u003e echo $?\n0\n```\n\n\u003e Note that the order in which the result messages are printed is\n\u003e non-deterministic.\n\nIf one or more of the TCP endpoints cannot be reached, the command will exit\nwith a non-zero code:\n\n```\n$\u003e tcpwait github.com:22 github.com:80 github.com:443 github.com:12345\nReached \"github.com:80\" in 0.029169s\nReached \"github.com:443\" in 0.029225s\nReached \"github.com:22\" in 0.029252s\nError: could not reach \"github.com:12345\" after 1.004060s\n\n$\u003e echo $?\n3\n```\n\nYou may use **tcpwait**'s retry and timeout options with multiple endpoints. All\nconnection attemts will be made with the same parameters. For example, this\ncommand will attempt to reach `google.com:12345` and `google.com:23456` with 2\nadditional retry attempts before failing:\n\n```\n$\u003e tcpwait -r 2 google.com:12345 google.com:23456\nWaiting for google.com:23456 (1)...\nWaiting for google.com:12345 (1)...\nWaiting for google.com:23456 (2)...\nWaiting for google.com:12345 (2)...\nError: could not reach \"google.com:23456\" after 3.013016s\n```\n\n### Executing a command\n\n**tcpwait** will interpret all arguments after the terminator (`--`) as a\ncommand to execute after all the TCP endpoints have been reached.\n\nThis can be used to conditionally execute a command as soon as a service, such\nas a database, is reachable. For example, the following command could be used to\nrun a Ruby on Rails application as soon as the database server can be reached:\n\n    tcpwait db.example.com:5432 -- rails server\n\n\u003e Note that the command is executed with [execve] and replaces **tcpwait**'s\n\u003e process, i.e. there is no leftover **tcpwait** process once the command\n\u003e executes, even if it is long-running like a web application.\n\n### Environment variable interpolation\n\n**tcpwait** will interpolate variables in TCP endpoint strings as well as in the\nvalue of its numeric options (`-i, --interval`, `-r, --retries`, and `-t,\n--timeout`):\n\n```\n$\u003e export TCPWAIT_HOST=google.com TCPWAIT_PORT=12345\n\n$\u003e tcpwait --retries '${TCPWAIT_RETRIES-3}' '$TCPWAIT_HOST:$TCPWAIT_PORT'\nWaiting for google.com:12345 (1)...\nWaiting for google.com:12345 (2)...\nWaiting for google.com:12345 (3)...\nError: could not reach \"google.com:12345\" after 4.011786s\n```\n\nSupported expansions are documented in the [interpolate] library.\n\n\u003e Note the use of single quotes. If you used double quotes or no quotes, the\n\u003e shell would interpolate the variables before they are passed to **tcpwait**.\n\u003e With single quotes, the string value, e.g. `${TCPWAIT_RETRIES-3}` is passed as\n\u003e is to **tcpwait**, which does the interpolation itself.\n\n#### Dockerfile\n\nAn example of how this feature can be useful is to support interpolating\nvariables into **tcpwait**'s arguments when using it with the exec form of a\nDockerfile's [`ENTRYPOINT`][entrypoint]:\n\n```\nENTRYPOINT [ \"tcpwait\", \"${DB_HOST-db}:${DB_PORT-5432}\", \"--\", \"rails\", \"server\" ]\n```\n\nNormally these variables would only be interpolated using `ENTRYPOINT`'s *shell*\nform, but since **tcpwait** is capable of interpolating those variables at\nruntime, you can use it with `ENTRYPOINT`'s *exec* form.\n\n### Quiet\n\n**tcpwait** outputs information on its standard error stream by default, to\nindicate failure or success, or that it it waiting. You can silence these\nmessages with the `-q, --quiet` option:\n\n```\n$\u003e tcpwait -q -r 4 google.com:12345\n\n$\u003e echo $?\n3\n```\n\n### TL;DR\n\nRun `tcpwait --help` for instructions:\n\n```\ntcpwait waits for TCP endpoints to be reachable.\n\nUsage:\n  tcpwait [OPTION...] ENDPOINT... [--] [EXEC...]\n\nOptions:\n  -i, --interval string   Time to wait between retries in milliseconds (default 0) (default \"0\")\n  -q, --quiet             Do not print anything (default false)\n  -r, --retries string    Number of times to retry to reach the endpoint if it fails (default 0) (default \"0\")\n  -t, --timeout string    TCP connection timeout in milliseconds (default 1000) (default \"1000\")\n\nExamples:\n  Wait for a website:\n    tcpwait google.com:80\n  Wait for a MySQL database (10 attempts every 2 seconds):\n    tcpwait -r 9 -i 2000 tcp://localhost:3306\n  Wait for multiple endpoints:\n    tcpwait github.com:22 github.com:80 github.com:443\n  Execute a command after an endpoint is reached:\n    tcpwait db.example.com:5432 -- rails server\n```\n\n\n\n## Exit codes\n\n**tcpwait** may exit with the following status codes:\n\nCode | Description\n:--- | :---\n`0`  | All endpoints were reached successfully.\n`1`  | Invalid arguments were given.\n`2`  | An unrecoverable error occurred while attempting to reach a TCP endpoint.\n`3`  | One of the endpoints could not be reached (even after retrying, if applicable).\n`4`  | An unrecoverable error occurred while trying to interpolate environment variables into options or TCP endpoint strings.\n`10` | The command to execute (provided after `--`) could not be found in the `$PATH`.\n`11` | An unrecoverable error occurred while attempting to execute the command.\n\n\u003e Note that if a command to execute is specified (after `--`), it is executed\n\u003e with [execve], meaning that the **tcpwait** process is replaced by the\n\u003e command's.\n\u003e\n\u003e In this case, the exit code returned will be that of the executed command, not\n\u003e **tcpwait**'s. Look in the command's documentation for the meaning of its exit\n\u003e codes.\n\n\n\n[entrypoint]: https://docs.docker.com/engine/reference/builder/#entrypoint\n[execve]: https://linux.die.net/man/2/execve\n[interpolate]: https://github.com/buildkite/interpolate#supported-expansions\n[go]: https://golang.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falphahydrae%2Ftcpwait","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falphahydrae%2Ftcpwait","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falphahydrae%2Ftcpwait/lists"}