Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Executing 'bash -c' in 'docker exec' command

Context: I'm trying to write a shortcut for my daily use of the docker exec command. For some reasons, I'm experimenting the problem that my output is sometimes broken when I'm using a bash console inside a container (history messed up, lines overwrite each other as I'm writing, ...)

I read here that you could overcome this problem by adding some command before starting the bash console.


Here is a relevant excerpt of what my script does

#!/bin/bash
containerHash=$1
commandToRun='bash -c "stty cols $COLUMNS rows $LINES && bash -l"'

finalCommand="winpty docker exec -it $containerHash $commandToRun"
echo $finalCommand
$finalCommand

Here is the output I get:

winpty docker exec -it 0b63a bash -c "stty cols $COLUMNS rows $LINES && bash -l"
cols: -c: line 0: unexpected EOF while looking for matching `"'
cols: -c: line 1: syntax error: unexpected end of file

I read here that this had to do with parsing and expansion. However, I can't use a function or an eval command (or at least I didn't succeed in making it work).

If I execute the first output line directly in my terminal, it works without trouble.

How can I overcome this problem?

like image 673
AdrienW Avatar asked May 07 '18 12:05

AdrienW


People also ask

What does exec command do in docker?

The docker exec command runs a new command in a running container. The command started using docker exec only runs while the container's primary process ( PID 1 ) is running, and it is not restarted if the container is restarted. COMMAND will run in the default directory of the container.

Which command can exec commands inside docker container?

Method 1: Using Bash You can directly access the bash of the Docker Container and execute commands there. It's very easy to launch the bash of the Container and you can do so using this command.

How do I start bash in a container?

In order to start a Bash shell in a Docker container, execute the “docker exec” command with the “-it” option and specify the container ID as well as the path to the bash shell. If the Bash is part of your PATH, you can simply type “bash” and have a Bash terminal in your container.

How do I run a bash command in a docker container?

Use the command docker exec -it <container name> /bin/bash to get a bash shell in the container. Or directly use docker exec -it <container name> <command> to execute whatever command you specify in the container.


1 Answers

It's not Docker related, but Bash (In other words, the docker's part of the command works well, it's just bash grumbling on the container like it would grumble on your host):

Minimal reproducible error

cmd='bash -c "echo hello"'
$cmd

hello": -c: line 0: unexpected EOF while looking for matching `"'
hello": -c: line 1: syntax error: unexpected end of file

Fix

cmd='bash -c "echo hello"'
eval $cmd

hello

Answer

foo='docker exec -it XXX bash -c "echo hello"'
eval $foo

This will let you execute your command echo hello on your container, now if you want to add dynamic variables to this command (like echo $string) you just have to get rid of single quotes for double ones, to make this works you will have to escape inner double quotes:

foo="docker exec -it $container bash -c \"echo $variable\""

A complete example

FOO="Hello"
container=$1
bar=$2

cmd="bash -c \"echo $FOO, $bar\""
final_cmd="docker exec -it $container $cmd"

echo "running command: \"$final_cmd\""
eval $final_cmd

Let's take time to dig in,

  • $FOO is a static variable, in our case it works exactly like a regular variable, just to show you.
  • $bar is a dynamic variable which takes second command line argument as value
  • Because $cmd and $final_cmd uses only double quotes, variables are interpreted
  • Because we use eval $final_cmd command is well interpreted, bash is happy.

Finally, a usage example:

bash /tmp/dockerize.sh 5b02ab015730 world

Gives

running command: "docker exec -it 5b02ab015730 bash -c "echo Hello, world""
Hello, world
like image 90
Arount Avatar answered Sep 18 '22 12:09

Arount