2

Have a situation where docker run .... is "wrapping" an unknown number of potential arguments so we can't use a function. If you're curious: https://github.com/dbt-labs/dbt-core/tree/main/docker#running-an-image-in-a-container

So I want to alias the docker run .... part of the docker run..... {real command} command.

alias my_command="docker run -e PASS='mypass' --some-setting"

'mypass' needs to be in single quotes.

With the above alias, alias my_command yields

alias mycommand='docker run -e PASS='\''mypass'\'' --some-setting'

And this doesn't execute the right command. Specifically we get a permission denied. Running the exact same command straight, without the alias, works:

docker run -e PASS='mypass' --some-setting
Jesse
  • 3,243
  • 1
  • 22
  • 29
sam
  • 653
  • 9
  • 21
  • 5
    Use a function instead , `my_command() { docker run -e PASS='mypass' --some-setting "$@"; }` Enjoy... – Jetchisel Jan 10 '23 at 00:52
  • Ahhh, sweet. Didn't know about `"$@"`. Thought we had to do `$1`, `$2`, .... Thanks! – sam Jan 10 '23 at 01:05
  • 1
    It will expand to all the positional parameter, at least whats left of it to expand. – Jetchisel Jan 10 '23 at 01:09
  • See `PAGER='less +/^\ *@' man bash` – Jetchisel Jan 10 '23 at 01:21
  • 2
    The output from `alias my_command` looks weird, but it's actually correct (at least, the part you gave looks correct). That weird `'\''` thing is one way to put a single-quote in a mostly-single-quoted string (which is how it's displaying the alias). See Nick Jensen's answer [here](https://stackoverflow.com/questions/8254120/how-to-escape-a-single-quote-in-single-quote-string-in-bash/48352047#48352047). Is there something in the password itself that's wrong in the `alias my_command` output, or is it just the weird-looking quoting? – Gordon Davisson Jan 10 '23 at 02:50
  • share us the exact permission denied error log – JRichardsz Jan 13 '23 at 15:46
  • If you want to see how your command is _actually being run_ to compare the aliased and not-aliased cases, use `set -x; my_command; set +x` and compare to `set -x; docker run -e PASS='mypass' --some-setting`. Adding the results of that comparison to the question would be helpful if you want folks to be able to explain why the old code was misbehaving, as opposed to just giving you instructions on how to avoid the problem (which is a place where using a function instead of an alias is very much the Right Thing). – Charles Duffy Apr 10 '23 at 16:33

1 Answers1

1

Quotes (' or ") and escape characters (\) are not part of a value; they solely instruct your shell to not perform any word splitting or parameter expansion.

Thus, if you have a command containing -e PASS='my pass', you could (re)write the command with the following equivalent forms – your shell won't care and your invoked binary cannot even find out which form was used:

  • -e 'PASS=my pass'
  • -e PASS=my' 'pass
  • -e PASS=my\ pass
  • -e 'PASS'="my pass"
  • '-e' "PASS"='my'\ "pass"

(yes, all of those are equivalent; identical even, after the shell has parsed them).

Consequently, you cannot use alias if your command is more complicated than the simplest and most trivial commands. Anything more complex (multi-word tokens, quotes, etc.) and you are better off defining a shell function to invoke the command for you. Shell functions have precedence over binaries so you can give them the name of an existing binary and your function would be invoked.

mycommand() {
  docker run -e 'PASS=my pass' --some-setting "$@";
}

"$@" expands to all positional parameters, but preserves the word-splitting of the original parameters. Invoke this shell function as follows:

mycommand --flag --option-with-value='value with spaces'
knittl
  • 246,190
  • 53
  • 318
  • 364