11

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?

AdrienW
  • 3,092
  • 6
  • 29
  • 59
  • 1
    Some tips might be found at http://mywiki.wooledge.org/BashFAQ/050 – Eric Renouf May 07 '18 at 12:52
  • @EricRenouf Thanks! I already stumbled upon this in my research but could not seem to find a paragraph that does apply to my case... Do you see one that fits? (3rd section maybe but I don't quite understand it) – AdrienW May 07 '18 at 12:55
  • 1
    Have you considered the initial part of just storing the arguments in an array instead of a string? Also, is it possible either `COLUMNS` or `LINES` contains an unexpected newline or something like that? perhaps those should be quoted as well? – Eric Renouf May 07 '18 at 12:58
  • I've tried replacing `COLUMNS` and `LINES` with hardcoded values but it did not help. Which part would you write as an array? If I take the command and execute it directly in the terminal, it works, that's what I don't get – AdrienW May 07 '18 at 13:06

1 Answers1

9

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
Arount
  • 9,853
  • 1
  • 30
  • 43
  • I think I understand. But there is still something bothering me: with this solution, I have to hard-code the variables: `foo='winpty docker exec -it 0b63a bash -c "stty cols 255 rows 59 && bash -l"'` in my case. Do you know a pretty way to use the variables inside the command? I could eval them after one another then glue the whole thing but it doesn't feel right – AdrienW May 07 '18 at 13:31
  • 1
    Yes, let me fix my answer – Arount May 07 '18 at 13:39