How to combine ssh and server variables - bash

Please note that I'm trying to create a ssh connection using variables and I getting the below:
SSH_USR=test
SSH_HOST=1.1.1.1
ssh $SSH_USR#SSH_HOST
I get the below output:
#1.1.1.1 - instead of the user and host.
Any ideas on how I can get the values parsed?
Thibo

In order to use the variables you initialized you must precede the variable name with a dollar sign $ whenever you reference the value it contains.
Since you used it correctly before SSH_USR I think you just made a typo and missed it for SSH_HOST:
SSH_USR=test
SSH_HOST=1.1.1.1
echo SSH_USR is $SSH_USR
echo SSH_HOST is $SSH_HOST
echo final statement is ssh $SSH_USR#$SSH_HOST
ssh $SSH_USR#$SSH_HOST

Related

Dynamic variable names based on value

Probably a noob question, but I'm having a particular challenge where I want to dynamically generate variable names based on a value. Eg. If I'd require 3 variables, variable names to be incremented dynamically var_0,var_1,var_3 respectively.
The solution I have right now is barebones. I'm just using read -p get user input and save it to variable. So for 5 hosts, I've just duplicated this 5 times to get the job done, but not a clean solution. I was looking around and reading through declare and eval but haven't got anywhere
Thinking of a solution where I input no. of hosts first and this dynamically picks up and asks for user input based on number of hosts and saves to variables incremented dynamically
Any help is appreciated, cheers
Use arrays. However, you don't have to ask the user for the number of hosts. Let them enter as many hosts as they like and finish by entering an empty line:
echo "Please enter hosts, one per line."
echo "Press enter on an empty line to finish."
hosts=()
while read -p "host ${#hosts[#]}: " host && [ -n "$host" ]; do
hosts+=("$host")
done
echo "Finished"
Alternatively, let the user enter all hosts on the same line separated by whitespace:
read -p "Please enter hosts, separated by whitespace: " -a hosts
To access the individual hosts use ${hosts[0]}, ${hosts[1]}, ..., ${hosts[${#hosts[#]}]}.
To list them all at once use ${hosts[#]}.
Use an array instead!
But read can actualy create dynamic vars, just like this:
for i in {1..3}; do
read -p 'helo: ' var_$i
done

Saltstack cloud.map with Bash variables

I'm trying to provision a Windows virtual machine in VMWare using Salt Cloud wrapped in a bash script so that I can parameterise it but I'm having a problem with the escaping of the map_data.
my command is:
#!/bin/bash
salt salt-cloud cloud.map_run map_data='{"PROFILE":[{"HOSTNAME":{"folder":"FOLDER","devices":{"network":{"Network adapter 1":{"ip":"MYIP"}}}}}]}'
This works fine however I would like HOSTNAME, FOLDER and MYIP to be variables ($hostname $folder and $ip) and I'm struggling a bit with the escaping so that the variables are expanded and passed correctly to salt.
I have tried putting the variable inline in the command:
salt salt-cloud cloud.map_run map_data='{"PROFILE":[{"$hostname":{"folder":"$folder,"devices":{"network":{"Network adapter 1":{"ip":"$ip"}}}}}]}'
This gets as far as copying the template in the profile before bombing out with a vmware error about the variblised elements being incorrect
I have also tried to encapsulate the whole map data in a variable, escaping the double quotes and passing that, e.g,
data="'{\"PROFILE\":[{\"$hostname\":{\"folder\":\"$folder\",\"devices\":{\"network\":{\"Network adapter 1\":{\"ip\":\"$ip\"}}}}}]}'"
This appears to expand correctly if I echo it out but when I add it to my command:
salt salt-cloud cloud.map_run map_data=$data
I get the following error:
Passed invalid arguments to cloud.map_run: map_run() takes at most 1 argument (10 given)
I know that this is probably not strictly Salt's problem but I wondered if anyone out there could give me some pointers on how to proceed?
Did you try the concatenation of strings like that :
salt salt-cloud cloud.map_run map_data='{"PROFILE":[{"'$hostname'":{"folder":"'$folder',"devices":{"network":{"Network adapter 1":{"ip":"'$ip'"}}}}}]}'
I don't use the cloud app myself, so I can't test it but looking at the first command you give:
salt salt-cloud cloud.map_run map_data='{"PROFILE":[{"$hostname":{"folder":"$folder,"devices":{"network":{"Network adapter 1":{"ip":"$ip"}}}}}]}'
Because the variables are in single quotes, they won't expand. So that won't work.
The second command you gave:
data="'{\"PROFILE\":[{\"$hostname\":{\"folder\":\"$folder\",\"devices\":{\"network\":{\"Network adapter 1\":{\"ip\":\"$ip\"}}}}}]}'"
Looks correct, it will expand the variables, but compared to the first command it will also add single quotes to the string (I think you forgot to remove those?).
Also in your first command a " seems to be missing after $folder.
Fixing those mistakes gives me the command:
salt salt-cloud cloud.map_run map_data="{\"PROFILE\":[{\"$hostname\":{\"folder\":\"$folder\",\"devices\":{\"network\":{\"Network adapter 1\":{\"ip\":\"$ip\"}}}}}]}"
which I think would work. If you put an echo in front of your command, and just copy your json, you can copy/paste it into a json formatter like https://jsonformatter.curiousconcept.com/ and it will tell you if the json you used is correct. This will help you find things like missing quotes.

bad substitution with string slices in bash

I'm trying to make a script that will append the port number to the host-name i extract from the computer but when i try to create slice from a string in bash it wont let me. i keep getting a bad substitution error in line 4. I have tried multiple things including using += but that just give me the same error
#! /bin/bash
addr=$(hostname -I)
len=${#addr}
echo "${addr:0:10}" # why does this not work? i tried it without quotes also, get same error
#echo "${addr:0:$len}" # am i a able to use variables in the slice

BASH : Problem regarding hash table/dictionary and bad substitution

Context:
I started writing this script for easily changing connections for my raspberry pi zero (Raspibian Lite as OS), this is because I always needed to edit the wpa-supplicant config file and decided to do something about it as it is a really portable pc.
How it works:
The core of the program is to create profiles in format of dictionaries to store the name and passwd and apply that profile when needed. The profiles are added to the script code itself. I made it like this, every time a new profile is created this 2 lines are generated with the profile name corresponded. For example:
declare -A profile1
profile1=( ["name"]="name" ["pass"]="pass")
Problem:
To apply that profile I put at terminal prompt "./script --use profile1" so my goal is that it gets the details of the profile desired.
When I write that by :
echo "${$2[name]}" it outputs me a " bad substitution" error.
Things I tried and checked:
Shebang is #!/bin/bash
I tried substituting the $2 in a string and trying to execute it but I dont get anything good.
Things to consider:
Here is the link to the script so you can test it yourself, there are some things are a bit more complex than the thing indicated in the post but I just simplified it.
https://github.com/gugeldot23/wpa_scrip
You need nameref variables if you want to address the profile array name by reference:
declare -n profile # nameref variable profile
profile="$2" # Fills-in the nameref from argument 2
# Address the nameref instead of echo "${$2[name]}"
echo "${profile[name]}"
See: gnu.org Bash Manual / Bash Builtins / declare:
-n
Give each name the nameref attribute, making it a name reference to another variable. That other variable is defined by the value of name. All references, assignments, and attribute modifications to name, except for those using or changing the -n attribute itself, are performed on the variable referenced by name’s value. The nameref attribute cannot be applied to array variables.

looping a shell command in ansible

I'm trying to get going with some more advanced Ansible playbooks and have hit a wall. I'm trying to get Ansible to do what this /bin/bash 'for' loop does;
for i in $(</filename.txt);do '/some/command options=1 user=usera server=$i';done
filesnames.txt contains 50-100 hostnames.
I can't use jinja templates as the command has to be run, not just the config file updated.
Any help would be greatly appreciated.
Thanks in advance,
Jeremy
you can use jinja templates, but differently
your specific code is not doing something that is most advisable
for multi-line code you should use shell module.
example of multi-code piece of call:
- name: run multiline stuff
shell: |
for x in "${envvar}"; do
echo "${x}"
done
args:
executable: /bin/bash
note I'm explicitly setting executable, which will ensure bash-isms would work.
I just used envvar as an example, of arbitrary environment variable available.
if you need to pass specific env variables, you should use environment clause of the call to shell module, refer to: http://docs.ansible.com/ansible/playbooks_environment.html
For simple variables you can just use their value in shell: echo "myvar: {{myvar}}"
If you wish to use an ansible list/tuple variable inside bash code, you can make it bash variable first. e.g. if you have a list of stuff in mylist, you can expand it and assign into a bash array, and then iterate over it. the shell code of the call to shell would be:
mylist_for_bash=({{mylist|join(" ")}})
for myitem in "${mylist_for_bash[#]}"; do
echo "my current item: ${myitem}"
done
Another approach would be to pass it as string env variable, and convert it into an array later in the code.
NOTE:
of course all this works correctly only with SPACELESS values
I've never had to pass array with space containing items

Resources