How to disable error message sent by command "ping"? - bash

I wrote a simple ping sweeper using bash script. I also use grep command to filter out the result I want. The problem is, the console keep printing out error message: "ping: recvmsg: No route to host" no matter what grep command I tried. I tried to write the output into a file, and there is no error message inside the file but they still appear on the console. I want to know what causes the console to print out error message like that and how to disable it, thanks.
Here is the script I wrote.
#!/bin/bash
for ip in $(seq 1 254); do
#ping -c 1 10.11.1.$ip | grep -v "recvmsg" | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1 &
ping -c 1 10.11.1.$ip | grep -v "recvmsg" |grep -v "ping" | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1| sort -d >> report &
done
wait
And here is the error message
ping: recvmsg: No route to host

You can use the redirectors for stderr (standard error) you only need put this at the end of your command 2> error.log
#!/bin/bash
for ip in $(seq 1 254); do
#ping -c 1 10.11.1.$ip | grep -v "recvmsg" | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1 &
ping -c 1 10.11.1.$ip 2> error.log | grep -v "recvmsg" |grep -v "ping" | grep "bytes from" | cut -d " " -f 4 | cut -d ":" -f 1| sort -d >> report &
done
wait

Related

Check ip is present within file & update iptables bash script

I want to check that the ip is present within the ccd folder and push the ip route to the FORWARDING chain in the iptables. Im new to bash scripting and need a little help finishing this script.
client file in /etc/openvpn/ccd :
ifconfig-push 10.8.0.45 255.255.255.0
push 'route 10.10.0.45'
I need to grep 10.8.0.45 & 10.10.0.45
and push those routes in the iptables.
e.g
iptables -A FORWARD -s 10.8.0.45 -d 10.10.0.45 -j ACCEPT
client-connect /etc/openvpn/on_connect.sh
script I need help with 'grep' or 'awk'
static_ip= cat $CCD_DIR/$common_name | grep -w "ifconfig-push" | awk -F ' ' {'print $2'}
ip_destination=cat $CCD_DIR/$common_name | grep -w "push 'route" | awk -F ' ' {'print $3'} | tr -d "'"
#!/usr/bin/env bash
#
# Add iptables rules based on CCD client config.
#
CCD_DIR="/etc/openvpn/ccd"
RULE_COMMENT="FORWARD"$common_name
static_ip=cat $CCD_DIR/$common_name | grep -w "ifconfig-push" | awk -F ' ' {'print $2'}.
ip_destination=cat $CCD_DIR/$common_name | grep -w "push 'route" | awk -F ' ' {'print $3'} | tr -d "'"
if [ -f $CCD_DIR/$common_name ]; then
sudo iptables -A FORWARD -s $static_ip -d ip_destination -j ACCEPT
fi
exit 0
Edit: I think my usage of cat is wrong .
Try like this.
static_ip=$( cat $CCD_DIR | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | grep -E '(^|\s)10.8.0.45($|\s)' )
ip_destination=$( cat $CCD_DIR | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | grep -E '(^|\s)10.10.0.45($|\s)' )
So first you grep all IP's address in file and then you search exactly what you need
Edited after your comment.
If I understand correctly,
"ifconfig-push" - Is only one peer ccd file ?
so you can use this :
static_ip=$( grep -w "ifconfig-push" | awk -F ' ' {'print $2'})
For the rest in "push route" you need to use loop to find all matching ip address and put them to the iptables.
if [ -f $CCD_DIR/$common_name ]
then
cat $CCD_DIR | awk -F 'route' {'print $2'} | awk -F ' ' {'print $1'} | sed '/^$/d' | grep -E "\b(10)\.(8)\.(0)\.|(10)\.(10)\.(0).\b" | while read ip_destination
do
sudo iptables -A FORWARD -s $static_ip -d ip_destination -j ACCEPT
done
fi

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.

Bash Stdout redirect on solaris 10

ok this is working:
trace -t lstat64 -v lstat64 ls "myfilename" 2>pipefile
cat pipefile | grep ct | cut -d '[' -f 2 | cut -d ' ' -f 2
But i dont want to have to use the file "pipefile", how can i redirect the output straight to my grep and cut?
So, you want to ignore stdout and only consider stderr?
trace -t lstat64 -v lstat64 ls "myfilename" 2>&1 1>/dev/null |
grep ct | cut -d '[' -f 2 | cut -d ' ' -f 2
First, the stderr file handle is redirected to whatever the stdout file handle refers to, then the stdout file handle is redirected to /dev/null. Then grep can read from stdin whatever is emitted from trace's stderr.
I got it, I just realized i was getting stderr confused with stdout, this was my solution:
trace -t lstat64 -v lstat64 ls "myfilename" 2>&1 | grep ct | cut -d '[' -f 2 | cut -d ' ' -f 2

Bash output to multiple variales

I'm creating a script in Bash to change all MAC addresses of my PC. I can list all network interfaces with this:
ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo
And the output of the script is:
eth0
wlan0
Now I need to create a variable for each network interface (to use it in the future), but I don't know how, and Google didn't help me...
Answer:
readarray -t interfaces < <(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo)
echo "${interfaces[0]}" # prints eth0
echo "${interfaces[1]}" # prints wlan0
And to loop over them use for:
for curInterface in "${interfaces[#]}"; do
echo "$curInterface"
done
But there are better ways to parse data:
First of all, instead of grepping < character you can use -o flag. This will output all of the data on single lines. Then you simply need the second word without : character. This is very simple in pure bash:
interfaces=()
while read -r _ curInterface _; do
interfaces+=("${curInterface%:}")
done < <(ip -o link)
Store the output in an array:
interfaces=( $(ip link | awk '/</ { print $2 }' | awk -F: '!/lo/ {print $1}') )
You can create an array from this output, and loop through it after.
my_array=( $(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo) )
You can also this exmaple giving different alternatives redirect output to array
And I could have it simpler like this with one awk command:
readarray -t youravar < <(exec ip link | awk -F': ' '/^[0-9]+:/&&!/ lo: /{print $2}')

Too many arguments error in shell script

I am trying a simple shell script like the following:
#!/bin/bash
up_cap=$( cat result.txt | cut -d ":" -f 6,7 | sort -n | cut -d " " -f 2 | sort -n)
down_cap=$( cat result.txt | cut -d : -f 6,7 | sort -n | cut -d " " -f 6| sort -n)
for value in "${down_cap[#]}";do
if [ $value > 80000 ]; then
cat result.txt | grep -B 1 "$value"
fi
done
echo " All done, exiting"
when I execute the above script as ./script.sh, I get the error:
./script.sh: line 5: [: too many arguments
All done, exiting
I have googled enough, and still not able to rectify this.
You want
if [ "$value" -gt 80000 ]; then
You use -gt for checking if A is bigger than B, not >. The quotation marks I merely added to prevent the script from failing in case $value is empty.
Try to declare variable $value explicitly:
declare -i value
So, with the dominikh's and mine additions the code should look like this:
#!/bin/bash
up_cap=$( cat result.txt | cut -d ":" -f 6,7 | sort -n | cut -d " " -f 2 | sort -n)
down_cap=$( cat result.txt | cut -d : -f 6,7 | sort -n | cut -d " " -f 6| sort -n)
for value in "${down_cap[#]}";do
declare -i value
if [ $value -gt 80000 ]; then
cat result.txt | grep -B 1 "$value"
fi
done
echo " All done, exiting"

Resources