For-Loop strange issue - bash

Please see below outputs, it looks like the first line isn't working for the first file only - but is for the others, any ideas?
#!/bin/sh
cpuser=$1
cd "/home/$cpuser/public_html"
wpconfigs=($(find . -name "wp-config.php"))
for i in "${wpconfigs[#]}";
do
cpuser=$cpuser
wpdb=$(grep -e "DB_NAME" $i | cut -d \' -f 4)
wpuser=$(grep -e "DB_USER" $i | cut -d \' -f 4)
wppass=$(grep -e "DB_PASS" $i | cut -d \' -f 4)
set -x uapi --output=jsonpretty --user="$cpuser" Mysql create_user name="${wpuser}" password="${wppass}";
sleep 2s;
set -x uapi --output=jsonpretty --user="$cpuser" Mysql set_privileges_on_database user="${wpuser}" database="${wpdb}" privileges="ALL PRIVILEGES";
sleep 2s;
set -x uapi --output=jsonpretty --user="$cpuser" Mysql set_password user="${wpuser}" password="${wppass}";
sleep 2s;
done
When I look at the output run set -x to debug I see the following;
[root#cpanel201 ~]# sh ./testing.sh qv5goe35p3783sz8
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_privileges_on_database 'user=qv5goe35p3783sz8_yscr_bbS$L5' database=qv5goe35p3783sz8_blog 'privileges=ALLPRIVILEGES'
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_password 'user=qv5goe35p3783sz8_yscr_bbS$L5' password=FhtH6UztIuoS0_
+ sleep 2s
+ for i in "${wpconfigs[#]}"
+ cpuser=qv5goe35p3783sz8
++ grep -e DB_NAME ./wordpress/wp-config.php
++ cut -d \' -f 4
+ wpdb=qv5goe35p3783sz8_wordpress
++ grep -e DB_USER ./wordpress/wp-config.php
++ cut -d \' -f 4
+ wpuser=qv5goe35p3783sz8_yscr_bb5X8h
++ grep -e DB_PASS ./wordpress/wp-config.php
++ cut -d \' -f 4
+ wppass=X7lyC17Td8tH3cm
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql create_user name=qv5goe35p3783sz8_yscr_bb5X8h password=X7lyC17Td8tH3cm
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_privileges_on_database user=qv5goe35p3783sz8_yscr_bb5X8h database=qv5goe35p3783sz8_wordpress 'privileges=ALL PRIVILEGES'
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_password user=qv5goe35p3783sz8_yscr_bb5X8h password=X7lyC17Td8tH3cm
+ sleep 2s
+ for i in "${wpconfigs[#]}"
+ cpuser=qv5goe35p3783sz8
++ grep -e DB_NAME ./newsite/wp-config.php
++ cut -d \' -f 4
+ wpdb=qv5goe35p3783sz8_newsite
++ grep -e DB_USER ./newsite/wp-config.php
++ cut -d \' -f 4
+ wpuser=qv5goe35p3783sz8_yscr_bbxQiN
++ grep -e DB_PASS ./newsite/wp-config.php
++ cut -d \' -f 4
+ wppass=XpMa4v5z54tcM
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql create_user name=qv5goe35p3783sz8_yscr_bbxQiN password=XpMa4v5z54tcM
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_privileges_on_database user=qv5goe35p3783sz8_yscr_bbxQiN database=qv5goe35p3783sz8_newsite 'privileges=ALL PRIVILEGES'
+ sleep 2s
+ set -x uapi --output=jsonpretty --user=qv5goe35p3783sz8 Mysql set_password user=qv5goe35p3783sz8_yscr_bbxQiN password=XpMa4v5z54tcM
+ sleep 2s
If you look at the outputs for the second + third set of files you'll see three uapi commands, however, for the first we only see two and no outputs in terms of the greps it is doing on the top file.
For your reference, cpuser is set on the command line (the value after sh ./testing.sh)
I've also noticed that in the top file, the user appears to get surrounded by 's however the other two don't.
For clarity what the script is doing here;
Scraping any wp configs for a sql db name, db user and db password
Passing the user name and password to a cpanel api to create the user in a cPanel instance
The action works on config files 2 and 3 in this instance, but, not with the initial one - you will see the first create_user is missing even on the set -x
**
UPDATE
Having reviewed the logs, I believe this may be due to the fact that the user on the first one has a $ within it - could this be why? I have noticed that only on this one also, the command gets quoted within ''s which is incorrect for uapi. If this may be why, how do I resolve that?
'user=qv5goe35p3783sz8_yscr_bbS$L5'
How do I escape the $, as I think that's what is causing the issue in this case - all others are okay, only where a $ is within the username does this issue occur

The follow code tells it all:
$ set -x ls
$ ls
+ ls
a.out
As far as I know in all shells the 'ls' behind 'set -x' is ignored. By the next '$ ls' and '+ ls' you can see that 'set -x' is executed.
The normal way to do this, and probably what you want, is:
$ set -x
$ ls
+ ls
a.out
$ set -
+ set -
Or as a one liner:
$ set -x ; ls ; set -
+ ls
a.out
+ set -
By the previous you can also see why the line is missing in your output 'set -x' just enables shell tracing for the next command, where 'set -' ends it also for the next command.

Related

command not executing when called from a case statement in bash

I'm stuck and trying to troubleshoot why the command within the case statement will not execute within this bash script.
If I copy and paste the command into the command line and hardcode the value it will work.
Example:
psql -h mycluster-1.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="foo_bar" -f getTableDetails.sql
In the script, I encased the command within parentheses for possible whitespace issues:
#!/usr/local/bin/bash
set -e
set -x
cluster_to_endpoint() {
case "$1" in
c01)
RUNCMD=$(psql -h mycluster-1.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="$NAME" -f getTableDetails.sql)
;;
c02)
RUNCMD=$(psql -h mycluster-2.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="$NAME" -f getTableDetails.sql)
;;
esac
}
while getopts ":c:n:" opt; do
case $opt in
c) cluster="$OPTARG";;
n) name="$OPTARG";;
*) usage
exit 1
;;
esac
done
I am executing the script like so: ./myscript.sh -c c01 -n foo_bar
I've also tried just removing the () as well:
c01)
psql -h mycluster-2.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="$NAME" -f getTableDetails.sql;;
It looks like the variables are set.
$ ./myscript.sh -c c01 -n foo_bar
+ getopts :c:n: opt
+ case $opt in
+ cluster=c01
+ getopts :c:n: opt
+ case $opt in
+ name=foo_bar
+ getopts :c:n: opt
So why isn't the command executing? Thanks.
The command that isn't executing is inside a function, cluster_to_endpoint, that's never called.

Shell script for searching different on multiple servers

I want to search different packages in multiple servers in Solaris 10. One file contains the package information, another file contains the server information.
I have tried this:
bash-3.00# cat pk
"VRTSvcs|VRTSvxfen"
"SUNWfmd|SUNWfsmgtr"
bash-3.00# cat ser
mokshi
niki
This is my script:
bash-3.00# cat tt
#!/usr/bin/bash
>output
for j in `cat ser`
do
for ip in `cat pk`
do
M=`ssh $j "pkginfo |egrep $ip |cut -d \" \" -f7 "`;
echo "$j " >>output
echo "$M" >>output
done
done
The expected output is
cat output
bash-3.00# cat output
moksha
VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen
niki
SUNWfmd
SUNWfmdr
SUNWfsmgtr
but when I run the script it is running twice like this:
bash-3.00# bash -x tt
++ cat ser
+ for j in '`cat ser`
'
++ cat pk
+ for ip in '`cat pk`'
++ ssh mokshi 'pkginfo |egrep "VRTSvcs|VRTSvxfen" |cut -d " " -f7 '
Password:
+ M='VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen'
+ echo 'mokshi '
+ echo 'VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen'
+ for ip in '`cat pk`'
++ ssh mokshi 'pkginfo |egrep "SUNWfmd|SUNWfsmgtr" |cut -d " " -f7 '
Password:
+ M='SUNWfmd
SUNWfmdr
SUNWfsmgtr'
+ echo 'mokshi '
+ echo 'SUNWfmd
SUNWfmdr
SUNWfsmgtr'
+ for j in '`cat ser`'
++ cat pk
+ for ip in '`cat pk`'
++ ssh niki 'pkginfo |egrep "VRTSvcs|VRTSvxfen" |cut -d " " -f7 '
Password:
+ M='VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen'
+ echo 'niki '
+ echo 'VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen'
+ for ip in '`cat pk`'
++ ssh niki 'pkginfo |egrep "SUNWfmd|SUNWfsmgtr" |cut -d " " -f7 '
Password:
+ M='SUNWfmd
SUNWfmdr
SUNWfsmgtr'
+ echo 'niki '
+ echo 'SUNWfmd
SUNWfmdr
SUNWfsmgtr'
And I am getting output like this:
bash-3.00# cat output
moksha
VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen
moksha
SUNWfmd
SUNWfmdr
SUNWfsmgtr
niki
VRTSvcs
VRTSvcsag
VRTSvcsea
VRTSvxfen
niki
SUNWfmd
SUNWfmdr
SUNWfsmgtr
The main goal of the script is that its take one server from server file and it has to search first line in package file. The it has to take second server name from server name and it searches for second line in package file.
please help me where I made a mistake.
You could do this - assuming you have an equal number of lines in your server and package files:
#!/usr/bin/env bash
while read -u 3 -r server && read -u 4 -r pkg; do
m=$(ssh -n "$server" "pkginfo | egrep '$pkg' | cut -d' ' -f7")
echo "$server"
echo "$m"
done 3<ser 4<pk >> output
3<ser connects fd 3 to file ser and 4<pk connects fd 4 to file pk
read -u 3 reads from file descriptor 3, read -u 4 reads from file descriptor 4
$() is better than back ticks (see the post below to find why)
cut -d' ' -> guess your delimiter is a space
ssh -n is needed so that ssh ignored stdin and doesn't interfere with read
it is better to put >> output at the end for more efficient I/O
See also:
Why you don't read lines with "for"
'read -r' doesn't read beyond first line in a loop that does ssh
What's the difference between $(command) and `command` in shell programming?

2nd echo statement in bash script not working

For some reason I'm not getting the output of my 2nd echo line when I run my script. Here is my code snippet:
IS_RUNNING=$(netstat -anp | grep ":7600" | grep java | awk '{print $7}' | cut -d"/" -f 2)
start(){
nohup /bin/su -c "/opt/app/bin/service start" - user &>/dev/null &
echo "Starting Services please wait"
sleep 30
if [ "$IS_RUNNING" = java ];
then
echo "Service is now running"
exit 0
fi
}
Interestingly. when I run it with:
sh -x ./service start
I get the output expected and my 2nd echo gets written to the screen.
+ case "$1" in
+ start
+ echo 'Starting Services please wait'
Starting Services please wait
+ sleep 30
+ nohup /bin/su -c '/opt/app/bin/service start' - user
+ '[' java = java ']'
+ echo 'Service is now running'
Service is now running
+ exit 0
Without using sh -x, I simply get this:
[root#init.d]# ./service start
Starting Services please wait
[root#init.d]#
I have a feeling I'm overlooking something simple. Can anyone help?
The running line is evaluated once:
IS_RUNNING=$(netstat -anp | grep ":7600" | grep java | awk '{print $7}' | cut -d"/" -f 2)
You should make a function for this or include this line in the start() function after the sleep.

Recursive while loop in docker cmd

I'm trying to run google chrome inside docker containers. I have been able to successfully do so, however there have been instances where chrome would not run on some of the containers (mass creation of containers).
So I'm looking to run a while loop till the chrome process is found to be running. I've tried the following but with errors like "bash: [if: command not found"
var chrome_command = 'google-chrome --user-data-dir=/home/ubuntu/chrome-user-dir';
var cmd = '';
cmd += 'Xvfb :99 & ';
cmd += 'export DISPLAY=:99 & ';
cmd += 'x11vnc -rfbport 6001 -display :99 -bg -q & ';
cmd += 'while [if ps aux | grep "google-chrome"|grep -v grep > /dev/null]; do ' + chrome_command + '; sleep 1 ; done';
Could someone point out where I am going wrong! Thanks!
The last line should be:
cmd += 'while ! ps aux | grep -v grep | grep -q chrome; do ' + chrome_command + '; sleep 1 ; done';
-q for the last grep would suffice to see if there's matched lines in the input.
Use ! to negate the result of list of commands.
It seems google-chrome won't appears in ps aux.

Bash loop never ends

I wonder why this script never ends?
#! /bin/bash
for ip in `seq 200 254`; do
ping -c 1 192.168.0.$ip | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1 &
done
But if I choose not to run commands in parallel, script ends up just ok.
#! /bin/bash
for ip in `seq 1 254`; do
ping -c 1 192.168.0.$ip | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1
done
Could somebody explain, please, why is it happens?
Your for loops are doing the exact same thing. The only difference is that in the first instance you are running all commands in the background and will not see a termination. Specifically:
ping -c 1 192.168.0.$ip | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1 &
^^^
Using the & operator at the end tells bash to background the process. Eliminating the & runs the process in the foreground where the execution is visible.

Resources