pc70
pc70

Reputation: 701

docker exec command doesn't return after completing execution

I started a docker container based on an image which has a file "run.sh" in it. Within a shell script, i use docker exec as shown below

docker exec <container-id> sh /test.sh

test.sh completes execution but docker exec does not return until i press ctrl+C. As a result, my shell script never ends. Any pointers to what might be causing this.

Upvotes: 6

Views: 5518

Answers (5)

Panos Vagenas
Panos Vagenas

Reputation: 46

As described here, this "hanging" behavior occurs when you have processes that keep stdout or stderr open.

To prevent this from happening, each long-running process should:

  1. be executed in the background, and
  2. close both stdout and stderr or redirect them to files or /dev/null.

I would therefore make sure that any processes already running in the container, as well as the script passed to docker exec, conform to the above.

Upvotes: 1

donniexu
donniexu

Reputation: 1

My case is a script a.sh with content
like

php test.php &

if I execute it like

docker exec contianer1 a.sh

It also never returned.

After half a day googling and trying
changed a.sh to

php test.php >/tmp/test.log 2>&1 &

It works!

So it seems related with stdin/out/err.

>/tmp/test.log 2>&1

Please try.

And please note that my test.php is a dead loop script that monitors a specified process, if the process is down, it will restart it. So test.php will never exit.

Upvotes: 0

silva
silva

Reputation: 482

OK, I got it.

docker stop a590382c2943

docker start a590382c2943

then will be ok.

docker exec -ti a590382c2943 echo "5"

will return immediately, while add -it or not, no use

actually, in my program, the deamon has the std input and std output, std err. so I change my python deamon like following, things work like a charm:

if __name__ == '__main__':
    # do the UNIX double-fork magic, see Stevens' "Advanced
    # Programming in the UNIX Environment" for details (ISBN 0201563177)

    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            os._exit(0)
    except OSError, e:
        print "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
        os._exit(0)
    # decouple from parent environment
    #os.chdir("/")
    os.setsid()
    os.umask(0)
    #std in out err, redirect
    si = file('/dev/null', 'r')
    so = file('/dev/null', 'a+')
    se = file('/dev/null', 'a+', 0)
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())
    # do second fork
    while(True):
        try:
            pid = os.fork()
            if pid == 0:
                serve()
            if pid > 0:
                print "Server PID %d, Daemon PID: %d" % (pid, os.getpid())
                os.wait()
                time.sleep(3)
        except OSError, e:
            #print "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
            os._exit(0)

Upvotes: 0

Matthias Lohr
Matthias Lohr

Reputation: 1856

I could get it working with adding the -it parameters:

docker exec -it <container-id> sh /test.sh

Upvotes: 4

ArgonQQ
ArgonQQ

Reputation: 1997

Mine works like a charm with this command. Maybe you only forgot the path to the binary (/bin/sh)?

docker exec 7bd877d15c9b /bin/bash /test.sh

File location at

/test.sh

File Content:

#!/bin/bash
echo "Hi"
echo
echo "This works fine"
sleep 5
echo "5"

Output:

ArgonQQ@Terminal ~  docker exec 7bd877d15c9b /bin/bash /test.sh
Hi

This works fine
5
ArgonQQ@Terminal ~ 

Upvotes: 0

Related Questions