Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Solaris - change hostname / ip / default-router-ip script

by Qiang (Friar)
on Feb 19, 2005 at 22:38 UTC ( [id://432791]=sourcecode: print w/replies, xml ) Need Help??
Category: Utility Scripts
Author/Contact Info
Description: I got bored when I had to change the ip/hostname from time to time on solaris 7 or 8 machines, there are too many files need to be changed!

you can change ip or hostname, or do both the same time. If the new ip is on different subnet from the old one. default router ip gets changed too (like the second example). two examples of running this script.

currently this script only prints out the command it is going to perform. To use it, comment out the following line in the script.

#print "\t $f changed\n" unless (system($cmd));
script -oldip [ip] -newip [ip] -oldhost [host] -newhost [host] script -oldip 1.2.1.1 -newip 1.2.3.100
I wish i could make this script shorter :)

UPDATE: adds \Q \E and \b also, don't trust user input (although in this case only myself) and validate it before processing.

#!/usr/bin/perl -w
#
use strict;
use Getopt::Long;

#;;;;;;;;;;;;
# tested on solaris 7 and 8
# change ip and hostname with submitted arguments from cmd
#
# change router ip as well if new ip is on different subnet
#;;;;;;;;;;;;

my ($opt_newip,$opt_oldip,$opt_newhost,$opt_oldhost);
my @ipFiles     = qw(/etc/hosts);
my @routerFiles = qw(/etc/defaultrouter);
my @hostFiles   = qw(/etc/hosts /etc/nodename /etc/hostname.hme0
                   /etc/net/ticlts/hosts /etc/net/ticots/hosts
                   /etc/net/ticotsord/hosts
                  );

GetOptions(
    'newip=s'   => \$opt_newip,
    'oldip=s'   => \$opt_oldip,
    'newhost=s' => \$opt_newhost,
    'oldhost=s' => \$opt_oldhost,
);
# none of the arguemnts supplied
if (!$opt_newip && !$opt_oldip && !$opt_newhost && !$opt_oldhost) {
    printHelp();
    exit;
}
# catch the case that the arguments are not supplied by pair
if ( ($opt_newip xor $opt_oldip) || ($opt_newhost xor $opt_oldhost) ) 
+{
    print "Error: need pair of arguemnts\n";
    printHelp();
    exit;
}

if ($opt_newip && $opt_oldip) {
    doReplace($opt_newip,$opt_oldip,\@ipFiles);
    # extract 1.2.3. from 1.2.3.4
    # comparing extracted subnets,
    # change router ip if subnets are different
    if ( (my ($subNew)=$opt_newip=~/(.*)\.\d+/) &&
         (my ($subOld)=$opt_oldip=~/(.*)\.\d+/)
       ) {
            doReplace($subNew,$subOld,\@routerFiles) unless ($subNew e
+q $subOld);
         
    }
}
if ($opt_newhost && $opt_oldhost) {
    doReplace($opt_newhost,$opt_oldhost,\@hostFiles);
}

sub doReplace {
    my ($new,$old,$files) = @_;
    my $regex="s/\Q\b$old\E/$new/g";
    foreach my $f (@$files) {
        my $cmd = "perl -i -pe '".$regex."' $f";
        print "cmd: $cmd\n";
        #print "\t $f changed\n" unless (system($cmd));
    }
}

sub printHelp {
    print "Change hostname and/ip in all config files for Solaris\n";
    print "Change router ip in config files as well base on supplied I
+Ps\n";
    print "eg: script -oldip [ip] -newip [ip] -oldhost [host] -newhost
+ [host]\n";
}
Replies are listed 'Best First'.
Re: Solaris - change hostname / ip / default-router-ip script
by graff (Chancellor) on Feb 20, 2005 at 23:48 UTC
    I think you might have a couple problems in the "doReplace" sub, because of how you build the replacement regex:
    my $regex = "s/$old/$new/g";
    • If you put "\Q" and "\E" around "$old" in that regex, the periods in the IP addresses and host names will only match literal periods; as it is, they will match any character (e.g. "123.1.3" also matches 123.1[012]3)
    • You also need to anchor that regex -- as it is, if $old is "box.my.dom", it matches "thisbox.my.dom" and "thatbox.my.dom"; the same applies to IP addresses, especially when doing your router files, where you change only the first three components -- if $opt_oldip is "123.123.123.4", your regex looks for any occurrence of "123.123.123", which would include "89.123.123.123"

    On top of that, you're taking it for granted that the command line option strings really are valid IP addresses and host names, and you're putting them into a shell command that you then pass to a single-arg system() call. Personally, I'd feel better if these were checked first -- better still if you don't put the one-liner perl script on the command line at all.

    In terms of simplifying things (while also fixing the problems above), you could consider something like this (untested):

    #!/usr/bin/perl use strict; use Getopt::Long; # ... define arrays of file names, then ... my ( $opt_ip, $opt_host ); GetOptions( 'ip=s' => \$opt_ip, 'host=s' => \$opt_host ); my $Usage = "Usage: $0 [-ip old:new] [-host old:new]\n"; die $Usage unless ( $opt_ip =~ /\S:\S/ or $opt_host =~ /\S:\S/ ); my $ipreg = qr/\d{1,3}(?:\.\d{1,3}){3}/; my $hostreg = qr/\w+(?:\.\w+){2,}/; if ( $opt_ip ) { $opt_ip =~ /($ipreg):($ipreg)/ or die "Bad value for -ip: $opt_ip\ +n $Usage"; my ( $old, $new ) = ( $1, $2 ); doReplace( $old, $new, 'IP', \@ipFiles ); s/.\d+$// for ( $old, $new ); doReplace( $old, $new, 'RTR', \@routerfiles ) if ( $old ne $new ); } if ( $opt_host ) { $opt_host =~ /($hostreg):($hostreg)/ or die "Bad value for -host: +$opt_host\n $Usage"; my ( $old, $new ) = ( $1, $2 ); doReplace( $old, $new, 'HOST', \@hostFiles ); } sub doReplace { my ( $old, $new, $typ, $files ) = @_; open TMP,">/tmp/$typ-config-editor.$$.perl" or die "can't write sc +ript file: $!" print TMP "s{\\b\\Q$old\\E\\b}{$new}\n"; close TMP; for my $f ( @$files ) { my $cmd = "perl -i .bak.$$ -p /tmp/$typ-config-editor.$$.perl +$f"; print "cmd: $cmd\n"; # system( $cmd ) or print "\t $f changed\n"; # (system returns exit status of $cmd: 0 for success) } }
    That still has the potential for trouble when editing the router files, if they contain any full IP addresses where the latter three components might match the first three components of the "old" IP address. If that's really a risk, you'll need to write a special one-liner script just for them.
      thanks for taking time correcting my code.

      I was being lazy not to check the arguments because i am the only one use this. well. no excuse.

      To the second suggestion(anchor one) you mentioned, i think a \b will do it. anchor requires the line start with that ip or hostname

      >>better still if you don't put the one-liner perl script on the command line at all.

      you put the regex in a seperate file then system calls it at once. that looks no much difference than directly calling it in the same perl script though.

        you put the regex in a seperate file then system calls it at once. that looks no much difference than directly calling it in the same perl script though.

        The difference is that in my version, the command line passed to system() contains only things that are created by the script itself -- including the name of a file that stores a temporary perl script to be run -- so the shell launched by system() won't do anything unexpected. In your version, where the content of the temp. perl script is included in the command line, unexpected things in the script (e.g. shell metacharacters that were not properly escaped) could cause the system() call to do things that you don't want.

        There might be a problem with the temp. perl script, and in my version, the perl job in the subshell would just exit with an error condition. In your version, the problem might be that some characters in the temp script are being interpreted by the shell.

        Another way around this is to use a multi-arg system() call.

Re: Solaris - change hostname / ip / default-router-ip script
by Taulmarill (Deacon) on Feb 21, 2005 at 09:25 UTC
    please read man sys-unconfig and tell me, why your script is better?
      okay. I have read it and I don't see how it is going to help me.

      the doc says that sys-unconfig is used to restore a system's configuration to an “as-manufactured” state, ready to be reconfigured again. and it removes few of the config files too. care to read it yourself??
      sys-unconfig manpage from sun.com

        AND it "Executes all system configuration applications."
        so sys-unconfig erases all your system configuration and let you configure them after the reboot. it's what your script wants to be and more.
        this is not intendet to be offense, but i just see no point in writing a script that does what you can do by only typing _one_ system command.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://432791]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2024-03-29 12:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found