Compose: strange exit status code behavior

Created on 26 Apr 2016  ·  19Comments  ·  Source: docker/compose

Depending wether I use docker-compose run with or without --rm, the exit status code is ignored.
Using docker-compose exec returns me a exit status code 129, while the same command with docker exec returns the correct status code.

I tried to understand what's happening under the hood, but I can't make sense of it, so I'll paste my results here.

 % $(docker exec qspot_php_1 php -r"exit(2);"); echo $?
2
 % $(docker-compose exec php php -r"exit(2);"); echo $?
129
 % $(docker-compose exec php sh -c "exit 2;"); echo $?
2
 % $(docker-compose run php php -r"exit(2);"); echo $? 
0
 % $(docker-compose run --rm php php -r"exit(2);"); echo $?
2

As you can see, there are quite a few differences :)
Is it a normal behavior?
What command should I use if I care about the exit status code?

PS: I'd like to be able to use the docker-compose exec version.

PPS: my versions:

 % docker-compose version
docker-compose version 1.7.0, build 0d7bf73
docker-py version: 1.8.0
CPython version: 3.5.1
OpenSSL version: OpenSSL 1.0.2g  1 Mar 2016

 % docker version
Client:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Sat Mar 12 19:18:57 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.11.0
 API version:  1.23
 Go version:   go1.5.4
 Git commit:   4dc5990
 Built:        Wed Apr 13 19:36:04 2016
 OS/Arch:      linux/amd64
arecli kinbug

Most helpful comment

I'm confirming docker-compose exec -T ... is solving (exactly) the same issue. Thanks @mauricioprado00

All 19 comments

Oh, I forgot a last result, which is interesting, as it seems that the php command behaves differently sometimes, compared to sh.

 % $(docker-compose exec php sh -c "exit 2;"); echo $?
2

Not even sure it has anything to do with https://github.com/docker/docker/issues/18948 since i haven't apparmor installed AFAIK.

The only workaround I found is to wrap it in sh -c:

 docker-compose exec php sh -c 'php -r"exit(2);"'
 # returns 2

@docteurklein I have exactly the same issue... did you fixed that since? I experiment that on docker and it seems to also depend on the docker version I use. Eg releases > 1.10.3 are broken and will return a 129 exit code.

@shouze the only workaround I found is to wrap it in sh -c, as stated above.

Been running into this as well on 1.11.2:

Works sometimes, or randomly exists with 129:

docker exec -it "my_container" bash -c "rm -rf /somefolder/*"

Works all the time:

docker exec -it "my_container" sh -c "rm -rf /somefolder/*"
m@localhost:~/gaps$ docker exec -ti gaps_pgsql_1 mkdir /tmp/dbmigration-scripts
m@localhost:~/gaps$ docker exec -ti gaps_pgsql_1 rm -Rf /tmp/dbmigration-scripts
m@localhost:~/gaps$ echo $?
129

but if I remove the allocation of the pseudo-TTY (-t parameter), it does work:

m@localhost:~/gaps$ docker exec -i gaps_pgsql_1 mkdir /tmp/dbmigration-scripts
m@localhost:~/gaps$ docker exec -i gaps_pgsql_1 rm -Rf /tmp/dbmigration-scripts
m@localhost:~/gaps$ echo $?
0

I think it's a better workaround for the issue than running sh -c, and hopefully brings some enlightenment to docker developers about the issue.

I'm confirming docker-compose exec -T ... is solving (exactly) the same issue. Thanks @mauricioprado00

I was running a PHP script with --tty and getting the 129 exit code (which was causing Travis CI builds to fail since it was non-0 — see https://travis-ci.org/geerlingguy/ansible-role-php-memcached/jobs/160060263#L753). Removing --tty from the docker exec call fixed it for me, and the PHP script exit code is passed through correctly (see https://travis-ci.org/geerlingguy/ansible-role-php-memcached/jobs/160061878#L753).

sure, but tty allocation brings colors to the output usually (that's what is used to detect if ran interactively or not.)

I found a workaround that addresses the issue without switching to sh or removing -t (either of which were not a viable option).

Add ; (exit $?) at the end of a command you are trying to execute with docker exec -it.

Example with docker

$ docker exec -it <container_name> bash -c 'php -r"exit(7);"; (exit $?)'
$ echo $?
7

The same applies to docker-compose

$ docker-compose exec <service_name> bash -c 'php -r "exit(7);"; (exit $?)'
$ echo $?
7

Credits: https://github.com/docksal/docksal/commit/34d1bb094e8f7c8265672f8b46bfa4035fee574f

Possibly related: I am getting an exit code of 129 even when all goes well:

for example:

docker-compose exec drupal8 /bin/bash -c 'drush en -y my_migration'
echo $?
# 129
docker exec "$(docker-compose ps -q drupal8)" /bin/bash -c 'drush en -y my_migration'
echo $?
# 0

This happens only when I call these from a script, not directly.

I am using the latest version of Docker and Docker compose for Mac OS X.

@alberto56 yes, if you read the thread you will find that myovchev already provided a solution for docker-compose https://github.com/docker/compose/issues/3379#issuecomment-244509753

For what it is worth I worked around the rm -rf inconsistent exit code issue with this:

set +e
docker exec -t <container> [ -d /my/dir ] && rm -rf /my/dir
set -e

Not pretty but it worked. I'll try setting -i instead of -t approach that @mauricioprado00 mentioned and the -T for docker-compose exec approach @myovchev mentioned and see if that solves it too.

I don't think this is a docker-compose problemo directly:

[development@localhost ~/project-o] docker exec -it megaprojecto-php-fpm php foo.php 
FO⏎                                                                                                                                                                      
[development@localhost ~/project-o] [129] echo $status
129
[development@localhost ~/project-o] docker-compose exec php-fpm php foo.php 
FO⏎                                                                                                                                                                      
[development@localhost ~/project-o] [129] echo $status
129
[development@localhost ~/project-o] php foo.php 
FO⏎                                                                                                                                                                      
[development@localhost ~/project-o] echo $status
0
[development@localhost ~/project-o] cat foo.php
<?php
echo "FO";

I also think it's not related to docker-compose at all. (IDK why I opened this issue here).

My guess is that it's related to the runtime executor directly, possibly related to the default apparmor profile.

Hi everyone,

Please note that docker-compose allocates a TTY by default for run / exec operations, whereas docker does not. As such, to obtain the equivalent behavior with compose as in docker, one should use the -T flag.

With that in mind, I don't believe this is a Compose issue (please correct me if I'm mistaken there), and I would recommend opening an issue on the moby/moby tracker instead.

This is still hapenning to me :(

rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], 0x7ffd99414f90, {tv_sec=1, tv_nsec=0}, 8) = -1 EAGAIN (Resource temporarily unavailable)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2226, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2226
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2233, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2232
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2233
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2232, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2238, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2237
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2238
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2237, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2242, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2242
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2249, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2249
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2248
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2248, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2253, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2253
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], 0x7ffd99414f90, {tv_sec=1, tv_nsec=0}, 8) = -1 EAGAIN (Resource temporarily unavailable)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], 0x7ffd99414f90, {tv_sec=1, tv_nsec=0}, 8) = -1 EAGAIN (Resource temporarily unavailable)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2260, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2260
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2267, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2267
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2046, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2273
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2046
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2273, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2285, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2285
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2286
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = 0
rt_sigtimedwait(~[ILL TRAP ABRT BUS FPE SEGV TTIN TTOU SYS RTMIN RT_1], {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=35, si_uid=0, si_status=0, si_utime=0, si_stime=0}, {tv_sec=1, tv_nsec=0}, 8) = 17 (SIGCHLD)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGHUP}], WNOHANG, NULL) = 6
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 35
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 640
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 641
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 643
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 644
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 645
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 650
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 944
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 1035
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 1036
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2290
wait4(-1, 0x7ffd99414fec, WNOHANG, NULL) = -1 ECHILD (No child processes)
exit_group(129)                         = ?
+++ exited with 129 +++
Was this page helpful?
0 / 5 - 0 ratings