vishnubob / wait-for-it Goto Github PK
View Code? Open in Web Editor NEWPure bash script to test and wait on the availability of a TCP host and port
License: MIT License
Pure bash script to test and wait on the availability of a TCP host and port
License: MIT License
wait-for
should throw an error message if dependencies are missing.
For example the Centos7 image neither has netcat
nor tcp
installed. A friendly message that this packages are neccessary.
Alternatively a hint in the README
should point the admin to the required packages.
Would you mind explicitly adding a license to this script? I realize this sounds like a ridiculous request, but lawyers are annoying. ;)
I am using a reverse proxy where a lot of services are located under the same domain on different paths.
my-domain/api/bacon
my-domain/api/potato
And I would like to wait for each of these services individually.
Would it be possible to do something like:
wait-for-it my-domain:80/api/bacon
I've tryed some variations of it and all of them fail.
Having quickly skimmed through the script, I couldn't find a way to wait for multiple host+port combinations to be ready. Any pointers on the best way to do this?
One way I can imagine is one wait-for-it
starting another wait-for-it
.
This is probably not a common situation, but in my case I need to wait for two independent databases to get ready before launching my app.
That would be awesome !
Hi,
I'm facing some issue when this script is probing a port to know if the service is up and running but sometimes the port is opened but the application is not yet ready.
Is it possible to add some sleep just after a successful check and running the command ?
Hi there! I wrote wait-for-it in order to help me orchestrate containers I operate at my day job. I thought it was a neat little script, so I published it. I assumed I would be its only user, but that's not what happened! wait-for-it has received more stars then all of my other public repositories put together. I had no idea this tool would solicit such an audience, and I was equally unprepared to carve out the time required to address my user's issues and patches. I would like to solicit a volunteer from the community who would be willing to be a co-maintainer of this repository. If this is something you might be interested in, please email me at [email protected]. Thanks!
It seems strange that all services are started, but cannot connect to the expose port...
But everything is ok via docker-compose
, except docker stack deploy
.
When running this script in Alpine, this error occurs:
timeout: can't execute '15': No such file or directory
BusyBox v1.24.1 (2015-12-16 08:00:02 GMT) multi-call binary.
Usage: timeout [-t SECS] [-s SIG] PROG ARGS
I am trying to run nginx startup command in the command args but failing
bash-4.3# /tmp/wait-for-fpm.sh webapp:9000 -t 100 -- nginx -g 'daemon off;'
wait-for-fpm.sh: waiting 100 seconds for webapp:9000
wait-for-fpm.sh: webapp:9000 is available after 0 seconds
nginx -g daemon off;
nginx: invalid option: "off;"
bash-4.3#
Can't find how the signgle quotes getting removed
The command should be as it is like nginx -g 'daemon off;'
not nginx -g daemon off;
we use wait-for-it.sh heavily in CI for docker integration testing in golang. Recently a job broke due to wait-for-it.sh error. I believe the issue may have to do with something changing in timeout from alpine3.9 (works) to alpine 3.10 (not working). In both cases we were installing bash with apk.
Repro (note in vi
I am copying wait-for-it from current master)
$ docker run -it --rm golang:1.12-alpine
/go # vi wait-for-it.sh
/go # chmod +x wait-for-it.sh
/go # apk update && apk add --no-cache bash
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
v3.10.1-11-g89d0862481 [http://dl-cdn.alpinelinux.org/alpine/v3.10/main]
v3.10.1-12-ga885fe876c [http://dl-cdn.alpinelinux.org/alpine/v3.10/community]
OK: 10327 distinct packages available
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/5) Installing ncurses-terminfo-base (6.1_p20190518-r0)
(2/5) Installing ncurses-terminfo (6.1_p20190518-r0)
(3/5) Installing ncurses-libs (6.1_p20190518-r0)
(4/5) Installing readline (8.0.0-r0)
(5/5) Installing bash (5.0.0-r0)
Executing bash-5.0.0-r0.post-install
Executing busybox-1.30.1-r2.trigger
OK: 15 MiB in 20 packages
/go # ./wait-for-it.sh docker:5432
timeout: unrecognized option: t
BusyBox v1.30.1 (2019-06-12 17:51:55 UTC) multi-call binary.
Usage: timeout [-s SIG] SECS PROG ARGS
Runs PROG. Sends SIG to it if it is not gone in SECS seconds.
Default SIG: TERM.
wait-for-it.sh: timeout occurred after waiting 15 seconds for docker:5432
Workaround: I was able to work around this issue by installing coreutils as well which updates timeout
(continuing from example above)
/go # apk update && apk add --no-cache coreutils
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
v3.10.1-11-g89d0862481 [http://dl-cdn.alpinelinux.org/alpine/v3.10/main]
v3.10.1-12-ga885fe876c [http://dl-cdn.alpinelinux.org/alpine/v3.10/community]
OK: 10327 distinct packages available
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/3) Installing libacl (2.2.52-r6)
(2/3) Installing libattr (2.4.48-r0)
(3/3) Installing coreutils (8.31-r0)
Executing busybox-1.30.1-r2.trigger
OK: 16 MiB in 23 packages
/go # ./wait-for-it.sh -t 15 docker:5432
wait-for-it2.sh: waiting 15 seconds for docker:5432
wait-for-it2.sh: timeout occurred after waiting 15 seconds for docker:5432
When a preffix is used before the domain or IP, like http://localhost:8080, the script recognizes the preffix as the domain so it tries to ping without the port, like:
wait-for-it.sh: waiting 10 seconds for http://localhost
wait-for-it.sh: timeout occurred after waiting 10 seconds for http://localhost
https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh leads to a 500: Internal Server Error
. This script is so useful when using in Docker containers and pipelines, would love for it to be available again instead of having to use Git to clone repo every time.
Is it possible to make this shell-independent?
/wait-for-it.sh: line 70: syntax error: unexpected "(" (expecting ";;")
This would be particularly useful to run it with alpine, which uses busybox.
Installing 'coreutils' and setting the alias to timeout for gtimeout does not work.
It is missing '--timeout' flag. So the code fails on line 56 or 58 where it specifies --timeout=$TIMEOUT.
I do not want to use PERL workaround as it won't be available on all machines. And the script needs to run on both Mac OS and linux alpine, so I can't simply change it to work with one or the other.
Trying all the examples in iTerm2 on my mac, I get the following error:
$ wait-for-it.sh www.google.com:80 -- echo "google is up"
wait-for-it.sh: line 53: timeout: command not found
wait-for-it.sh: timeout occurred after waiting 15 seconds for www.google.com:80
google is up
I've tried with variations such as using bash
and sh
and different working directories. Is this just not compatible with mac osx, El Captain?
I'm having problems with running wait-for-it.sh
with CouchBase Sync Gateway. Without wait-for-it.sh
sync-gateway
starts, with it - doesn't start.
The full description is on CouchBase forums.
I have a situation where the port is open but the application is still initializing. Can we add an option to wait for a HTTP resource to return?
I was using wait-for-it.sh for starting service from docker-compose after RabbitMq is ready.
Though wait-for-it.sh was overriding my $HOST and $PORT variables that the service was dependent on.
I customized script a little bit to dump env variables and then return them back when executing commands after --
I suggest to add this to script or if needed I can open a PR for
as it was relatively hard to debug
If using windows operating system this may cause a problem.
Desite supplying a command with host and port as below:
When using command in docker-compose
command: ["/wait-for-it.sh", "myservice:4444", "npm", "test"]
error
"Error: you need to provide a host and port to test."
Solution, download file manually by clicking 'raw' on github and downloading it.
Sometimes it is needed to not just reach the endpoint, but verify that something is responding normally there. My specific use case was that I had an nginx
server on which I was testing the endpoints "successfully", but they were returning 502 Bad Gateway
errors because the server that it was proxying was not yet up.
Can add an option to use curl
or wget
to do this.
It would be ideal if multiple services (i.e. multiple host:port combinations) could be declared such that the command is executed only after all dependent services are available.
After updating my image to Alpine 3.7 i have noticed that wait-for-it hangs after success of finding host.
In order to use it with Docker and docker-compose,
place it alongside Dockerfile
, build it into the image with exec permissions and reference it in docker-compose.yml
.
- Dockerfile
- wait-for-it.sh
#Dockerfile
...
COPY wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh
...
#docker-compose.yml
...
my-service:
build:
context: "."
container_name: my_container
command: ["/wait-for-it.sh", "mysql:3306", "--", [entrypoint function]]
...
Hello @douglas-gibbons!
Could you enable Travis?
https://travis-ci.org/github/vishnubob/wait-for-it
or
https://travis-ci.com/github/vishnubob/wait-for-it (modern)
I have a scenario where I want to start a server within a container and then, once it's up and running, hit it with a curl command to further configure it. Does anyone have an example of something like this?
echo sends a newline character which causes some server software to report an error message about an invalid HTTP request. By adding the '-n' flag the echo command can be used to open the port without sending anything.
I've created a pull request to fix this: #86
I have a Dockerfile which basis is
FROM jboss/keycloak-mysql:3.3.0.Final
Exposing the port 8080.
The wildfly comes up pretty fast, in xx seconds, the keycloak.war takes yy minutes to deploy.
My next service is relying that the keycloak war is up and running with its realms.
Using wait-for-it.sh gives clerance after xx seconds while I would want to wait for yy minutes.
The last rows in Dockerfile relying on keycloak looks lik this ( where 'sso' is my keycloak-service)
ENTRYPOINT ["/sbin/tini", "--", "/wait-for-it.sh", "sso:8080", "-t", "300", "--"]
CMD ["java", "-jar", "accounts-api-swarm.jar", "-Sinitdata" ]
So 'sso' always starts to early, the keycloak realms have not been created.
What I would like to do is to have an enhancement that works like this
ENTRYPOINT ["/sbin/tini", "--", "/wait-for-it.sh", "sso:8080/auth/realms/master/", "-t", "300", "--"]
so "sso:8080/auth/realms/master/ gives me http_status = 200 - Then and only then would like to start the java -jar accounts-api-swarm.jar Sinitdata
....
Some thoughts are here in this small repo :
https://github.com/Inkimar/wait-for
-Ingimar
The script contaminates the environment, clobbering the PORT
env-var, among others. These are not-uncommon names to use when setting up services in a container.
It might be wise for the script to namespace its env-vars, like WAITFORIT_PORT
The version where it doesn't work: GNU bash, version 4.4.23(1)-release (x86_64-apple-darwin17.5.0)
. After each command it shows:
readlink: illegal option -- f
The version where it works: GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
It would be nice if --timeout=-1 would wait forever until the port is available.
It would be great if we could just install this from something like apt-get.
I would like to do the following steps:
sudo apt-get install wait-for-it
wait-for-it www.google.com:80 -- echo "google is up"
I was using wait-for-it on a debian docker container, and all things were great (thanks for the script!).
However, we switched to an Alpine Linux based docker image (which uses busybox) and the script stopped waiting correctly.
As it turns out timeout
requires an argument flag for the time. Here's the manual from https://busybox.net/downloads/BusyBox.html
timeout
timeout [-t SECS] [-s SIG] PROG [ARGS]
Runs PROG. Sends SIG to it if it is not gone in SECS seconds. Defaults: SECS: 10, SIG: TERM.
This differs from typical linux usage:
timeout [OPTION] DURATION COMMAND [ARG]...
Changing lines 52 and 54 where timeout
is used by prepending -t
before the $TIMEOUT
causes it to work.
Here's the working result:
wait_for_wrapper()
{
# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
if [[ $QUIET -eq 1 ]]; then
timeout -t $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
else
timeout -t $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT &
fi
PID=$!
trap "kill -INT -$PID" INT
wait $PID
RESULT=$?
if [[ $RESULT -ne 0 ]]; then
echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"
fi
return $RESULT
}
I did a quick search for a simple method to determine if busybox is being used, not sure what the best solution would be. Worst case - this post may help others in a similar situation.
ERROR: for api Cannot start service api: oci runtime error: container_linux.go:247: starting container process caused "exec: "./wait-for-postgres.sh": permission denied"
ERROR: Encountered errors while bringing up the project.
Hi,
I noticed some abnormal behavior and i need some tips if you can help me, when i run my compose file and let docker manage the networks the containers start and wait for their respectively dependencies and being available in the ports i specified but when i specify for each container network: bridge and run the compose i get this weird behavior that the container starts but never runs the init script i define it to run. in the logs it nevers shows the wait-for-it script picking up the container it was waiting for it to be live,
Any help on how to fix this
Thanks
Hi guy, when I run this script in OSX, everything will be ok. But when I deploy docker on cloud with CentOS 7, this error is shown.
timeout: can't execute '15': No such file or directory
Please help me this problem.
Since this script is a bash script and running it under POSIX sh will fail, it is technically incorrect for it to be named .sh
.
In busybox commit c9720a761, a breaking change was introduced that
removes the -t
flag to timeout
in favor of just taking the time as
the second arg, bringing it in line with coreutils' timeout
. This
commit was included in tag 1.31.1, released on 25 Oct, 2019, at
which point my integration tests that spin up a server using wait-for-it
started to fail.
I am going to upload wait-for-it to Debian and It would help me keep up with development if the repository was tagged. Are you able to do that please?
OSX bash shell doesn't have a timeout command, but often (at least dev OSX machines) will have perl. Can do:
function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
i suggest wait-for-it support multiple condition
example:
./wait-for-it.sh mysql:3306 redis:6379
on centos5, timeout command not found.
how to fix it?
line 75: syntax error: unexpected "(" (expecting ";;")
P.S: Script running via /bin/sh
/wait-for-it.sh: 75: /wait-for-it.sh: Syntax error: "(" unexpected (expecting ";;")
error when trying to build with a openjdk:8-jre image
In my use case:
web:
build: .
command: ./wait-for-it.sh mongo:27017 -t 0 -- nodemon server.js
restart: always
environment:
- PORT=8096
volumes:
- .:/code
ports:
- "8096:8096"
links:
- mongo
mongo:
image: 'mongo:3.2.1'
ports:
- '27017:27017'
volumes:
- './data/db:/data/db'
I have environment variable named PORT which will be overridden by mongo's port when running wait-for-it bash.
My solution is to change PORT variable in bash to _PORT to make it looks more private.
Debian tracker reports three issues. The one with higher importance is:
The package is severely out of date with respect to the Debian Policy. The package should be updated to follow the last version of Debian Policy (Standards-Version 4.5.0 instead of 3.9.7).
Apparently #3 could be closed.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.