Shell commands can be combined into programs (or "scripts") which can be run at any time. All that you need to do is save all the commands you want to run in a text file, with a "shebang" at the top (the characters "#!") followed by the shell you are using, and set the file to be executable by using (you guessed it) the shell command "chmod +x script.sh" (assuming your script was called "script.sh"). You can then run it by typing the path of the file, for example /Users/owen/Documents/script.sh.
Here's an example script, which lists all of the devices on a small IP network, followed by an explanation of how it works...
#!/bin/sh s="192.168.1." for i in {1..254} do echo ".\c" p=`ping -c 1 -W 500 $s$i | grep '1 packets received'` if [ "$p" != "" ]; then echo echo "$s$i responded" fi done echo echo "Scan complete"
#!/bin/sh. This line tells the system which shell to use (in this case the standard shell "sh"). The shebang (#!) is just a syntax element identifying this command.
s="192.168.1.". On this line, s is a variable and I assign the first 3 bytes of the addresses I want to search through. Note the final dot, inside the double quotes, which becomes part of the address when a final number is appended (see later).
for i in {1..254}. This sets up a loop which uses a variable i to vary from 1 to 254 (the possible values of the final byte of an IP address) in the following instructions, and "do" is just a syntactic element which shows the start of the for loop. The end of the loop is the "done" command (see later). So all the commands between do and done are executed 254 times with the variable i holding the current value from 1 to 254.
echo ".\c". Echo is a command which displays something on the screen, in this case a single dot. The "\c" just means don't start a new line after this is displayed. In general, the backslash character means interpet the next letter as in a special way.
p=`ping -c 1 -W 500 $s$i | grep '1 packets received'`. This is a bit more complex. The key is that there are two commands, separated with a pipe (|) which sends the output from the first command to the second. So here's an explanation...
The first part p= just means to take the output of all the rest (which is inside back ticks (`) meaning it should be evaluated as a value) and put it in a variable called "p".
The second part is the ping command which sends a small message to another computer and waits for a reply. This is used to check a computer at that address is running. The "-c 1" part means send only one ping, the "-W 500" means wait 500 milliseconds for a reply, and the "$s$i" means insert the values of the two variables s and i. Remember that s contains "192.168.1." and i changes from 1 to 254 as it loops.
The third part of the line is a grep command. This is the "global regular expression parser" which is a utility used for searching for strings. In this case it looks for the string "1 packets received" inside the output for the grep and only passes on results where this is found. So only successful pings will be processed and if that string isn't found the result (which is stored in the variable p) will be empty.
if [ "$p" != "" ]; then. This is an if statement which checks if the variable "p" is empty. The commands from here up to the end of the if (fi) will only be run if p doesn't equal (!=) nothing ("").
echo. Display a blank line, and echo "$s$i responded". Shows the name of the computer which responded to the ping. fi. The end of the if block, and done. The end of the for block. echo. Another blank line, and echo "Scan complete". Just displays a message to show all addresses have been checked.
So we have created a useful little utility to identify which computers are running on a home network. Note that almost all home networks use IP addresses where the first 3 bytes of the address stay the same and each device has a unique byte 4. The 3 bytes 192.168.1 are reserved for this use but other common sequences are 10.0.0, 172.16.0, and 192.168.0. Just look at the address of any computer to find what these are on your network and change the value next to s= appropriately. And yes, I know I could have passed that as a parameter to the script!
I usually write a blog post about once a week. The latest post can be viewed here: Unity Through Division: Sometimes hard decisions need to be made to make genuine progress. (posted 2024-11-18 at 19:13:00). I do podcasts too!. You can listen to my latest podcast, here: OJB's Podcast 2024-08-22 Stirring Up Trouble: Let's just get every view out there and fairly debate them..