When I'm hardcoding i. e.
server1=ip-10.237.40.10-aws-n-myhost
ssh - i /home/<passwordfile> akhil#$server1
It is working,but when I'm greping the host from other file its not working
Eg:
server2=$(grep - e host /home/akhil/configuration. File | awk FS, '{print $2} ' )
echo $server2
ssh - i /home/<passwordfile> akhil#$server2
While printing server 2 is fine, but when it is used in ssh I'm getting a error saying : not known host name.
I want to automate the script with a configuration file so that when ever the cluster changes I could simply change the ip address in configfile instead of changing in all my scripts.
I need help in this.
Thanks
Related
I have a small BASH backup script that uses Rsync to grab a handful of computers on my LAN. It works very well for static devices using an Ethernet cable - trouble comes in for my even smaller number of Laptop users that have docks. Every once in a while they do not connect to the Dock & Ethernet cable/statically assigned address and end up on the WiFi with a DHCP assigned address. I already have a list of known statically assigned targets in a file that is parsed through to actually backed up. So I keep thinking I should fairly easily be able to create a second file with an nmap scan before each backup run with other code I found - something like:
sudo nmap -n -sP 192.168.2.0/24 | awk '/Nmap scan report for/{printf $5;}/MAC Address:/{print " => "$3;}' | sort
which gives me a list of 192.168.2.101 => B4:FB:E4:FE:C6:6F for all found devices in the LAN. I just removed the | sort and send it to a file > found.devices instead.
So Now I have a list of found devices IP and MAC address - and I'd like to compare the two files and create a new target list with any changed IP addresses found (for those Laptop users that forgot to connect to the Dock and are now using DHCP). But I still want to keep my original targets file clean for the times that they do remember and also continue to get those other devices that are wired all the time while ignoring everything else on the LAN.
found.devices
192.168.2.190 => D4:XB:E4:FE:C6:6F
192.168.2.102 => B4:QB:Y4:FE:C6:6F
192.168.2.200 => B4:FB:P4:ZE:C6:6F
192.168.2.104 => B4:FB:E4:BE:P6:6F
known.targets
192.168.2.101 D4:XB:E4:FE:C6:6F domain source destination
192.168.2.102 B4:QB:Y4:FE:C6:6F domain source destination
192.168.2.103 B4:FB:P4:ZE:C6:6F domain source destination
192.168.2.104 B4:FB:E4:BE:P6:6F domain source destination
Should get a list or a file for the current back run to use of:
192.168.2.190 domain source destination
192.168.2.102 domain source destination
192.168.2.200 domain source destination
192.168.2.104 domain source destination
Currently my bash script just reads the file of known.targets one line at a time:
cat /known.targets | while read ip hostname source destination
do
this mounts and backs up the data I want ...
I really like the current system, and have found it to be very reliable for my simple needs, just need to find some way to get those users that intermittently forget to dock. I expect its series of nested loops, but I cannot get my head to wrap around it - been away from actual coding for too long - Any suggestions would be greatly appreciated. I'd also really like to get rid of the => and just use comma or space separated data but every time I mess with that awk statement - I end up shifting the data and getting an oddly placed CR somewhere I cannot figure it either!
Try this pure Bash code:
declare -A found_mac2ip
while read -r ip _ mac; do
[[ -n $mac ]] && found_mac2ip[$mac]=$ip
done <'found.devices'
while read -r ip mac domain source destination; do
ip=${found_mac2ip[$mac]-$ip}
# ... DO BACKUP FOR $ip ...
done <'known.targets'
It first sets up a Bash associative array mapping found mac address to ip addresses.
It then loops through the known.targets file and for each mac address it uses the ip address from the known.targets file if the mac address is listed in it. Otherwise it uses the ip address read from the known.targets file.
It's also possible to extract the "found" MAC and IP address information by getting it directly from the nmap output instead of from a `found.devices' file. This alternative version of the code does that:
declare -A found_mac2ip
nmap_output=$(sudo nmap -n -sP 192.168.2.0/24)
while IFS=$' \t\n()' read -r f1 f2 f3 f4 f5 _; do
[[ "$f1 $f2 $f3 $f4" == 'Nmap scan report for' ]] && ip=$f5
[[ "$f1 $f2" == 'MAC Address:' ]] && found_mac2ip[$f3]=$ip
done <<<"$nmap_output"
while read -r ip mac domain source destination; do
ip=${found_mac2ip[$mac]-$ip}
# ... DO BACKUP FOR $ip ...
done <'known.targets'
UPDATE: per comment from OP, dropping assumption (and associated code) about keeping an IP address that shows up in found.devices but without a match in known.targets (ie, this cannot happen)
Assumptions:
start with a list of IP/MAC addresses from known.targets
if a MAC address also shows up in found.devices then the IP address from found.devices takes precendence
Adding a standalone entry to both files:
$ cat known.targets
192.168.2.101 D4:XB:E4:FE:C6:6F domain source destination
192.168.2.102 B4:QB:Y4:FE:C6:6F domain source destination
192.168.2.103 B4:FB:P4:ZE:C6:6F domain source destination
192.168.2.104 B4:FB:E4:BE:P6:6F domain source destination
111.111.111.111 AA:BB:CC:DD:EE:FF domain source destination
$ cat found.devices
192.168.2.190 => D4:XB:E4:FE:C6:6F
192.168.2.102 => B4:QB:Y4:FE:C6:6F
192.168.2.200 => B4:FB:P4:ZE:C6:6F
192.168.2.104 => B4:FB:E4:BE:P6:6F
222.222.222.222 => FF:EE:CC:BB:AA:11
One awk idea:
$ cat ip.awk
FNR==NR { ip[$2]=$1; dsd[$2]=$3 FS $4 FS $5; next }
$3 in ip { ip[$3]=$1 }
END { for (mac in ip) print ip[mac],dsd[mac] }
Running against our files:
$ awk -f ip.awk known.targets found.devices
192.168.2.200 domain source destination
192.168.2.190 domain source destination
192.168.2.104 domain source destination
111.111.111.111 domain source destination
192.168.2.102 domain source destination
Feeding this to a while loop:
while read ip hostname source destination
do
echo "${ip} : ${hostname} : ${source} : ${destination}"
done < <(awk -f ip.awk known.targets found.devices)
This generates:
192.168.2.200 : domain : source : destination
192.168.2.190 : domain : source : destination
192.168.2.104 : domain : source : destination
111.111.111.111 : domain : source : destination
192.168.2.102 : domain : source : destination
I am newbie in luci and lua api. Now I have problem about remove firewall rule from luci webgui in opnewrt. I know delete the rule is using the uci command : uci delete firewall.#rule[index]
But I don't know the index exectly. So I use blow shell script name index.sh to find the index by key word.
uci show firewall | grep $1 | grep -oE '\[.*?\]' | sed 's/[][]//g' | head -n 1
Here $1 is the mac address.
My process is get the mac address from luci web and remove the firewall rule of block the
network access from the mac address I set before. To recover the network access of the mac address.
But I use the lua api of luci.sys.exec and luci.util.exec to get the output of firewall rule index that are all wrong.
My example code:
1.Get the mac address from luci
local del_mac = protocol.urldecode(luci.http.formvalue("deleteMac"))
2.Execute the the shell script to get the index
local ruleindex = ut.trim(tostring(luci.sys.exec("index.sh '" .. del_mac .."'"))
local uci_delete_rule = "uci delete firewall.#rule['" .. ruleindex .. "]'"
luci.sys.exec(uci_delete_rule)
or
local index = "index.sh %s" %{list_del_mac}
local rule_index = ut.trim(tostring(luci.util.exe(index)))
local uci_delete_rule = "uci delete firewall.#rule['" .. rule_index .. "]'"
luci.sys.exec(uci_delete_rule)
3.Reload the firewall rule
luci.sys.exec("uci commit firewall")
luci.sys.exec("fw3 reload")
Can anyone help me to reslove the problem?
Thank you for your help
This doesn't look right to me: "index.sh %s" %{list_del_mac} Unless it's short for string.format in luci, that's not proper Lua. Concatenate your command string, or actually use string.format
"index.sh " ..list_del_mac
or
string.format( "index.sh %s", list_del_mac )
also, to get the return value after execution, you need to send it to a variable
return_value = luci.sys.exec(uci_delete_rule)
print( return_value )
I am trying to create an autocomplete script for scp.
The script reads the user and hostname from my .ssh/config file
My .ssh/config file looks like:
Host host1
HostName host1
User userA
port 22
Host host2
HostName host2
User userB
port 22
Host host3
HostName host3
User userB
port 22
My .autocomplete_scp.sh file is:
# SSH
function _scp_completion() {
pcregrep -o -M 'HostName [a-zA-Z.]+[\n\t\s]+User [a-zA-Z]+'
$HOME/.ssh/config | awk 'NR % 2 == 1 { o=$2 ; next } { print $2"#"o}'
}
complete -W "$(_scp_completion)" scp
I source this file in my bashrc.
Now when I type userA and press Tab, the autocomplete function will give me userA#host1. When I type userB and hit Tab, the autocomplete function will give me userB#, but I am not able to get the full string (userB#host2 or userB#host3).
It also doesn't work when I type userA#h and hit the Tab button twice. So it seems to get stuck due to the # sign.
(When I remove the # sign from the _scp_completion function it works fine.)
Any ideas to fix this? Thanks!
The easy way to make it work is to remove '#' from $COMP_WORDBREAKS or Bash would handle # by itself. You can try like this:
COMP_WORDBREAKS=${COMP_WORDBREAKS//#}
complete -W 'userA#host1 userB#host2 userB#host3' scp
According to bash doc:
COMP_WORDBREAKS
The set of characters that the readline library treats as word separators when performing word completion.
I have ssh config file which contains so many servers from google,aws and some remote servers.I wanted to have a bash function that will output only the Host and the HostName of the server so I dont have to remember there public DNS to check my webapps.
Sample Server Config in my ssh config looks like this
Host aws_server
User rand
HostName 65.2.25.152
Port 8000
IdentityFile PEM PATH
ServerAliveInterval 120
ServerAliveCountMax 30
I want the output like
aws_server 65.2.25.152
for all the servers
Using sed
sed '/^Host/{s/[^ ]* //;:1;N;s/\n.*HostName */\t/;t2;b1;:2;p};d' file
aws_server 65.2.25.152
Modified version that's more robust for multiple hosts,missing HostNames
sed ':1;s/\(.*\n\|^\)Host *//;N;s/\n.*HostName */\t/;t2;$!{b1;:2;p};d' file
using awk
awk '{if($1=="Host")k=$2;if($1=="HostName")printf("%s\t%s\n",k,$2)}' file
I would use awk for this:
awk '
# Save the host when we see it.
/^Host/ {
host=$2
next
}
# If we have a host and are on a HostName line
host && $1 == "HostName" {
# Print the Host and HostName values
printf "%s"OFS"%s\n", host, $2
host=""
next
}
# If we have a HostName without a Host clear the host (should not happen but just to be safe)
$1 == "HostName" {
host=""
}
' .ssh/config
I am using puppet for provisioning to AWS cloud. I am a newbie to this.
My requirement is to add entry into /etc/hosts file of amazon ec2 instance. However at the time of writing puppet, I do not know the actual hostname.
How can I use $HOSTNAME variable in .pp file?
Something like this -
host { '$HOSTNAME':
ip => 'echo $HOSTNAME | tr "-" "." | sed 's/ip.//'',
host_aliases => 'mywebsite',
}
Something like this :
host { $fqdn :
ip => $ipaddress,
host_aliases => 'mywebsite',
}
$fqdn provides fully qualified domain name and $ipaddress provides IP address for the machine. These variables are available if you have facter installed in your system. facter is available at the puppetlab repo. You can install it the same way you installed puppet in your system.
As in the comment, you can also use $hostname to get the short-hostname in place of $fqdn.
Since I wanted the hosts file to be updated before startup script's start gets executed, I did this and it worked for me.
Added this in /etc/init.d/
setup_hostname() {
IPADDR=`echo $HOSTNAME | tr "-" "." | sed 's/ip.//'`
echo "${IPADDR} ${HOSTNAME}" >> /etc/hosts
}
Called setup_hostname from start
case "$1" in
start)
clean
setup_hostname
start
;;