Pass shell variable to mongodb script - mongodb

I am using jenkins and mongodb on centos 7 server.
I want to insert some jenkins build data on success to my mongo database.
this is the code i'm running in my post build task shell:
echo 'password' | su -
mongo jenkinsdb <<\EOF
db.history.insert({wokspace:$WORKSPACE,remote_url:$GIT_URL,branch:$GIT_BRANCH,type:"back",date:$(date
'+%Y-%m-%d %H:%M:%S'),description:$short_description})
db.history.find()
EOF
The problem is mongo is interpreting the Jenkins environnement variables as in simple strings.
How can i pass those variables to the mongo script ?

You are preventing the variable interpolation by using \ before EOF. See https://tldp.org/LDP/abs/html/here-docs.html:
Quoting or escaping the "limit string" at the head of a here document disables parameter substitution within its body. The reason for this is that quoting/escaping the limit string effectively escapes the $, `, and \ special characters, and causes them to be interpreted literally.
serene% a=1
serene% cat <<T
heredoc> $a
heredoc> T
1
serene% cat <<\T
heredoc> $a
heredoc> T
$a
Remove the backslash if you want interpolation to happen.

Related

How can I concatenate a variable and string without spaces in powershell

I'm importing some values from a csv file and using them to create a adb command for an Android intent with the following code.
Write-Host adb shell am start -a android.intent.action.VIEW '-d' '"https://api.whatsapp.com/send?phone=' $($c.number)'"'
This gives me an out put of:
adb shell am start -a android.intent.action.VIEW -d "https://api.whatsapp.com/send?phone= 12345678 "
How can I remove the spaces where the variable is concatenated to the string to give the output of:
adb shell am start -a android.intent.action.VIEW -d "https://api.whatsapp.com/send?phone=12345678"
Use string interpolation by switching to double quotes:
Write-Host adb shell am start -a android.intent.action.VIEW '-d' "`"https://api.whatsapp.com/send?phone=$($c.number)`""
Within double quotes, you have to backtick-escape double quotes to output them literally.
zett42's helpful answer is unquestionably the best solution to your problem.
As for what you tried:
Write-Host ... '"https://api.whatsapp.com/send?phone=' $($c.number)'"'
The fact that there is a space before $($c.number) implies that you're passing at least two arguments.
However, due to PowerShell's argument-mode parsing quirks, you're passing three, because the '"' string that directly follows $($c.number) too becomes its own argument.
See this answer for more information.
Therefore, compound string arguments (composed of a mix of quoted and unquoted / differently quoted tokens) are best avoided in PowerShell.
Therefore:
Either: Use a single, expandable (double-quoted) string ("..."), as in zett42's answer.
Or: Use an expression enclosed in (...) and use string concatenation with the + operator, as shown below.
Write-Host ... ('"https://api.whatsapp.com/send?phone=' + $c.number + '"')

Replace specials characters with sed

I am trying to use a sed command to replace specials characters in my file.
The characters are %> to replace by ].
I'am using sed -r s/\%>\/\]\/g but i have this error bash: /]/g: No such file or directory, looks like sed doesn't like it.
Put your sed code inside quotes and also add the file-path you want to work with and finally don't escape the sed delimiters.
$ echo '%>' | sed 's/%>/]/g'
]
ie,
sed 's/%>/]/g' file
To complement Avinash Raj's correct and helpful answer:
Since you were using an overall unquoted string (neither single- nor double-quoted), you were on the right track by \-escaping individual characters in your sed command.
However, you neglected to \-quote >, which is what caused your problem:
> is one of the shell's so-called metacharacters
Metacharacters have special meaning and separate words
Thus, s/\%>\/\]\/g is mistakenly split into 2 arguments by >:
s/\% is passed to sed - as s/%, because the shell removes the \ instances (a process called quote removal).
As you can see, this is not a valid sed command, but that doesn't even come into play - see below.
>\/\]\/g is interpreted by the shell (bash), because it starts with output-redirection operator >; after quote removal, the shell sees >/]/g, tries to open file /]/g for writing, and fails, because your system doesn't have a subdirectory named ] in its root directory.
bash tries to open an output file specified by a redirection before running the command and, if it fails to open the file, does not run the command - which is what happened here:
bash complained about the nonexistent target directory and aborted processing of the command - sed was never even invoked.
Upshot:
In a string that is neither enclosed in single nor in double-quotes, you must \-quote:
all metacharacters: | & ; ( ) < > space tab
additionally, to prevent accidental pathname expansion (globbing): * ? [
Also note that if you need to quote (escape) characters for sed,you need to add an extra layer of quoting; for instance to instruct sed to use a literal . in the regex, you must pass \\. - two backslashes - so that sed sees the properly escaped \..
Given the above, it is much simpler to (habitually) use single quotes around your sed command, because it ensures that the string is passed as is to sed.
Let's compare a working version of your command to the one from Avinash Raj's answer (leaving out the -r for brevity):
sed s/\%\>\/\]\/g # ok - all metachars. \-quoted, others are, but needn't be quoted
sed s/%\>/]/g # ok - minimum \-quoting
sed 's/%>/]/g' # simplest: single-quoted command
I'm not sure whether I got the question correctly. If you want to replace either % or > by ] then sed is not required here. Use tr in this case:
tr '%>' ']' < input.txt
If you want to replace the sequence %> by ] then the sed command as shown by #AvinashRaj is the way to go.

bash script to build complex command syntax, print it first then execute - problems with variable expansion

I want to create scipt to faciliate producing local text file extracts from Hive.
This is to basically execute commands like below:
hive -e "SET hive.cli.print.header=true;SELECT * FROM dropme"|perl -pe 's/(?:\t|^)\KNULL(?=\t|$)//g'>extract/outbound/dropme.txt
While the above works like a charm I find it quite problematic to implement through the parametrized following script (much simplified):
#!/bin/sh
TNAME=dropme
SQL="SELECT * FROM $TNAME"
echo $SQL
echo "SQL: $SQL"
EXTRACMD="hive -e \"SET hive.cli.print.header=true;$SQL\"|perl -pe 'BEGIN{if(defined(\$_=<ARGV>)){s/\b\w+\.//g;print}}s/(?:\t|^)\KNULL(?=\t|$)//g'>extract/outbound/$TNAME.txt"
echo "CMD: $EXTRACMD";
${EXTRACMD}
When run I get: Exception in thread "main" java.lang.NumberFormatException: For input string: "e"
I know there may be many flavours you can print the text or execute command. For instance the line echo $SQL prints me list of files in the directory instead:
SELECT file1.txt file2.txt file3.txt file4.txt FROM dropme
while the next one: echo "SQL: $SQL" gives just what I want: SQL: SELECT * FROM dropme
echo "CMD: $EXTRACMD" prints the (almost) the command to be executed. Almost, as I see \t in perl code being expanded:
CMD: hive -e "SET hive.cli.print.header=true;SELECT * FROM dropme"|perl -pe 'BEGIN{if(defined($_=<ARGV>)){s\w+\.//g;print}}s/(?: |^)\KNULL(?= |$)//g'>extract/outbound/dropme.txt
Maybe that's still ok, but what I want is to be able to copy&paste this command into (other) terminal and execute as the command I put at the top. Ideally I would like that command to be exactly the same (so with \t there)
Biggest problem I have comes when I try to execute it (${EXTRACMD} line). I'm getting the error:
Exception in thread "main" java.lang.NumberFormatException: For input string: "e" …and so on, irrelevant as bash treats every 'word' as single command here. I assume as I don't even know what is really tries to run (prior print attempt obviously doesn't help)
I'm aware that I have multiple options, like:
escaping special characters in the command definition string (like I did with doublequotes)
experimenting with echo and $VAR, '$VAR' or "$VAR"
experimenting with "${EXTRACMD}" or evaluating through eval "${EXTRACMD}"
experimenting with shopt -s extglob or set -f
but as number of combinations is quite large and with my little bash experience I feel it's better to ask for good practice here so my question is:
Is there a way to print a (complex/compound shell) command first and subsequently be able to execute it (exactly as per printed output)? In this case it would be printing the exact command from the top, then executing it the same way as by manually copying that output into terminal prompt and pressing Enter.
Do not construct commands as strings. See http://mywiki.wooledge.org/BashFAQ/050 for details.
That page also talks about a built-in way of getting the shell to tell you what it is running (section 6).
If that doesn't do what you want you can also, with bash, try using printf %q\\n "${arr[*]}".

Single quotes and double quotes in perl

I'm a newbie in perl and I'm trying to execute an operating system command from a Perl script.
The operating system command is executed with IPC::Open3, and the command is like
$cmd = "mycommand --add \"condition LIKE '%TEXT%' \"";
This command is supposed to insert the string contained after the "add" into a database.
The problem is that it inserts the record in the database without the single quotes around %TEXT%, like this:
condition LIKE %TEXT%
If I execute the command at a command prompt it inserts the string correctly.
How should I format the double and single quotes so that it is inserted in the database correctly?
Thanks for the help
By putting the command in a single string, you are inflicting upon it a pass through your system's shell. (You don't mention if it's cmd.exe or bash or other fun stuff.)
Suggestions:
Creating your system command as an array of strings will avoid the shell re-interpolating your command line.
#cmd = ('mycommand', '--add', q(condition LIKE '%TEXT%'));
Throw in extra backslashes to protect the single quotes from your shell. Prepending echo to your command could help with the debugging....
(my personal favorite) Don't shell out for your Database access. use DBI.
$cmd = q{mycommand --add "condition LIKE '%TEXT%'"};
qq is for double-quoting , q is for single quoting.
This way it takes whole command as it is.

Escape sequence for $ (dollar sign) in T-sql script

I am running a T-SQL script, called from a powershell script, that contains a text row which includes a sequence containing $(MV).
When I run the script I get the error "'MV' scripting variable not defined." which I assume is because it interpretates the $(MV) string as a variable instead of being a part of the text string.
How can I write the dollar sign as an escape sequence? Is that possible in a string?
Are you executing the script with sqlcmd? It will interpret $(variablename) and try to expand it.
You can disable this using the -x command-line option.
Oh, if you're using Invoke-Sqlcmd you can use the -DisableVariables parameter.
I was assuming you didn't want to have the sqlcmd variable substitution done. If you were just trying to get the $ past Powershell, use the back-tick (`$) as in another suggestion.
You can use the backtick character to escape a $ sign in PowerShell:
`$