tail -f /dev/null is a command that runs endlessly and doesn't use any CPU because nothing can be read from /dev/null and we are asking for an endless read from it.
How can we make it easier? In this situation, you can add tail -f /dev/null to your command. By doing this, even if your main command runs in the background, your container doesn't stop because tail is keep running in the foreground.
Dockerfile Command to Keep the Container Running Method 1: You can use the -t (pseudo-tty) docker parameter to keep the container running. Method 2: You can run the container directly passing the tail command via arguments as shown below. Method 3: Another method is to execute a sleep command to infinity.
docker exec -it 5f4 sh / # (<-- you can run linux command here!) type exit to come out- You can run it in detached mode and it will keep running. You will need to STOP otherwise it will keep running. Show activity on this post.
Here is better way to keep the container running
sleep infinity
To answer your question under what circumstances tail -f /dev/null
might finish and therefore continue to the next line in something like a shell script:
/dev/null
(as with everything in Linux) is a file. When executing tail
onto any file, the file must be opened using a filedescriptor. It's not that tail -f /dev/null
terminates because it's finished (it won't ever finish), it terminates because of interference with the filedescriptor which can happen due to a number of reasons, however, inside the container itself there is (most likely) nothing else happening that would interfere with the filedescriptor.
Since docker containers are just a somewhat fancy overlay of so called Linux namespaces all the processes that run inside a container (even if it is inside a separate PID namespace) actually run on your host. So for some reason your host is interfering with your filedescriptor.
To check for open filedescriptors created by a process you can execute the following command:
$ sudo ls -la /proc/<pid>/fd
You will see certain numbers in the output:
0
stands for standard input.1
stands for standard output.2
stands for standard error.The rest are files that are being opened by the process.
<pid>
is the id of the process you want to look at. When running tail -f /dev/null
as the entrypoint inside a container it is most likely going to have the pid 1
inside the container. In order to find the pid on your host machine you can simply grep for it like so:
$ sudo ps aux | grep 'tail -f /dev/null'
To close the filedescriptor yourself and manually reproduce what would happen in those cases you can use the GNU debugger gdb
.
Simply attach the debugger to the pid you found earlier:
$ sudo gdb attach <pid>
Now you can go ahead and choose which filedescriptor you want to close (most likely it is going to be number 3
since the process does not open any other files):
(gdb) call (int)close(3)
$1 = 0
Now check the logs of your container while leaving the debugger:
(gdb) quit
Depending on your configuration you are likely to see an error coming from tail
in the container logs:
tail: error reading '/dev/null': Bad file descriptor
As explained earlier, there is also a filedescriptor for standard error (2
).
You can repeat the entire process and close both the standard error and the actual filedescriptor during the same debugger session:
(gdb) call (int)close(2)
$1 = 0
(gdb) call (int)close(3)
$2 = 0
(gdb) quit
Upon doing so there won't be an error visible in the container logs and in case of a bash script it is going to proceed with the next line.
As to check what exactly is interfering with your filedescriptor you would have to extensively monitor your host system during the moment of the occurrence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With