LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-04-2019, 06:54 PM   #1
sysmicuser
Member
 
Registered: Mar 2010
Posts: 458

Rep: Reputation: 0
Unhappy How to break array and extract individual components in a shell script


Hey Guys,

I have a shell script below, basically, the intent of the script is to enable firewall rule on remote Windows servers for WinRM so that ANsible can perform configuration management.

Code:
#!/bin/bash

set -x
PROCESS_ID=$$

LOGFILE=/tmp/"${PROCESS_ID}"

az vm list --output=table |tee -a >> "${LOGFILE}"

az login --service-principal -u $APP_ID --password $PASSWORD --tenant $TENANT_ID

# declare an array variable
declare -a host_list=$(cat "${LOGFILE}"|grep NXT|awk '{print $1}')
echo $host_list
## now loop through the above array
for i in "${host_list[@]}"
do
case ${i} in
*AD* )
  export resource_group="rg-ad"
  ;;
*AOS* | *WEB* )
  export resource_group="rg-app"
  ;;
*SQL* | *FS* )
  export resource_group="rg-sql"
  ;;
*APP* | *STG* )
  export resource_group="rg-remote"
  ;;
*BI* | *SSRS* )
  export resource_group="rg-bi"
  ;;
*)
  Message="Invalid hostname , please check"
  ;;
esac
   echo "Installing Windows Remote Management $i with resource group $resource_group "


   az vm run-command invoke --command-id RunPowerShellScript --resource-group "${resource_group}" --name "${i}" --scripts '(New-Object -TypeName System.Net.WebClient).DownloadFile("https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1", "$env:temp\ConfigureRemotingForAnsible.ps1")'

   az vm run-command invoke --command-id RunPowerShellScript --resource-group "${resource_group}" --name "${i}" --scripts 'powershell.exe -ExecutionPolicy ByPass -File "$env:temp\ConfigureRemotingForAnsible.ps1"'
   az vm run-command invoke --command-id RunPowerShellScript --resource-group "${resource_group}" --name "${i}" --scripts 'netsh advfirewall firewall add rule name="Allow WinRM (Http)" dir=in localport=5985 protocol=tcp action=allow enable=yes'
   az vm run-command invoke --command-id RunPowerShellScript --resource-group "${resource_group}" --name "${i}" --scripts 'netsh advfirewall firewall add rule name="Allow WinRM (Https)" dir=in localport=5986 protocol=tcp action=allow enable=yes'

done

exit 0
When it is executed

Code:
./temp.sh
+ PROCESS_ID=13879
+ LOGFILE=/tmp/13879
+ az vm list --output=table
+ tee -a
+ az login "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
[
  {
    "cloudName": "AzureCloud",
      "type": "servicePrincipal"
    }
  }
]
++ cat /tmp/13879
++ awk '{print $1}'
++ grep NXT
+ declare -a 'host_list=NXTPREPAOS-1
NXTPREPAOS-2
NXTPREPAOS-3
NXTPREPAOS-4
NXTPREPAOS-5
NXTPREPSQL-1
NXTPREPSQL-2'
+ echo NXTPREPAOS-1 NXTPREPAOS-2 NXTPREPAOS-3 NXTPREPAOS-4 NXTPREPAOS-5 NXTPREPSQL-1 NXTPREPSQL-2
NXTPREPAOS-1 NXTPREPAOS-2 NXTPREPAOS-3 NXTPREPAOS-4 NXTPREPAOS-5 NXTPREPSQL-1 NXTPREPSQL-2
+ for i in '"${host_list[@]}"'
+ case ${i} in
+ export resource_group=rg-app
+ resource_group=rg-app
+ echo 'Installing Windows Remote Management NXTPREPAOS-1
NXTPREPAOS-2
NXTPREPAOS-3
NXTPREPAOS-4
NXTPREPAOS-5
NXTPREPSQL-1
NXTPREPSQL-2 with resource group rg-app '
Installing Windows Remote Management NXTPREPAOS-1
NXTPREPAOS-2
NXTPREPAOS-3
NXTPREPAOS-4
NXTPREPAOS-5
NXTPREPSQL-1
NXTPREPSQL-2 with resource group rg-app
+ az vm run-command invoke --command-id RunPowerShellScript --resource-group rg-app --name 'NXTPREPAOS-1
NXTPREPAOS-2
NXTPREPAOS-3
NXTPREPAOS-4
NXTPREPAOS-5
NXTPREPSQL-1
NXTPREPSQL-2' --scripts '(New-Object -TypeName System.Net.WebClient).DownloadFile("https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1", "$env:temp\ConfigureRemotingForAnsible.ps1")'
Operation failed with status: 'Bad Request'. Details: 400 Client Error: Bad Request for url: https://management.azure.com/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/rg-app/providers/Microsoft.Compute/virtualMachines/NXTPREPAOS-1%0ANXTPREPAOS-2%0ANXTPREPAOS-3%0ANXTPREPAOS-4%0ANXTPREPAOS-5%0ANXTPREPSQL-1%0ANXTPREPSQL-2/runCommand?api-version=2018-10-01
I want to dynamically get the no of VM's as it could change as per requirement. I know the problem is a whitespace character in the array, how to solve?
 
Old 03-04-2019, 09:13 PM   #2
sysmicuser
Member
 
Registered: Mar 2010
Posts: 458

Original Poster
Rep: Reputation: 0
Unhappy

Made it simpler, all what we want is individual hostnames from an array.

Code:
#!/bin/bash
set -x
PROCESS_ID=$$

LOGFILE=/tmp/"${PROCESS_ID}"

az vm list --output=table |tee -a >> "${LOGFILE}"

az login "xxxxxxxxxxxxxx"

# declare an array variable
declare -a host_list=$(cat "${LOGFILE}"|grep NXT|awk '{print $1}')
echo $host_list

## now loop through the above array
for i in "${host_list[@]}"
do
targetedhost=$(echo $i|cut -d ' ' -f1)
case ${targetedhost} in
*AD* )
  export resource_group="rg-ad"
  ;;
*AOS* | *WEB* )
  export resource_group="rg-app"
  ;;
*SQL* | *FS* )
  export resource_group="rg-sql"
  ;;
*APP* | *STG* )
  export resource_group="rg-remote"
  ;;
*BI* | *SSRS* )
  export resource_group="rg-bi"
  ;;
*)
  Message="Invalid hostname , please check"
  ;;
esac
   echo "Installing Windows Remote Management $targetedhost with resource group $resource_group "

done

exit 0

Output: Looks good but it not going for next hostname until end of the array:

Code:
./temp.sh
+ PROCESS_ID=15311
+ LOGFILE=/tmp/15311
+ az vm list --output=table
+ tee -a
+ az login "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
[
  {
    "cloudName": "AzureCloud",
    "name": "Visual Studio Enterprise",
    }
  }
]
++ cat /tmp/15311
++ grep NXT
++ awk '{print $1}'
+ declare -a 'host_list=NXTPREPAOS-1
NXTPREPAOS-2
NXTPREPAOS-3
NXTPREPAOS-4
NXTPREPAOS-5
NXTPREPSQL-1
NXTPREPSQL-2'
+ echo NXTPREPAOS-1 NXTPREPAOS-2 NXTPREPAOS-3 NXTPREPAOS-4 NXTPREPAOS-5 NXTPREPSQL-1 NXTPREPSQL-2
NXTPREPAOS-1 NXTPREPAOS-2 NXTPREPAOS-3 NXTPREPAOS-4 NXTPREPAOS-5 NXTPREPSQL-1 NXTPREPSQL-2
+ for i in '"${host_list[@]}"'
++ echo NXTPREPAOS-1 NXTPREPAOS-2 NXTPREPAOS-3 NXTPREPAOS-4 NXTPREPAOS-5 NXTPREPSQL-1 NXTPREPSQL-2
++ cut -d ' ' -f1
+ targetedhost=NXTPREPAOS-1
+ case ${targetedhost} in
+ export resource_group=rg-app
+ resource_group=rg-app
+ echo 'Installing Windows Remote Management NXTPREPAOS-1 with resource group rg-app '
Installing Windows Remote Management NXTPREPAOS-1 with resource group rg-app
+ exit 0
As you would see above we got the hostname and it finished it need to loop through, why it is not going through?
 
Old 03-04-2019, 10:38 PM   #3
orbea
Senior Member
 
Registered: Feb 2015
Distribution: Slackware64-current
Posts: 1,950

Rep: Reputation: Disabled
Your quoted array is not splitting, is this intentional?

For example.

Code:
$ foo='this is a test'
$ for i in ${foo[@]}; do echo $i; done
this
is
a
test
$ for i in "${foo[@]}"; do echo $i; done
this is a test
 
1 members found this post helpful.
Old 03-04-2019, 11:05 PM   #4
sysmicuser
Member
 
Registered: Mar 2010
Posts: 458

Original Poster
Rep: Reputation: 0
@orbea

Thanks, heaps for that, I cannot believe that double quotes around the array were causing the grief! I am now confused, normally it a good practice to reference a variable like "${env}", so this does not hold true for an array?

Please enlighten

Thank you
 
Old 03-04-2019, 11:12 PM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,869
Blog Entries: 1

Rep: Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870
It depends your goal: it you don't wish your variable space-splitted, use qutes: "$env", otherwise don't: $env or ${env}
 
2 members found this post helpful.
Old 03-04-2019, 11:26 PM   #6
sysmicuser
Member
 
Registered: Mar 2010
Posts: 458

Original Poster
Rep: Reputation: 0
Aah! Got it, Thanks @Nevem Teve!
 
Old 03-05-2019, 12:48 AM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,008

Rep: Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193Reputation: 3193
This is an extremely bad example.

You should in fact double quote if it was actually an array.
As it is a simple string the ${[@]} expander is not being used correctly hence the output issues.
Here is a quick demo using orbea's example:
Code:
foo='this is a test'
for i in ${foo[@]}; do echo $i; done
for i in "${foo[@]}"; do echo $i; done


fooa=(this 'is a' test)

for i in ${fooa[@]}; do echo $i; done
for i in "${fooa[@]}"; do echo $i; done
The additional quotes inside the array are to prove why you need quotes around an array
 
2 members found this post helpful.
Old 03-05-2019, 02:04 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,869
Blog Entries: 1

Rep: Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870Reputation: 1870
It would be nice to see an mcve.
https://stackoverflow.com/help/mcve
 
1 members found this post helpful.
Old 03-05-2019, 07:40 AM   #9
orbea
Senior Member
 
Registered: Feb 2015
Distribution: Slackware64-current
Posts: 1,950

Rep: Reputation: Disabled
Quote:
Originally Posted by grail View Post
The additional quotes inside the array are to prove why you need quotes around an array
Thanks for the additional examples, this is what I get for almost never using bash specific arrays.
 
Old 03-05-2019, 08:03 AM   #10
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,784

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
In this case, it probably makes more sense to use a while read loop (and drop useless use of cat and grep):

Code:
awk '/NXT/ {print $1}' "$LOGFILE" | while read i
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
ipv6 newbie. is ipv6 configurable by an individual? or ipv4 still best for individual debguy Linux - Networking 1 10-26-2015 01:40 PM
BASH-Adding array element: Naming issue using array[${#array[*]}]=5 calvarado777 Programming 8 07-26-2013 09:48 PM
[SOLVED] break word into individual alphabets sysmicuser Linux - Newbie 6 03-15-2012 07:36 PM
[SOLVED] shell script help: copying directory list into an array and then accessing the array richman1234 Linux - Newbie 6 07-25-2010 11:19 PM
extract all the diagrams in a pdf file to individual graphics files on linux tcma Linux - Software 0 10-22-2004 01:52 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:08 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration