Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 214
  • Last Modified:

Perl Script to append xml file

I have an xml file like below.

 <interface type='network'>
      <mac address='52:54:00:a3:24:30'/>
      <source network='phybrid'/>
      <target dev='vnet3'/>
      <alias name='net1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </interface>

I want a perl script which adds below lines to this

<filterref filter='clean-traffic'>
        <parameter name='IP' value='1.2.3.1'/>
        <parameter name='IP' value='3.2.3.3'/>
      </filterref>

So the final output should be like below

<interface type='network'>
      <mac address='52:54:00:fc:70:00'/>
      <source network='phybrid'/>
      <target dev='vnet3'/>
      <filterref filter='clean-traffic'>
        <parameter name='IP' value='1.2.3.1'/>
        <parameter name='IP' value='3.2.3.3'/>
      </filterref>
      <alias name='net1'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
0
pehalwaan
Asked:
pehalwaan
  • 15
  • 11
  • 5
3 Solutions
 
wilcoxonCommented:
The simplest (possibly naive version) would be:
$xml =~ s{(<target dev=.*?/>)$}{$1\n    <filterref filter='clean-traffic'>\n        <parameter name='IP' value='1.2.3.1'/>\n        <parameter name='IP' value='3.2.3.3'/>\n    </filterref>}msg;

Open in new window

0
 
pehalwaanAuthor Commented:
This is not working. Can you please give me a script which accepts xml file as an argument

I would really appreciate it
0
 
wilcoxonCommented:
What's not working?  Here's an alternate way to do it as a one-liner command...
perl -pe -i.bak 's{(<target dev=.*?/>)$}{$1\n    <filterref filter=\'clean-traffic\'>\n        <parameter name=\'IP\' value=\'1.2.3.1\'/>\n        <parameter name=\'IP\' value=\'3.2.3.3\'/>\n    </filterref>}' <filename>

Open in new window


One side questions - why does your XML use single quotes around attribute values?  Both are valid but double quotes is the norm in XML.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
pehalwaanAuthor Commented:
KVM
This is what i get while running. These are KVM xml files. These are auto-generated when we create kvm's.

I am unable to work with one liners. Can you provide a detailed script.
0
 
ozoCommented:
perl -i.bak -pe "s#(\s*)(?=<alias name)#\$1<filterref filter='clean-traffic'>\n\$1 <parameter name='IP' value='1.2.3.1'/>\n\$1 <parameter name='IP' value='3.2.3.3'/>\n\$1</filterref>#" file.xml
0
 
pehalwaanAuthor Commented:
There are many other occurrences of aliasname which are getting replaced too in the file.

What i am trying out is parsing the xml file and appending my new lines in interface tag.

Please suggest if you have some better approach
0
 
ozoCommented:
perl -i.bak -pe "s#(\s*)(?=<alias name='net1'/>)#\$1<filterref filter='clean-traffic'>\n\$1 <parameter name='IP' value='1.2.3.1'/>\n\$1 <parameter name='IP' value='3.2.3.3'/>\n\$1</filterref>#" file.xml
0
 
wilcoxonCommented:
Sigh.  I forgot the -i has to go before the -e.  Try this one-liner.  If there are other instances of "alias name" and "target dev", you will very likely have to do as you suggest (and actually parse the XML).
perl -i.bak -pe "s{(<target dev=.*?/>)$}{$1\n    <filterref filter='clean-traffic'>\n        <parameter name='IP' value='1.2.3.1'/>\n        <parameter name='IP' value='3.2.3.3'/>\n    </filterref>}" test1.xml

Open in new window

0
 
pehalwaanAuthor Commented:
These one liners are wonderful and work perfectly. But can you help me with the script because IP values coming in this will be not fixed , they will be coming as arguments in my production environment
0
 
ozoCommented:
perl  -MO=Deparse -i.bak -pe "s#(\s*)(?=<alias name='net1'/>)#\$1<filterref filter='clean-traffic'>\n\$1 <parameter name='IP' value='1.2.3.1'/>\n\$1 <parameter name='IP' value='3.2.3.3'/>\n\$1</filterref>#"

BEGIN { $^I = ".bak"; }
LINE: while (defined($_ = <ARGV>)) {
    s[(\s*)(?=<alias name='net1'/>)][$1<filterref filter='clean-traffic'>\n$1 <parameter name='IP' value='1.2.3.1'/>\n$1 <parameter name='IP' value='3.2.3.3'/>\n$1</filterref>];
}
continue {
    die "-p destination: $!\n" unless print $_;
}
0
 
wilcoxonCommented:
For a script version, try this...
use strict;
use warnings;
use Tie::File; # not strictly necessary but I like it when editing files
my $fil = shift or die "Usage: $0 file ip1 ... ipX\n";
tie my @lines, 'Tie::File', $fil or die "could not open $fil: $!";
# may need to restructure next line
# can't remember if @lines gets recalced each iteration or not
for my $i (0..@lines-1) {
    if ($lines[$i] =~ m{^(\s+)<target dev=.*?/>\s*$}) {
        my $spc = $1;
        splice @lines, $i+1, 0, "$spc<filterref filter='clean-traffic'>", map({ "$spc    <parameter name='IP' value='$_'/> } @ARGV), "$spc</filterref>";
    }
}
untie @lines;

Open in new window

0
 
pehalwaanAuthor Commented:
When using this one liner inside my perl script it gives below error

String found where operator expected at /usr/local/sbin/KVM3.pm line 414, near "n"    /etc/libvirt/qemu/$cust_id-$server_id.xml""
syntax error at /usr/local/sbin/KVM3.pm line 414, near ""perl -i.bak -pe "s#(\s*)(?=<source network='pyhbrid'/>)#\$1<filterref filter='clean-traffic'>\n\$1 <parameter name='IP' value='$wan_primary_ip'/>\n\$1</filterref>#"

Can you help write a simple formatted code for this. This is very urgent
0
 
ozoCommented:
this is how a one liner can be converted into a script
perl -MO=Deparse  -Mwarnings -Mstrict -i.bak -pe "s#(\s*)(?=<source network='pyhbrid'/>)#\$1<filterref filter='clean-traffic'>\n\$1 <parameter name='IP' value='$wan_primary_ip'/>\n\$1</filterref>#"
BEGIN { $^I = ".bak"; }
use warnings;
use strict;
LINE: while (defined($_ = <ARGV>)) {
    s[(\s*)(?=<source network='pyhbrid'/>)][$1<filterref filter='clean-traffic'>\n$1 <parameter name='IP' value=''/>\n$1</filterref>];
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK
0
 
pehalwaanAuthor Commented:
I have written a script to change root password directly in shadow file. Below it is

my $admin_password=shift;
my $password_salt=qx{perl -e 'print crypt("$admin_password","\$6\$saltsalt\$") . "\n"'};
print "$password_salt";
qx{perl -pe 's|(root):(\$.*?:)|\1:\$6\$SALTsalt\$$password_salt:|' shadow > shadow.new};

When i run these perl commands from command line, they work fine, but when i write them in a pl file and run pl file, i get below errors.

perl p.pl dfr
Final $ should be \$ or $name at -e line 1, within string
syntax error at -e line 1, near ","$6$saltsalt$""
Execution of -e aborted due to compilation errors.

I am unable to stat what is wrong here. Can anybody help
0
 
ozoCommented:
Did you mean
my $password_salt=qx{perl -e 'print crypt("$admin_password","\$6\$saltsalt\\\$") . "\n"'};        
Or easier
my $password_salt=crypt($admin_password,"$6$saltsalt\$")."\n";
0
 
pehalwaanAuthor Commented:
easier method is working but not replacing new salt in shadow file
0
 
ozoCommented:
Neither $6 nor $SALTsalt seems to be defined in
qx{perl -pe 's|(root):(\$.*?:)|\1:\$6\$SALTsalt\$$password_salt:|' shadow > shadow.new};
and it doesn't replace anything in shadow file, it would replace in shadow.new file
and are you sure that qr|(root):($.*?:)| matches in shadow file?
0
 
pehalwaanAuthor Commented:
below is pattern in shadow.new file

root:$6$izkFWw9QZFNE7Y6B$5LgqIJPO1LT9WTq/DgThqzuYNq8QmOwpkVnC0aWdU727kdljidRXe1WVT2wlqn1RS6MLCOMEjTSbVzC5YTBYa1:16007:0:99999:7:::

And i didn't get your point of $6 and $SALT
0
 
ozoCommented:
Did you want
{local @ARGV=("shadow");
local $^I=".old";
s/(?:^root:)[^:]/$saltsalt$password_salt/ and print while <>;
}
0
 
ozoCommented:
Since $6 and $SALTsalt are in "" quotes, the -e script will try to interpolate it.
Did you mean to say \\\$6$saltsalt
0
 
pehalwaanAuthor Commented:
No. My just motive is to change root password by replacing "hashed password " in shadow file. As i mentioned, if i run these one liners from command line, they work completely fine.

Can you help me get the correct script
0
 
pehalwaanAuthor Commented:
Any suggestions/answers
0
 
ozoCommented:
I made a couple of suggestions.  If you find them unsuitable, I am unsure what kinds of improvements you would require.
0
 
pehalwaanAuthor Commented:
Please help me fix this

SCRIPT

#!/usr/bin/perl

my $admin_password=shift;
my $password_salt=qx{openssl passwd -1 $admin_password};    ##### Generate
print "$password_salt";
$old_password_salt=qx{cat shadow.new | grep root | cut -d: -f2};
print "$old_password_salt";
qx{sed -i -e 's|$old_password_salt|$password_salt|g' shadow.new};

OUTPUT

perl p.pl bghuin
$1$tOuKv7mH$HKHlphoXl4LTSRUXWqWvM.
$6$izkFWw9QZFNE7Y6B$5LgqIJPO1LT9WTq/DgThqzuYNq8QmOwpkVnC0aWdU727kdljidRXe1WVT2wlqn1RS6MLCOMEjTSbVzC5YTBYa1
sed: -e expression #1, char 108: unterminated `s' command

PLEASE HELP.
0
 
pehalwaanAuthor Commented:
PLEASE REPLY
0
 
pehalwaanAuthor Commented:
Please HELP
0
 
ozoCommented:
chomp $password_salt;
chomp $old_password_salt;
0
 
ozoCommented:
Or

#!/usr/bin/perl
my $admin_password=shift;
my $password_salt=qx{openssl passwd -1 $admin_password};    ##### Generate
print $password_salt;
chomp  $password_salt;
@ARGV=("shadow.new");
$^I="";
while( <> ){
    s/:([^:]*):/:$password_salt:/ && print STDERR "$1\n" if /root/;
    print;
}
0
 
pehalwaanAuthor Commented:
I've requested that this question be deleted for the following reason:

Solved it
0
 
wilcoxonCommented:
ozo and I both provided significant help on this question.  The person asking often would just reply with things like "help" without any details about what was not working.  The asker never responded with what was not working in either my final script or ozo's final script.  As such, it seems like at least the majority of the points should be distributed.
0
 
pehalwaanAuthor Commented:
@All-

I am sorry for the action. One of my team members deleted it. I am accepting the solution.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 15
  • 11
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now