Chef - using a for loop with SQLEOH - ruby

I have a bash resource which is failing when attempting to loop through some ddl scripts. The same syntax without a for loop (and literal script name) works fine in Chef, and it all works including with the for loop in a terminal:
bash "run_ddl_create_tenants" do
user "#{ENV['CHEFUSER']}"
environment "PATH" => "/usr/lib/oracle/12.1/client64/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/aws/bin:/opt/aws/bin:/home/#{ENV['CHEFUSER']}/bin"
code <<-EOH
for f in $(grep '>' /tmp/diffs/tnntdiff | cut -c 3-); do
sqlplus "admin/password#(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=$(aws rds describe-db-instances --db-instance-identifier #{ENV['CLIENTID']}-#{ENV['CTCENV']} | grep 'Address' | cut -d\\\" -f4))(PORT=#{ENV['DBPORT']}))(CONNECT_DATA=(SID=#{ENV['CLIENTID']}#{ENV['CTCENV']})))" <<-SQLEOH
##{ENV['CTC_CONFIGURATION']}/ddl/ddl_create_tenant_$f.sql
#{ENV['DBPASSWD']}
exit;
SQLEOH
done
EOH
end
The errors I am getting indicate a problem with the SQLEOH delimiter and unexpected end-of-file.
STDERR: /tmp/chef-script20151012-25490-16o11q7: line 7: warning: here-document at line 2 delimited by end-of-file (wanted `SQLEOH')
/tmp/chef-script20151012-25490-16o11q7: line 8: syntax error: unexpected end of file
What is the disconnection between the terminal commands and the way Chef is interpreting this resource?

Got it, issue of whitespaces preceding the delimiter. Removed indentation on SQLEOH and connected successfully

Related

strange behaviour of a subshell executing command with arguments

when I execute the following command directly:
root#busybox-694d76bb5d-2gcvh:/# mysql -hmariadb -P3306 -uroot -ppassword -e 'SELECT 1'
I get the following output:
mysql: [Warning] Using a password on the command line interface can be insecure.
+---+
| 1 |
+---+
| 1 |
+---+
However, the same command in a subshell, like so:
$(mysql -hmariadb -P3306 -uroot -ppassword -e 'SELECT 1')
outputs:
mysql: [Warning] Using a password on the command line interface can be insecure.
bash: 1: command not found
why does bash interprets the "1" I send as an argument as if it was a separate command when it is sent in a subshell?
It's not the 1 that's part of the arguments that is interpreted by bash, it's the output of the command.
First, you need to know that mysql has two default modes of output : table and raw. The first is used when the command's output stream is a terminal and prints an human-readable output. The second is used otherwise and prints an output easily manipulated by scripts. You can force one or the other by using the options whose documentation I've linked.
Secondly, you need to know the difference between a simple (subshell) and $(command substitution) : in both cases the command is run in a subshell, but with command substitution the output of the command is substituted in the original command line which is then executed.
So what happened when you wrote your $(mysql command) is that its output was 1 (the raw result) instead of the table you previously saw, which then failed to be parsed as a command.
You can see the difference between subshell and command substitution more easily by testing the difference between (echo 1) and $(echo 1), the second of which will fail in the exact same way as your current command.

Single quotes escaping Ruby

So, Im working with a Ruby script that needs to connect to a bunch of servers and get information from them. The problem I am having is that the single quotes seem to be getting lost somehow. What am I doing wrong here ?
command = "grep -E \'^(upstream| *server)\' /etc/nginx/upstreams.conf | sed -E \'s/_pool.*//g ; s/^upstream //g\'"
puts system("ssh -n -o 'StrictHostKeyChecking no' #{nginx_stage_servers[0]} #{command}")
Error I am getting :
$ ruby nx.rb
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `grep -E ^(upstream| *server) /etc/nginx/upstreams.conf'
true
The reason of the error is the single quotes missing.
You have too many layers of quoting and escaping to deal with when you use system(command_string), you're almost always better off using the multi-argument form of Kernel#system to avoid dealing with the shell. Something like this will be less problematic:
system('ssh', '-n', '-o', 'StrictHostKeyChecking no', nginx_stage_servers[0], command)

Ansible echo into file

I'm struggling with some Ansible/YAML syntax here. How do I echo multiple lines (in append mode) in to a file? I also can't use the copy module (with the content arg) because it has to be appended.
This code:
- name: Write backup script for each app
shell: echo | '
line one
line two
line three
' >> /manager/backup.sh
errors out with nonsensical:
"stderr": "/bin/sh: line one line two line three : command not found"
I'm using the pipe because I think it's how you tell Ansible you want multiple lines (with preserved formatting), but maybe it's being used as a shell pipe.
You want something like this:
- name: Write backup script for each app
shell: |
echo 'line one
line two
line three' >> /manager/backup.sh
or explicitly specifying newline with printf:
- name: Write backup script for each app
shell: printf 'line one\n
line two\n
line three\n' >> /manager/backup.sh
The error message you get makes perfect sense: you tried to pipe (|) the output of the echo command to the line one line two line three command. As shell does not find the latter, it reports the command not existing. It's the same if you executed the following directly in shell:
echo | "line one line two line three" >> /manager/backup.sh
YAML uses | to indicate multi-line value, but when used directly after the key, not anywhere in the value field.
I fixed it with:
ansible node -i hosts -m shell -a "echo 'line one\nline two\nline three' | sudo tee -a /tmp/test.file;"

condor: unmatched quotes when submitting bash jobs

I wrote a conder script for a job and use condor_submit to submit this job. Below is my script:
Executable=/bin/bash
Arguments=" -c "" command_to_run -d -f"" "
initialdir= /path/
output=/path/out
error=/path/err
log=/path/log
universe = vanilla
Getenv = true
Queue
As seen above, the executable is bash and I use -c to pass the command as a string to bash. The job gets submitted fine, but I get the following error message in err output file:
command_to_run: -c: line 0: unexpected EOF while looking for matching `"'
command_to_run: -c: line 1: syntax error: unexpected end of file
This is simply bash complaining about unmatched double quotes. But double quotes look fine to me. I don't know what the problem is. It seems like it is a condor problem. Any ideas?
If you're just passing -c to bash then single quoting should be sufficient (unless you're trying to embed variables):
Arguments=" -c 'command_to_run -d -f' "

Bash script from Codesourcery arm-2011.03 can't find grep or sed

I'm trying to run the CodeSourcery arm-2011.03.42 BASH script in Ubuntu 12.04. At the top of the script is the following:
#! /usr/bin/env bash
But, when I execute it, I get the following errors:
line 140: grep: command not found
line 140: sed: command not found
I can run both grep and sed from the command line, but not in the script.
Here's what line 140 look like
env_var_list=$(export | \
grep '^declare -x ' | \
sed -e 's/^declare -x //' -e 's/=.*//')
If I change the first line to
#!/bin/sh
I get the following error:
Line 51: Syntax error: "(" unexpected (expecting "}")
Here's what Line 51 looks like
check_pipe() {
local -a status=("${PIPESTATUS[#]}") #<-- Line 51
local limit=$1
local ix
The #<-- Line 51 actually doesn't appear in the shell script. I just added it to this post for clarity.
I've tried dos2unix and a number of other things, but I just can't win. I would very much appreciate your help.
I changed this line in the script
pushenvvar PATH /usr/local/tools/gcc-4.3.3/bin
to
pushenvvar PATH /usr/local/tools/gcc-4.3.3/bin:/bin
and it seems to work now.
Shell script must be bash as arrays don't exist in sh.
Check your PATH evironment variable, and the path of grep and sed /bin normally.
Ther might be several possiable reasons.
As #AntonioD pointed out, there must not be any space between '#!' and '/usr/bin/env' at the begining of the file.
The grep and sed command does not exists in your $PATH, checkout your /bin and /user/bin to see if they are existed, or run which grep and which sed in your shell.
If grep and sed are indeed existed, you need to make sure they have right access.They should be accessable and executable, in general, this should not happen.
You must not using #!/bin/sh instead of #!/usr/bin/evn or #!/bin/bash, because that would cause the shell run in POSIX compatible mode in which most of bash advanced features such as arrays are not functional.
If all of above are not the case, then it is really weird.

Resources