The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   OS X Developer (http://hintsforums.macworld.com/forumdisplay.php?f=27)
-   -   Perl advice needed (http://hintsforums.macworld.com/showthread.php?t=25344)

ibroughton 07-02-2004 01:13 PM

Perl advice needed
 
I have come across a small Perl script I'd like to use, but haven't got the faintest idea what to do with it. Basically it reports my IP address to my web server should my Mac get stolen.

The script is
---
#!/usr/bin/perl

sleep int(rand 60);
$network = `ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/tunnel/d' -e '/inet/p' | wc -l`;

$serial_number1 = `system_profiler 2> /dev/null | grep \"Customer serial number\"`;
@serial_number2 = split (' ', $serial_number1);
$url = "http://www.iainbroughton.com/$serial_number2[3].html";
$useragent = "Thief Killer (Mac OS X)";
if ( $network == 1 ) {
**$status = `curl -A \"$useragent\"$www.iainbroughton.com`;
}
---

but the resulting output gives me a load more stuff I don't really understand

---
#/usr/bin/perl
Percy:~ iain$
Percy:~ iain$ sleep int(rand 60);
-bash: syntax error near unexpected token `('
Percy:~ iain$ $network = `ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/tunnel/d' -e '/inet/p' | wc -l`;
-bash: =: command not found
Percy:~ iain$
Percy:~ iain$ $serial_number1 = `system_profiler 2> /dev/null | grep \"Customer serial number\"`;
grep: serial: No such file or directory
grep: number": No such file or directory
-bash: =: command not found
Percy:~ iain$ @serial_number2 = split (' ', $serial_number1);
-bash: syntax error near unexpected token `('
Percy:~ iain$ $url = "http://www.iainbroughton.com/$serial_number2[3].html";
-bash: =: command not found
Percy:~ iain$ $useragent = "Thief Killer (Mac OS X)";
-bash: =: command not found
Percy:~ iain$ if ( $network == 1 ) {
-bash: syntax error near unexpected token `{'
Percy:~ iain$ \302\240\302\240$status = `curl -A \"$useragent\" www.iainbroughton.com`;
% Total % Received % Xferd Average Speed Time Curr.
Dload Upload Total Current Left Speed
100 5037 100 5037 0 0 1898 0 0:00:02 0:00:02 0:00:00 4127
-bash: **: command not found
---

Do I need to compile this script? Do I need to make it executable, what file extension should it have?

yellow 07-02-2004 01:32 PM

No compilation needed. It's a script, not source code. And it should not just be copied and pasted to the Terminal, because it attempts to run each line individually (as you saw above).
Just copy the code you have into a file and name it whatever you want, with .pl as a suffix. Like foo.pl. Make it executable, thusly:

chmod +x foo.pl

Then run the executable script thusly:

./foo.pl

ibroughton 07-02-2004 02:03 PM

As simple as that? Wow! You guys are Mac GODS!!!

I followed your advice and now I get

Scalar found where operator expected at ./test.pl line 13, near "**$status"
(Missing operator before $status?)
syntax error at ./test.pl line 13, near "**$status "
Execution of ./test.pl aborted due to compilation errors.

hayne 07-02-2004 02:11 PM

The **$status doesn't make any sense in Perl.
It looks like you have some corruption in your copy of the script.

ibroughton 07-02-2004 02:27 PM

Quote:

Originally Posted by hayne
The **$status doesn't make any sense in Perl.

not sure what I need to do there then, I've tried removing the ** bit and now get

--
sed: option requires an argument -- e
usage: sed script [-Ean] [-i extension] [file ...]
sed [-an] [-i extension] [-e script] ... [-f script_file] ... [file ...]
sh: line 2: /0.0.0.0/d: No such file or directory

--

Basically all I want this script to do is to contact my web server with a specific/unique user agent so it is easy to identify the IP that it has come from. Has any one any other ideas for doing this?

nkuvu 07-02-2004 02:29 PM

There are some things with the script that don't make sense to me. The **$status is one of them. The use of $www is another.

I found the script with Google, and it looks like
Code:

#!/usr/bin/perl

sleep int(rand 60);
$network = `ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/tunnel/d' -e '/inet/p' | wc -l`;

$serial_number1 = `system_profiler 2> /dev/null | grep \"Customer serial number\"`;
@serial_number2 = split (' ', $serial_number1);
$url = "http://yourserver.edu/$serial_number2[3].html";
$useragent = "Thief Killer (Mac OS X)";
if ( $network == 1 ) {
$status = `curl -A \"$useragent\" $url`;
}

In this script the only thing you should change is 'yourserver.edu'. The $url should stay as it is.

Hmm. I copied and pasted the source from the page I linked to, and got ** before the $status in this post. Weird. Then posted into a text editor, and noticed that the two characters before the $status were not viewable. So definite weirdness from the copy and paste. And by looking at the source, there are two   characters before $status...

nkuvu 07-02-2004 02:50 PM

And just to amuse myself, I retyped this into a new file to make sure there were no other strange characters. I changed the script a bit. No reason to store into $status if we don't use it, so I just took it out. Also set the script to use strict, added comments, and removed extraneous variables.
Code:

#!/usr/bin/perl

use strict;

sleep int(rand 60);

# Change this to match your server name:
my $webserver = "http://yourserver.edu";

# Don't change anything below this unless you know what
# you're doing.  :)
my $network = `ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/tunnel/d' -e '/inet/p' | wc -l`;

my @serial_number = split ' ', `system_profiler 2>/dev/null | grep "Customer serial number"`;
if ($network == 1) {
    system "curl -A \"Thief Killer (Mac OS X)\" $webserver/$serial_number[3].html";
}


ibroughton 07-02-2004 02:51 PM

OK, I've edited it now to

-#!/usr/bin/perl

sleep int(rand 60);
$network = `ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e
'/0.0.0.0/d' -e '/tunnel/d' -e '/inet/p' | wc -l`;

$serial_number1 = `system_profiler 2> /dev/null | grep \"Customer serial
number\"`;
@serial_number2 = split (' ', $serial_number1);
$url = "http://www.iainbroughton.com/$serial_number2[3].html";
$useragent = "Thief Killer (Mac OS X)";
if ( $network == 1 ) {
$status = `curl -A \"$useragent\" $url`;
}
--

I still get the same error
--
sed: option requires an argument -- e
usage: sed script [-Ean] [-i extension] [file ...]
sed [-an] [-i extension] [-e script] ... [-f script_file] ... [file ...]
sh: line 2: /0.0.0.0/d: No such file or directory

--

Still stumped, and what is IP 0.0.0.0 anyway?

derekhed 07-02-2004 02:51 PM

Beware Copy and Paste
 
Quote:

Originally Posted by nkuvu
Hmm. I copied and pasted the source from the page I linked to, and got ** before the $status in this post. Weird. Then posted into a text editor, and noticed that the two characters before the $status were not viewable. So definite weirdness from the copy and paste. And by looking at the source, there are two   characters before $status...

I have also found that the default prefs for Terminal (if you are editing with pico for example), can add line feeds to your scripts. I would use BBEdit if you have it to make sure you know exactly what is going into your file.

Looking at the script some more, it looks like it is reporting the IP number as given by ifconfig. If your stolen computer is behind a router, then you are only going to get the private IP address like 192.168.0.X or something just as useless. I think you would be better off getting the outside IP address. There are scripts in the forums that will do that for you, I am using one myself. Let me know if you want and I'll post it.

My $.02

ibroughton 07-02-2004 03:08 PM

I've copied and pasted your script and still get

sed: option requires an argument -- e
usage: sed script [-Ean] [-i extension] [file ...]
sed [-an] [-i extension] [-e script] ... [-f script_file] ... [file ...]
sh: line 2: /0.0.0.0/d: No such file or directory
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
sh: line 2: Customer serial number: command not found

As for the BBEdit, is that an extra I need to install (yes, still green in the realms of Terminal!)

yellow 07-02-2004 03:20 PM

Not sure if this is the issue, but make sure that whatever editor you're using isn't trying to break up long lines like:

Code:

my $network = `ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/tunnel/d' -e '/inet/p' | wc -l`;
Which looks to my non-code-understanding-eyes as to why it's complaining that the "sed -e needs and argument".

derekhed 07-02-2004 03:25 PM

Bag it?
 
OK, let's back up a second and take a look at what we're trying to do here.

You want your computer to post your IP number in case it is stolen, right?

1. What IP number do you want to report?
2. Where is it going to report the number?
3. How often is this going to happen?

It looks like this script has some flaws in it. To me, the major one is using the ifconfig command to report the IP number. Because of the router problem I noted earlier, this is not the most useful way to get a valid IP number. For example, if I stole your computer and took it home, plugged it into my network and your script fired, it would report an IP number of 192.168.0.3 or something just as useless to you. You want the OUTSIDE IP number that my router gets from my ISP.

The second flaw (or my understanding is flawed here) is that I can't see how this information is posted anywhere. Maybe I am not seeing the whole script?

At any rate, I do the same thing you are trying to. I will post a separate set of instructions for that if you want to give it a try.

derekhed 07-02-2004 03:35 PM

Track a changing IP number remotely
 
Found it!

http://www.macosxhints.com/article.p...MOTE+ip+number

It looks like dyndns has changed their page format. This actually makes it simpler. My script now is just:
Code:

#! /bin/sh
curl -s http://checkip.dyndns.org>ipaddress.html

ftp <<**
open name.of.your.site
epsv4
cd htm
lcd
ascii
put ipaddress.html ipaddress.html
bye
**

Nothing fancy, but you can always see the IP number as reported by your machine. Run this every half hour or so with a cron job.

nkuvu 07-02-2004 03:37 PM

derekhed brings up a good point (a while ago, I'm a slow typist today :) ). How are you editing these files?

BBEdit is a text editor, from BareBones software. It's a nice editor, but not free. $179 or so.

So if you're using pico in the Terminal, you can either fix the newlines yourself, or modify the script so that it's unlikely to wrap. I find that long lines in pico are a pain in the... script. So I changed the script to use shorter lines. In this version no lines are longer than 56 characters, so unless your Terminal window is really small it shouldn't wrap, and so pico shouldn't introduce any funky newlines that would mess things up:
Code:

#!/usr/bin/perl

use strict;

sleep int(rand 60);

# Change this to match your server name:
my $webserver = "http://yourserver.edu";

# Don't change anything below this unless you know what
# you're doing.  :)
my $command = "ifconfig -a inet 2>/dev/null | ";
$command .= "sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' ";
$command .= "-e '/tunnel/d' -e '/inet/p' | wc -l";

my $network = `$command`;

$command = "system_profiler 2>/dev/null | ";
$command .= "grep \"Customer serial number\"";

my @serial_number = split ' ', `$command`;
if ($network == 1) {
    $command = "curl -A \"Thief Killer (Mac OS X)\" ";
    $command .= "$webserver/$serial_number[3].html";
    system $command;
}


ibroughton 07-02-2004 03:40 PM

Quote:

Originally Posted by derekhed
You want your computer to post your IP number in case it is stolen, right?

1. What IP number do you want to report?
2. Where is it going to report the number?
3. How often is this going to happen?

To clarify things,

1. Yes I want an EXTERNAL IP address to be reported.
2. The best thing I can think of (with this script) is to have it access my hosted web server which will record the IP address given and the referal agent (ie even though I am behind a router, it still knows my IP is 212.159.xxx.xxx). If I can create a unique referal agent, so instead of Mozilla/IE/Whatever, it reports "Your Mac is Here" even better.
3.How often ismy Mac going to be stolen? Never (I hope!!). How often will this script run, I don't know, once an hour or even less if I feel paranoid enough!

Any instructions that will help secure my Mac are welcome. Yes I know if someone was determined to steal it, then they would, but at least it would give me SOME hope of catching the little b*$****$!

nkuvu 07-02-2004 03:45 PM

Quote:

Originally Posted by derekhed
It looks like this script has some flaws in it. To me, the major one is using the ifconfig command to report the IP number. Because of the router problem I noted earlier, this is not the most useful way to get a valid IP number. For example, if I stole your computer and took it home, plugged it into my network and your script fired, it would report an IP number of 192.168.0.3 or something just as useless to you. You want the OUTSIDE IP number that my router gets from my ISP.

Good point. But not an issue. The ifconfig bit is only to determine if the network connection is available. If you run the whole ifconfig command complete with sed calls, it reports 1 or 0, indicating network availability.
Quote:

The second flaw (or my understanding is flawed here) is that I can't see how this information is posted anywhere. Maybe I am not seeing the whole script?
This is the whole script. The tidbit that I linked to earlier talks about setting this script to run via cron job. Okay, so it attempts to download a page from your webserver. What page?

It would attempt to download a page with your computer's serial number. That's from the system_profiler command. It doesn't matter if that page even exists on your web server, the logs will show the attempt. And the logs will also have the real IP address.

It's actually a clever setup if the person who stole the machine connects it to the net. And also assuming that your webserver is not your home machine.

nkuvu 07-02-2004 04:09 PM

I also found an error in the script, but it may just be due to changes in the report generated by system profiler (I'm guessing this script was written on something other than Panther).

The system profiler doesn't report a "Customer Serial Number", just three instances of "Serial Number". So the line
Code:

$command .= "grep \" Customer serial number\"";
needs to change to
Code:

$command .= "grep -i \"serial number\"";

derekhed 07-02-2004 04:15 PM

Ah, I get it now. Very nice...

I am guessing that by getting your machine's serial number, you can find it in the logs of your web server. I did have a problem with that. I am running 10.3.4 and my system_profiler command returns:

Serial Number: WS83N2H5T0 (ok, I made that up)

Point is that the text is not "Customer serial number". Plus it takes a looong time.

So I would change your grep command to:
Code:

$command = "system_profiler -detailLevel -2 2>/dev/null | ";
$command .= "grep -i \"Serial number\"";

This will also throw off your $serial_number array, so that line would have to be:
Code:

$command .= "$webserver/$serial_number[2].html";
Note the [2].

Can you think of any more improvements?

(dang! Took too long! Thanks nkuvu!)

nkuvu 07-02-2004 05:04 PM

I'm not sure why the serial number has to be generated dynamically. All you're looking for, really, is a unique identifier. I suppose it is a little easier to set up if the script determines the serial number, but since the end user has to change the web server name anyway, why not add the serial number also?
Code:

#!/usr/bin/perl

use strict;

sleep int(rand 60);

# Change this to match your server name:
my $webserver = "http://your.server.net";

# Change this to your serial number or other
# uniquely identifying information.
my $serial = "Q1234567890";

# Don't change anything below this unless you know what
# you're doing.  :)
my $command = "ifconfig -a inet 2>/dev/null | ";
$command .= "sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' ";
$command .= "-e '/tunnel/d' -e '/inet/p' | wc -l";

my $network = `$command`;

if ($network == 1) {
    $command = "curl -A \"Thief Killer (Mac OS X)\" ";
    $command .= "$webserver/$serial.html";

    system $command;
}

Which eliminates the possibility that future versions of the system_profiler change the name or order or something...

derekhed 07-02-2004 05:37 PM

On the other hand...
 
This script did originate from a site dedicated to more cluster and lab oriented solutions, i.e., universities and large organizations. I can imagine the desire to keep a general script around that would work on a large number of machines. Even in my case, I run three Macs and tweaking files for each one has driven me batty in the past. (I'm much better now, thank you.)

I would therefore grep insensitively for 'serial' while using the -detailLevel flag available to the system_profiler command in 10.3. This should avoid the discovery of other serial numbers not associated with the hardware. I don't have access to any 10.2 machines, so I can't test other system_profilers. I suppose you could check for other versions of the profiler in your script...

ibroughton 07-03-2004 07:12 AM

Yay!
 
After all that hard work, it finally does what it is supposed to do. The final code was altered to:-
---

#!/usr/bin/perl

use strict;

sleep int(rand 60);

# Change this to match your server name:
my $webserver = "http://www.iainbroughton.com";

# Don't change anything below this unless you know what
# you're doing. :)
my $command = "ifconfig -a inet 2>/dev/null | ";
$command .= "sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' ";
$command .= "-e '/tunnel/d' -e '/inet/p' | wc -l";

my $network = `$command`;

$command = "system_profiler -detailLevel -2 2>/dev/null | ";
$command .= "grep -i \"serial number\"";

my @serial_number = split ' ', `$command`;
if ($network == 1) {
$command = "curl -A \"Thief Killer (Mac OS X)\" ";
$command .= "$webserver/$serial_number[2].html";
system $command;
}

---

and now produces a very pretty entry on my server log file (Obviously I've altered the IP and serial for this posting!)
--
212.159.xxx.xxx - - [03/Jul/2004:11:41:13 +0100] "GET /W902103XPJH.html HTTP/1.1" 200 0 "-" "Thief Killer (Mac OS X)"
--

Thankyou so much! :)

ibroughton 07-03-2004 07:30 AM

The only thing I don't quite understand is the

$command = "system_profiler -detailLevel -2 2>/dev/null | ";
$command .= "grep -i \"serial number\""

as it doesn't show up anywhere, and the W902103XPJH.html was created manually by me. Should the serial number (as got automatically by the script) show up anyhere? At least it works though! :)

hayne 07-03-2004 07:39 AM

If you want to make this less noticeable, you should avoid running the system_profiler when not connected to a network.
To do this, just add the following line right after the line that sets the $network variable.

exit unless $network;

nkuvu 07-03-2004 07:44 AM

Doesn't show up anywhere?

The script won't create the HTML file, if that's what you're thinking. And really, the HTML file doesn't need to exist in order for this to work. If it doesn't, the log will show a 404 response (instead of the 200 that you quoted) but you'll still have all of the info you need.

If you're thinking that the curl command should save the HTML file somewhere, you'd be right. If the command had the proper options. What's happening as it stands is that the curl has a -A option, which sets the user agent. Then it downloads the file and sends it to standard output. If you run this script by itself you'll see the downloaded file displayed on the screen. If you wanted to save the file you'd need to add a -o or -O option to the curl command (read man curl for explanations of the options).

ibroughton 07-03-2004 08:39 AM

No, I didn't think it would create the HTML file for me, and no, the system serial number doesn't appear at all. I don't want the file saved locally. Sorry for sounding thick, but I don't really understand what this is doing other than making a stamp (either a 200 or a 404) in my servers log, displaying the correct IP address. Is it actually supposed to show anything up in the HTML file, or just show in the server log? :confused:

nkuvu 07-03-2004 08:59 AM

The point is just to put a stamp in the server log. The HTML file is irrelevant.

ibroughton 07-03-2004 09:01 AM

In which case we have succeeded! :)

hayne 07-03-2004 09:23 AM

Quote:

Originally Posted by ibroughton
In which case we have succeeded!

At the risk of saying the obvious, I'd like to point out that you haven't really tested this until you have taken your Mac to various other network locations (other ISPs, dialup, cable, DSL, with & without intervening router) and tried it there.

ibroughton 07-03-2004 10:41 AM

Well yes, but I don't have the luxury of a dial up account. I'll just have to take this as a suitable measure untill I can verify it further. I'm quite content with the way that this is working at the moment, I presume the way the script is written, it doesn't matter how the machine is connected to the internet, as long as there is a connection present?

hayne 07-04-2004 01:49 PM

Quote:

Originally Posted by ibroughton
I presume the way the script is written, it doesn't matter how the machine is connected to the internet

I was merely pointing out that I wouldn't be confident that this script would fulfill its purpose until I had tested it on someone else's Internet connection (and preferably several other connections of varying types). It may seem to work in theory, but that's the nature of software bugs - you don't realize the problem until after it fails and then it often seems obvious what the problem is. Right now you only know that it works on your system. You don't know if there is some dependency on the current configuration.


All times are GMT -5. The time now is 05:45 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.