How to add something after a line grep found? - bash

I would like to see whenever the ping to a specific server goes down.
So at the moment I have something like this: ping 8.8.8.8 | grep time=11 && date
This pings google and prints every line that has a ping of 11.x that is just for testing so that I have some output that is not there all the time but often enough that I can test this. And then I have && date that I thought would print the date when grep finds the string.. But it does not. So my question now Is how can I get it so that in every line that grep spits out I can append the current timestamp. Or what would be even better is to have it as a prefix in front of every line that grep spits out. Is this possible with one command? Or do I need a simple shell script?
Thanks in advance. I hope I get an answer soon. :)
Also merry x-mas to everyone!

See if it works for you:
ping 8.8.8.8 | while read line; do echo "$(date): $line"; done | grep time=13

You can also turn the setup around to check when a remote host becomes available by using while ! ping ... Example, in case your path to 8.8.8.8 goes down:
declare -i cnt=0; while ! ping -c 1 8.8.8.8; do ((cnt++)); echo "test '$cnt' - network down on $(date)"; sleep 60; done
Which will check once per-minute if the host 8.8.8.8 is available and report, for example:
test '10' - network down on Sat Dec 26 16:38:48 CST 2015
The script will terminate on its own once the network path is established.

Related

bash script to perform dig -x

Good day. I was reading another post regarding resolving hostnames to IPs and only using the first IP in the list.
I want to do the opposite and used the following script:
#!/bin/bash
IPLIST="/Users/mymac/Desktop/list2.txt"
for IP in 'cat $IPLIST'; do
domain=$(dig -x $IP +short | head -1)
echo -e "$domain" >> results.csv
done < domainlist.txt
I would like to give the script a list of 1000+ IP addresses collected from a firewall log, and resolve the list of destination IP's to domains. I only want one entry in the response file since I will be adding this to the CSV I exported from the firewall as another "column" in Excel. I could even use multiple responses as semi-colon separated on one line (or /,|,\,* etc). The list2.txt is a standard ascii file. I have tried EOF in Mac, Linux, Windows.
216.58.219.78
206.190.36.45
173.252.120.6
What I am getting now:
The domainlist.txt is getting an exact duplicate of list2.txt while the results has nothing. No error come up on the screen when I run the script either.
I am running Mac OS X with Macports.
Your script has a number of syntax and stylistic errors. The minimal fix is to change the quotes around the cat:
for IP in `cat $IPLIST`; do
Single quotes produce a literal string; backticks (or the much preferred syntax $(cat $IPLIST)) performs a command substitution, i.e. runs the command and inserts its output. But you should fix your quoting, and preferably read the file line by line instead. We can also get rid of the useless echo.
#!/bin/bash
IPLIST="/Users/mymac/Desktop/list2.txt"
while read IP; do
dig -x "$IP" +short | head -1
done < "$IPLIST" >results.csv
Seems that in your /etc/resolv.conf you configured a nameserver which does not support reverse lookups and that's why the responses are empty.
You can pass the DNS server which you want to use to the dig command. Lets say 8.8.8.8 (Google) for example:
dig #8.8.8.8 -x "$IP" +short | head -1
The commands returns the domain with a . appended. If you want to replace that you can additionally pipe to sed:
... | sed 's/.$//'

Another parsing bash script output to variables

I know this has been asked before, and I have looked at the previous posts, but can't seem to get what I am trying to do working.
I know it's really basic, so I'm hoping this will be easy for most people on SO.
I want to create a simple bash script that pings an address, and then inserts the ping output into a csv file (or rather, into a file, separated with commas).
The ping command would be
ping -D google.com
and the output looks like
PING google.com (74.125.239.103) 56(84) bytes of data.
[1393992465.052723] 64 bytes from nuq05s01-in-f7.1e100.net (74.125.239.103): icmp_req=1 ttl=55 time=2.66 ms
I want to insert epoch time, ttl, and time into a file, separated by commas.
If it's easy enough, then it wouldn't hurt to convert to the epoch time to a date also, but this can be my next step in this simple project.
I figured out the command to convert epoch time to human format is
date -d #[epoch_time]
Side trivia - why do I need the #?
ping -D google.com | sed -n -e 2p -e 2q |
while read epoch b64 bytes from host ip icmp ttl time ms
do
date=$(date -d #$(sed 's/[][]//g' <<< "$epoch"))
ttl=$(sed 's/ttl=//' <<< "$ttl")
time=$(sed 's/time=//' <<< "$time")
echo "$date,$ttl,$time"
done >> file.csv
Clearly, you can extend the number of lines you analyze by adjusting the first sed command. You can probably do the editing within the loop with ${var/x/y} notation, but I don't think of doing that until I'm writing up at the end because I've spent longer working with shells where that wasn't an option than I have with bash. Are you sure you don't want the host or IP address information?
In the cold light of morning, there's an easy way to improve the code:
ping -D google.com | sed -n -e 2p -e 2q |
while read epoch b64 bytes from host ip icmp ttl time ms
do
epoch=${epoch#[}
epoch=${epoch%]}
date=$(date -d #${epoch})
echo "$date,${ttl#ttl=},${time#time=}"
done >> file.csv
It's a matter of choice whether you create the date variable or simply embed the $(date -d #${epoch}) directly in the echo argument.

Greping a tcpdump with tshark

I'm trying to program a little "dirty" website filter - e.g. an user wants to visit an erotic website (based on domain name)
So basically, I got something like
#!/bin/bash
sudo tshark -i any tcp port 80 or tcp port 443 -V | grep "Host.*keyword"
It works great but now I need to do some actions after I find something (iptables and DROPing packets...). The problem I got is that tcp dumping is still running. If I had a complete file with data, the thing I'm trying to reach is easy to solve.
In pseudocoude, I'd like to have something like:
if (tshark and grep found something)
iptables - drop packets
sleep 600 # a punishment for an user
iptables accept packets I was dropping
else
still look for a match in the tcp dump that's still running
Thanks for your help.
Maybe you could try something like the following:
tshark OPTIONS 2>&1 | grep --line-buffered PATTERN | while read line; do
# actions for when the pattern is found, the matched input is in $line
break
done
The 2>&1 is important so that when PATTERN is matched and the while loop terminates, tshark has nowhere to write to and terminates because of the broken pipe.
If you want to keep tshark running and analyze future output, just remove the break. This way, the while loop never terminates and it keeps reading the filtered output from tshark.

Mac ping but only display avg ms

What I want is to ping a server but only want the avg time to be returned, I think grep or something like that would help but a google search doesn't return much useful.
This is to go into a geektool script that will display a servers ping for me to see if its up.
Needs to be a script / command that will work in terminal as I need to pull it over to python as well.
Thanks
Somehow on my system ping command doesn't output round-trip but rtt.
So this one is going to work better:
ping -q -c 5 google.com | tail -n 1 | cut -f 5 -d '/'
-q makes it less verbose because we don't need much of the output anyway. tail simply returns the last line of the output
How about something like:
ping -c 5 google.com | grep "round-trip" | cut -f 5 -d "/"

Discovering public IP programatically in bash on Linux

I found a post that does what I need, but on Windows:
Discovering public IP programmatically
> tracert -d www.yahoo.com
`Tracing route to www-real.wa1.b.yahoo.com [69.147.76.15]
over a maximum of 30 hops:`
1 <1 ms <1 ms <1 ms 192.168.14.203
2 * * * Request timed out.
3 8 ms 8 ms 9 ms 68.85.228.121
4 8 ms 8 ms 9 ms 68.86.165.234
5 10 ms 9 ms 9 ms 68.86.165.237
6 11 ms 10 ms 10 ms 68.86.165.242
The 68.85.228.121 is a Comcast (my provider) router. We can ping that:
ping -r 9 68.85.228.121 -n 1
Pinging 68.85.228.121 with 32 bytes of data:
Reply from 68.85.228.121: bytes=32 time=10ms TTL=253
Route: 66.176.38.51 ->
68.85.228.121 ->
68.85.228.121 ->
192.168.14.203
Voila! The 66.176.38.51 is my public IP.
This (third) answer shows a way to get my ISP's IP and then to use ping to get my IP.
It doesn't work unmodified on Linux. Traceroute works instead of tracert, but because its output is unpredictable, I'm not sure how to parse it.
I got as far as
IP="$(traceroute -d www.yahoo.com | grep ' 2 ' | sed -e 's/.*(\(.*\)).*/\1/')"
but the grep is (poorly) hard coded. I didn't see how to get ping to work as in the example.
Any input would be appreciated.
Personally, I'd run this command:
wget -qO- whatismyip.org
I just combined what #pizza said with this answer and produced the following working script. It's not as nice as using something like traceroute, but it's a lot less complicated.
#!/bin/bash
content="$(wget http://checkip.dyndns.org/ -q -O -)"
myip="$(<<< "$content" sed -e 's/.*Current IP Address: //' -e 's/<.*//')"
echo "myip = [${myip}]"
The wget command retrieves the result of asking dyndns for my IP. Then, sed chops off everything before and after the IP address dyndns returns.
As noted elsewhere, websites such as dyndns may block such requests if they are made too frequently, but since your IP should remain constant in most situations for at least the duration of your session, if not for many days, it shouldn't be necessary to run this script very often.
This is not a reliable solution, a passive way to do this is to write a script to pull your own router's "WAN" status page. You can do that as many times as you want and nobody will complain about excessive probing.
ok, i know this is an old thread, but this posting revealed some things to me, and combining it with what I've already learned, I think I've come up with a solid solution.
The grep you want is:
grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
My personal solution to find my external IP used to be:
curl icanhazip.com
Now it is:
ISP=`traceroute -M 2 -m 2 8.8.8.8 | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'` | ping -R -c 1 -t 1 -s 1 $ISP | grep RR | grep -m 1 -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' > .extIP
and then
cat .extIP
Have fun!
IF what you want is simplicity, AND you don't mind relying on other servers (or services) try:
dig +short myip.opendns.com #resolver1.opendns.com
That will spit out your address only
or,
#!/bin/bash
myip="$(dig +short myip.opendns.com #resolver1.opendns.com)"
echo "myip = [${myip}]"

Resources