-1

I have built a program which involves pinging specified IP addresses to tell whether they are active or not.

repeat for IPaddress in allIPaddresses
try
    do shell script "ping -o -t 1 -c 1 " & IPaddress
    set goodIPs to (goodIPs & IPaddress) -- where goodIPs is a list of online IPs
end try
end repeat

The problem is that it will cycle through a lot of IPs if needed and the interface freezes up while it is pinging - so if you needed to hit the "Quit" button, you can't and Force Quitting is the only way to stop it. After searching around for how to run the command as a background process, I found the most common answer (eg https://discussions.apple.com/thread/323661?start=0&tstart=0) was to add:

> /dev/null 2>&1 &

or slight (but similar output) variations of that to the end of the shell command. But that involves sending the stderr away from the application, and since my program needs the stderr to tell if the ping was successful or not, this is not an option. Does anyone know how to keep stderr normal but move the command to a background process so that the interface works as normal?

DJpotato
  • 17
  • 7
  • Consider pinging, say 64, hosts in parallel with a 2-second timeout. It'll take around 2 seconds... http://stackoverflow.com/a/25790774 – Mark Setchell Aug 23 '15 at 08:56
  • thanks for the reply and that would be amazing, how do you use 'parallel' in a command, I tried using it but it said that parallel is not a command? Additionally, there is no for loop in my script, just a repeat loop for each IP address. I'll update my question to show – DJpotato Aug 23 '15 at 10:15
  • The easiest way to install GNU Parallel, or *lots* of other interesting Open Source software, is to use `homebrew` as your package manager since Apple do not provide one. You go to http://brew.sh and download the one-line installer and run it in Terminal. Then you can install GNU Parallel with `brew install parallel`. – Mark Setchell Aug 23 '15 at 11:10
  • Thanks, I have home-brew and I'll install that, but I assume that it will only work with computers which have that installed, meaning less portability. Is there a solution that does not require a home-brew download, or is there a way to include the necessary files into the app itself? – DJpotato Aug 24 '15 at 06:00
  • What is *"a lot"* of addresses - 60? 8000? – Mark Setchell Aug 24 '15 at 11:26
  • 255 would be average (x.x.x.1-255) but it also has a 'favourites' section and if you were really committed you could have more than that - 255 would be the usual maximum though – DJpotato Aug 24 '15 at 13:25

1 Answers1

0

Updated Answer

If you want to ping one at a time no matter how slow and show off the slow progress with a progress bar ;-)

ping -o -t 1 -c 1 192.168.0.1 > /dev/null 2>&1 && echo up

This will output up if the host is up, and nothing if it is down. Or if you want it to output down if the host is down:

ping -o -t 1 -c 1 192.168.0.1 > /dev/null 2>&1 && echo up || echo down

Second Answer

You could do it in the shell with a little script like this. Save it as pinger, and then make it executable with

chmod +x pinger

Then in your Applescript, you would need to write the list of IP addresses you want checked into a file called iplist.txt and use

do shell script /path/to/wherever/pinger

and grab its output.

You can try it in the Terminal with

./pinger

Here is the script.

#!/bin/bash
# pinger
#
# Remove results of any previous runs, but suppress any error messages
rm hostup-* 2> /dev/null

# Ping all hosts in "iplist.txt" ...
# ... and create file "hostup-<IP ADDRESS>" for any that are up
while read ip; do
   ( ping -o -t 1 -c 1 $ip > /dev/null 2>&1 && touch hostup-$ip ) &
done < iplist.txt

wait # for all pings to finish

# Now go back through and see who answered
while read ip; do
   filename="hostup-$ip"
   if [ -f "$filename" ]; then
      rm $filename
      echo $ip
   fi
done < iplist.txt

Précis of Original Answer

Use GNU Parallel...

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • That is a nice solution, the only problem is that, since it is still a shell script, the interface freezes up - also, the progress bar no longer increments since the repeat loop is no longer there (my fault, I didn't mention the progress bar). This is much faster, but is there a solution, however slow, that fits into a repeat loop (i.e. one IP per loop) that won't freeze the interface, will allow progress bar advancing and is portable? Sorry, I know I'm being picky and I'm asking a lot. – DJpotato Aug 25 '15 at 08:45
  • Thank you so much, that last solution is perfect for the app. In addition, that script is good for mass pinging from terminal so I might use that in the future. Thanks again – DJpotato Aug 26 '15 at 02:57