-1

I am attempting to automate the following series of commands which work correctly into a BASH script:

kubectl exec -it mongo-pod -- bash
mongo DBNAME
db.auth("theUser", "thePw")
db.theCollection.find()

The script I am using is as follows:

#!/bin/bash

kubectl exec -it mongo-pod -- bash -c "mongo DBNAME && /
db.auth("theUser", "thePw") && /
db.theCollection.find()"

I have tried the following: Executing multiple commands( or from a shell script) in a kubernetes pod but any commands that are added after the first using & or && are not executed. For example just using "mongo DBNAME" correctly opens the prompt and sets it to the correct db, but adding any other command with && causes all commands to fail with the following:

bash: -c line 0: syntax error near unexpected token 'theUser'

  • 1
    Are `db.auth(...` and `db.theCollection...` commands, mongo commands? As your script is written they are being executed by bash after successful exit of the previous command ( thats what `&&` does) – Will Barnwell Aug 21 '18 at 22:36
  • Yes, those are mongo commands, see this question https://stackoverflow.com/questions/4837673/how-to-execute-mongo-commands-through-shell-scripts – Will Barnwell Aug 21 '18 at 22:38
  • I'd invoke mongo shell directly `kubectl exec -it mongo-pod -- mongo ""` then see [here](https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/) – stacksonstacks Aug 21 '18 at 23:07
  • @Will Barnwell I looked at the solutions in https://stackoverflow.com/questions/4837673/how-to-execute-mongo-commands-through-shell-scripts but was not able to get any of these solutions to work in conjunction with "kubectl exec -it mongo-pod -- bash -c " past the first command. – JabberwokyStrollin Aug 22 '18 at 00:29
  • @stacksonstacks When I use "kubectl exec -it mongo-pod -- mongo" I connect to mongodb in the pod (similar to when I use the -- bash option) but I am not sure where to go from there based on the MongoDB manual scripting description you linked too. Specifically, I am already connected to the db, but don't have a javascript variable db to perform commands on without reconnecting via some thing like the new Mongo().getDB("theDB"). – JabberwokyStrollin Aug 22 '18 at 00:51

1 Answers1

0

All of the comments are spot on, but at least two things I have the highest confidence I have the answer to:

First, you have the line continuation character wrong; it should be \ and not /. It actually wouldn't even be required if you switched bash into "exit on error" mode, with

kubectl exec -it mongo-pod -- bash -ec "mongo DBNAME
echo 'this command only runs if mongo exits a-ok'
exit 1
and this never will run
"

However, the other mistake is around the quoting characters used: if you have bash -c " then you must either use the single-quote for the interior string literals, or escape them with \". You can actually see what I'm talking about by looking at the syntax highlighting of the shell snippet in your question. Observe that the string literal is red, but then the text theUser as well as thePw are both black -- that's because they are outside the string literal since the string stopped at the first " it encountered -- the one present in db.auth("

It is almost always the case that you'll want to use single quotes when invoking bash remotely like that, for several reasons but the most relevant is that you can then use db.auth("something") without having to unnecessarily escape the double quotes.

Since mongo (like many interpreters such a node and python) wants you to either type in it interactively, provide the input on its "standard input", or give it a local file containing commands, you will want to change the invocation to one of those strategies depending on your needs.

A very convenient way of redirecting standard input without having to use echo or printf and its associated quoting hell is to use what are called "here documents" (abbreviated "heredocs") in bash:

kubectl exec -it mongo-pod -- bash -ec 'mongo DBNAME<<"FOO"
db.auth("theUser", "thePw")
printjson(db.theCollection.find())
FOO
'

That causes bash to transmit almost all characters between the two "heredoc delimiters" to the standard input of the command. If you quote the delimiter, as I have with the [arbitrary] word FOO, then the contents are not subject to variable expansion, command interpolation, etc, which can be one more mechanism to avoid backtick and dollarsign weirdness.

mdaniel
  • 31,240
  • 5
  • 55
  • 58
  • The last half of your answer is confusing, im not sure why you included the command expansion stuff. OP is not trying to use command expansion, and heredocs are not a solution to improper command expansion. That being said, heredocs are a neat solution to OP's challenge. This answer would be great if you removed the command expansion stuff and instead explained why the heredoc is solving the problem of sending multiple commands to mongo's interactive shell – Will Barnwell Aug 22 '18 at 19:11