How can I determine the IP address from a bash script? - linux

How do I get the IPaddress of the current machine from Bash in a cross platform compatible way? I need to get the IP address the same way for Windows Linux and Mac OS.
I am currently using docker-compose to create a local version of my full deployment, however I can't access it using localhost or 127.0.0.1, I have to refer to the current machines IP address, for example curl 192.168.0.23:80
Currently I make the user set the IP address manually:
# Return true if we pass in an IPv4 pattern.
not_ip() {
rx='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
if [[ $1 =~ ^$rx\.$rx\.$rx\.$rx$ ]]; then
return 1
else
return 0
fi
}
# Ensure lower case
OPTION=$(echo $1 | tr [:upper:] [:lower:])
case "$OPTION" in
"test")
LOCAL_IP=${LOCAL_IP:-$2}
if not_ip "$LOCAL_IP" ; then
echo The test command couldn\'t resolve your computers Network IP. $LOCAL_IP
echo
help_comment
exit 1
fi
python -m webbrowser "http://${LOCAL_IP}:80/" &
;;
esac
However I would love to be able to get this without having to have the user set any environment variables, especially when dealing with Windows machines.
Any ideas?

You need to detect host before use of the following because of OS specific commands
Windows (Cygwin command line )
LOCAL_IP=${LOCAL_IP:-`ipconfig.exe | grep -im1 'IPv4 Address' | cut -d ':' -f2`}
MacOS
LOCAL_IP=${LOCAL_IP:-`ipconfig getifaddr en0`} #en0 for host and en1 for wireless
Linux
LOCAL_IP=${LOCAL_IP:-`ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'`}

Related

Server not reachable within a VPN (SNX) out of a Docker container

I am working with the latest Manjaro with the kernel: x86_64 Linux 5.10.15-1-MANJARO.
I am connected to my company network via VPN.
For this I use SNX with the build version 800010003.
When I start a Docker container (Docker version 20.10.3, build 48d30b5b32) which should connect to a machine from the company network, I get the following message.
[maurice#laptop ~]$ docker run --rm alpine ping company-server
ping: bad address 'company-server'
Also using the IP from the 'company-server' doesn't work.
A ping outside the container works, no matter using the name or IP.
The resolv.conf looks correct to me.
[maurice#laptop ~]$ docker run --rm alpine cat /etc/resolv.conf
# Generated by NetworkManager
search lan
nameserver 10.1.0.250
nameserver 10.1.0.253
nameserver 192.168.86.1
What I have found out so far.
If I downgrade packages glibc and lib32-glibc to version 2.32-5, the ping out of the container works again. Because of dependencies I have also to downgrade gcc, gcc-libs and lib32-gcc-libs to version 10.2.0-4.
I tried the whole thing with a fresh Pop OS 20.10 installation, same problem.
I also did a test with another VPN (OpenVPN) which worked fine. However, this was only a test scenario and cannot be used as an alternative.
I have been looking for a solution for several days but have not found anything. It would be really nice if someone could help me with this.
TL;DR:
on kernel >5.8 the tunsnx interface is no longer created with global scope and need to be recreated. small script to the rescure https://gist.github.com/Fahl-Design/ec1e066ec2ef8160d101dff96a9b56e8
Longer version:
Here are my findings and the solution to (temp) fix it:
Steps to reproduce:
connect your snx tunnel
see ping fails to server behind tunnel
docker run --rm -ti --net=company_net busybox /bin/sh -c "ping 192.168.210.210"
run this command to check ip and scope of the "tunsnx" interface
ip -o address show "tunsnx" | awk -F ' +' '{print $4 " " $6 " " $8}'
if you get something like
192.168.210.XXX 192.168.210.30/32 247
or (Thx Timz)
192.168.210.XXX 192.168.210.30/32 nowhere
the scope is not set to "global" and no connection can be established
to fix this, like "ronan lanore" suggested, you need to change the scope to global
this can be done with a little helper script like this one:
#!/usr/bin/env bash
#
# Usage: [dry_run=1] [debug=1] [interface=tunsnx] docker-fix-snx
#
# Credits to: https://github.com/docker/for-linwux/issues/288#issuecomment-825580160
#
# Env Variables:
# interface - Defaults to tunsnx
# dry_run - Set to 1 to have a dry run, just printing out the iptables command
# debug - Set to 1 to see bash substitutions
set -eu
_log_stderr() {
echo "$*" >&2
}
if [ "${debug:=0}" = 1 ]; then
set -x
dry_run=${dry_run:=1}
fi
: ${dry_run:=0}
: ${interface:=tunsnx}
data=($(ip -o address show "$interface" | awk -F ' +' '{print $4 " " $6 " " $8}'))
LOCAL_ADDRESS_INDEX=0
PEER_ADDRESS_INDEX=1
SCOPE_INDEX=2
if [ "$dry_run" = 1 ]; then
echo "[-] DRY-RUN MODE"
fi
if [ "${data[$SCOPE_INDEX]}" == "global" ]; then
echo "[+] Interface ${interface} is already set to global scope. Skip!"
exit 0
else
echo "[+] Interface ${interface} is set to scope ${data[$SCOPE_INDEX]}."
tmpfile=$(mktemp --suffix=snxwrapper-routes)
echo "[+] Saving current IP routing table..."
if [ "$dry_run" = 0 ]; then
sudo ip route save >$tmpfile
fi
echo "[+] Deleting current interface ${interface}..."
if [ "$dry_run" = 0 ]; then
sudo ip address del ${data[$LOCAL_ADDRESS_INDEX]} peer ${data[$PEER_ADDRESS_INDEX]} dev ${interface}
fi
echo "[+] Recreating interface ${interface} with global scope..."
if [ "$dry_run" = 0 ]; then
sudo ip address add ${data[$LOCAL_ADDRESS_INDEX]} dev ${interface} peer ${data[$PEER_ADDRESS_INDEX]} scope global
fi
echo "[+] Restoring routing table..."
if [ "$dry_run" = 0 ]; then
sudo ip route restore <$tmpfile 2>/dev/null
fi
echo "[+] Cleaning temporary files..."
rm $tmpfile
echo "[+] Interface ${interface} is set to global scope. Done!"
if [ "$dry_run" = 0 ]; then
echo "[+] Result:"
ip -o address show "tunsnx" | awk -F ' +' '{print $4 " " $6 " " $8}'
fi
exit 0
fi
[ "$debug" = 1 ] && set +x
Same problem for me now. Nothing big change but tunsnx interface scope change from global to 247. Delete it and re create with global scope.
Just for collection of possible solutions. I had the same problem but found that "tunsnx" interface was configured properly with "global" keyword. In my case the problem was that snx was started after docker daemon and restarting docker service docker restart helped.

wsl2 DISPLAY variable on windows host

I use windows 10 and WSL2.
To run linux applications on the X server hosted by the windows machine, I use the second command:
export WSL_HOST_IP=$( cmd.exe /C netsh interface ip show addresses "vEthernet (WSL)" | grep "IP Address" | sed -e "s/\sIP Address:\s//g" ) and it works:
echo $WSL_HOST_IP
172.20.48.1
how do i transform it into the DISPLAY variable?
what I want to get is this: DISPLAY = $WSL_HOST_IP:0.0 but I can't write ": 0.0" in bash. Anyone help me? Thanks in advance
You need to remove DOS line ending with s/\r//:
export WSL_HOST_IP=$( cmd.exe /C netsh interface ip show addresses "vEthernet (WSL)" | grep "IP Address" | sed -e "s/\sIP Address:\s//g; s/\r//" )

Shell script run with mac address validate

Can we run shell script with check system mac address validation then process.
#!/bin/bash
### here i need to check system mac address
### if mac is not match then script will not run
killall gnome-terminal
echo "End Of Day Session Complete"
plz suggest
Why not. First get the mac address of your system and store it in a variable in your shell script or in a config file. Every time when you run the script first get the mac address of the system and compare with the mac id already stored in your script's variable if same continue and if not just exit. Use ifconfig -a command to get the mac address of your system and store it in a config file or in your script.
A hardware adress can be obtained like this:
LC_ALL=C ifconfig | egrep "HWaddr" | awk '{print $5}'
but note:
there might be more than one interface with a mac
on many systems, the mac can be spoofed
To suspend work, just exit. Don't killall, and if you do, don't expect later echo messages to be seen by someone.
As you want to run your code on multiple systems, you could use an associative array to store the MAC addresses of the systems where the script is to be run
declare -A valid_mac
valid_mac["00:00:00:00:00:00"]=1
valid_mac["00:00:00:00:00:01"]=1
valid_mac["00:00:00:00:00:02"]=1
Your script function is to terminate all gnome-terminal sessions on each machine where it is run if the mac address is valid.
Let's define a function
function kill_all_terms(){
killall gnome-terminal
echo "End Of Day Session Complete"
}
Now on each machine you want to get a list of MAC addresses of this machine. There are many ways to do it. The function below lists MAC addresses of all IPv4 interfaces using shell string parsing capabilities
function macs(){
local macs line l1
while read line ; do
l1="${line#*link/ether }" ;
macs="${l1% brd*} ${macs}" ;
done < <( ip -4 -o link ) ;
echo "${macs}"
}
Now we can define the main loop
function main() {
for mac in $(macs) ; do
if [ -n "${valid_mac[$mac]}" ] ; then
kill_all_terms
break
fi
done
}
Finally just run main() as
main "$#"

Why this function in bashrc Dosnt work?

I am trying to get this function to file .bashrc
This is my function :
function my_ip() {
echo "internal or external?"
read -r choise
if [ "$choise" == "internal" ] ;then
echo "please enter the name of the card that youare using at";
read -r card ;
ifconfig "$card" | grep 'inet addr' |cut -d':' -f2|cut -d ' ' -f1;
else
wget -qO- http://noc.co.il |grep "var VisitorCountry" | awk '{print$4}'|cut -d '"' -f4;
fi
}
My goal is that the function will quickly give me my IP by choosing internal or external
if I want to automatically displays the network card ("without the need to ask Which network card do you use(The computer automatically detects which network card the user uses and will put the name as a variable at the right commend for internal IP , how can I get him to identify what card the user use(WLAN0 WLAN1 etc.) ?
A system can have more than one IP address. Which one of them is the one you are looking for? You did not specify that.
There are multiple questions related to finding IP addresses with bash:
Find internal IP address
The accepted answer uses a deprecated option for hostname; the second answer is the more correct one IMHO.
In bash, is there a way to find the IP address for all interfaces?
Find IP address for my system
Bash script to find all IP addresses
If none of those float your boat, consider closing this question and posting a new one with more precise phrasing what you are looking for.

Check if a Samba share exists in local network

i'm trying to figure out how to make a script for check if a dir exist in the network and than backup a directory in the network. Unfortunatly the IP of this machine (Windows 7 with samba) is not static and everytime is changing.
at the moment what I do for backup my notebook is:
in W7 notebook, launch cmq and with ipconfig check the ip of the machine
in linux, go in /etc/hosts file and change the IP set for the notebook
launch rsnapshot manually or wait for the crontab to do it
now what I want to do is a script that does:
to check which IP is available in a range of IPs
check which one has a specific dir available
if both tests are ok, I change the hosts name with the IP and I lanunch the rsnapshot.
maybe a smartest way could be to check if the MAC Address is available in the network and which IP is associated to it and launch the rssnapshot after have changed the hosts or the rsnapshots.conf file
till now what I did is:
for ip in 192.168.1.{128..142}; do # for loop and the {} operator
ping -c 1 -t 1 $ip > /dev/null 2> /dev/null # ping and discard output
if [ $? -eq 0 ]; then # check the exit code
if [check if dir exists for ip $ip] #not sure how do this check
/usr/bin/rsnapshot daily
else
echo "${ip} is down"
fi
done
Use smbclient to list (-L) the shares ex. :
smbclient -L SERVERNAME | grep -i "YOURSHARENAME"

Resources