LINUX.ORG.RU

Помогите спецы в perl, подтолкните в нужном направлении

 ,


1

1

Возникла необходимость следить и править некоторый файл config.conf, перетирает его определенный софт на который я не могу повлиять, это бинарник. Любезно предоставленный на халяву, нужно:

поискать строку с нужным IP и дополнить ее. Так с командной строки или в bash скрипте работает на ура.

perl -p -i -e 's\10.8.100.5/32\10.8.100.5/32, 192.168.0.0/24\g' config.conf

Но вставляя в perl скрипт

s\10.8.100.5/32\10.8.100.5/32, 192.168.0.0/24\g config.conf

Не работает, не могу понять почему. Передо мной книжка Энциклопедия Perl правда за 2002 год, но не помогает ничего не нашел ни в ней ни в инете. Выкрутился пока так в скрипте, но как то некрасиво дергать зубы через задний проход.

system('/usr/bin/perl -p -i -e "s\10.8.100.5/32\10.8.100.5/32, 192.168.0.0/24\g" config.conf');
★★★★

Не работает, не могу понять почему

Потому, что это не валидный код на perl. В однострочнике выше у тебя perl-кодом является только s\10.8.100.5/32\10.8.100.5/32, 192.168.0.0/24\g. Дальше в дело вступает параметр -p (см. man perlrun), который превращает твой код в

while (<>) {
    s\10.8.100.5/32\10.8.100.5/32, 192.168.0.0/24\g;
} continue {
    print or die "-p destination: $!\n";
}

Далее config.conf передается получившемуся скрипту в качестве парамера, и <> начинает из него читать (он читает из всех файлов из @ARGV, или из stdin, если там пусто)

Если все еще ничего не понятно, то брать книжку с верблюдом и читать до просветления

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)

Возникла необходимость следить и править некоторый файл config.conf, перетирает его определенный софт на который я не могу повлиять, это бинарник.

Как вариант, можно сделать chattr +i config.conf, тогда файл станет read-only. Если твой бинарник после этого не начнет вылетать, то на этом можно закруглиться.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Как вариант, можно сделать chattr +i config.conf

Нет это не вариант, бинарник все таки должен писать в conf, но пишет он и затирает мою домашнюю сетку. Это wireguard-ui все кинулись на удаленку и надо мне им генерить конфиги wg каждому, но вот видимо какой то баг закрался. Ибо в его базе (JSON) все вроде правильно по моему конфигу.

{
........................
        "allocated_ips": [
                "10.8.100.5/32"
        ],
        "allowed_ips": [
                "10.8.100.0/24",
                "192.168.0.0/24"
        ],
....................
}

но перепускает сервер, и остается только одно. Спасибо попробую еще поразбираться на досуге, хотя кое как пока выкрутился, хоть и не по красоте.

alex_sim ★★★★
() автор топика
Ответ на: комментарий от alex_sim

Это wireguard-ui ... видимо какой то баг закрался

Этот баг вроде бы год назад чинили https://github.com/ngoduykhanh/wireguard-ui/issues/77

Что-то там про ExtraAllowedIPs в итоге, как я понял.

Просто погуглил.

Toxo2 ★★★★
()
Ответ на: комментарий от Toxo2

Этот баг вроде бы год назад чинили https://github.com/ngoduykhanh/wireguard-ui/issues/77

была у меня старенькая версия, и тоже полдумал, что надо обновить, кто то же наступил на грабли и исправили, но в последней версии тоже самое, вот и стал изобретать велосипед.

Почитал по ссылке, пока ответа не нашел, регистрируюсь чтоб прочесть все. Добавил в ExtraAllowedIPs эфекта нет. Спасибо.

alex_sim ★★★★
() автор топика
Ответ на: комментарий от Infra_HDC

либо указывать как обычно, но тогда нужно человеческий скрипт писать, с алгоритмом и циклами

Самое смешное что у меня и есть цикл, но с помошью grep я сразу дергаю всего одну строку из файла, если она есть, дополняю ее,если нету ничего не делаю. Попробую сделать по человече.

alex_sim ★★★★
() автор топика
Ответ на: комментарий от annulen

Потому, что это не валидный код на perl.

сделал так

open (InFile,"wg1.conf");
while ($str=<InFile>)
    {
    print "$str";

    s{10.8.100.5/32}{10.8.100.5/32, 192.168.0.0/24}g;

    } continue {
    print or die "-p destination: $!\n";
    }
close ( InFile );

Файл читается но земены нет, просветляемся дальше.

alex_sim ★★★★
() автор топика
Ответ на: комментарий от alex_sim

regexp

my $result = '';

my $file = $ARGV[0];
$file && -f $file or die $!;

open (my $input, '<', $file) or die $!;
while (<$input>) {
  s{(10.8.100.5/32)}{$1, 192.168.0.0/24}g;
  $result .= $_;
}
close ($input);

open (my $output, '>', $file) or die $!;
print $output $result;
close ($output);

animechaos ★★
()
Последнее исправление: animechaos (всего исправлений: 1)
Ответ на: комментарий от annulen

так работает, осталось рассосать как файл переписать этот же

#!/usr/bin/perl
open (InFile,"wg1.conf");
while (<InFile>)
        {
    (undef,undef,$p1)=split(' ');

    if( $p1 eq '10.8.100.5/32')
    {
        s{10.8.100.5/32}{10.8.100.5/32, 192.168.0.0/24}g;
    }
}
continue {
    print or die "-p destination: $!\n";
    }

close ( InFile );
alex_sim ★★★★
() автор топика
Ответ на: комментарий от animechaos

ну это прям готовый вариант, на блюдечке с голубой каемочкой :-) Но сработает только первый раз если по крону запускать, будет к строке дописывать и дописывать сетку 192.168.0.0/24 все равно нужно дорихтовывать, но спасибо за механизм переписывания файла, так с миру по нитке…. :-)

alex_sim ★★★★
() автор топика
Ответ на: комментарий от alex_sim

Сразу писать надо было в условие)

my $result = '';

my $file = $ARGV[0];
$file && -f $file or die $!;

open (my $input, '<', $file) or die $!;

my $net = '192.168.0.0/24';
while (<$input>) {
  ! m/$net/ && s{(10.8.100.5/32)}{$1, $net}g;
  $result .= $_;
}
close ($input);

open (my $output, '>', $file) or die $!;
print $output $result;
close ($output);
animechaos ★★
()
Ответ на: комментарий от animechaos

О вот так вроде то что надо

#!/usr/bin/perl
my $result = '';

my $file = $ARGV[0];
$file && -f $file or die $!;

open (my $input, '<', $file) or die $!;
while (<$input>) {
(undef,undef,$p1)=split(' ');
if( $p1 eq '10.8.100.5/32')
    {
  s{(10.8.100.5/32)}{$1, 192.168.0.0/24}g;
  }
  $result .= $_;
}
close ($input);

open (my $output, '>', $file) or die $!;
print $output $result;
close ($output);
alex_sim ★★★★
() автор топика
Ответ на: комментарий от animechaos

В этом коде есть одна операция с потенциально квадратичной сложностью, которую можно очень легко избежать

use strict;

my @result;

my $file = $ARGV[0];
$file && -f $file or die $!;

open (my $input, '<', $file) or die $!;

my $net = '192.168.0.0/24';
while (<$input>) {
  ! m/$net/ && s{(10.8.100.5/32)}{$1, $net}g;
  push @result, $_;
}
close ($input);

open (my $output, '>', $file) or die $!;
print $output @result;
close ($output);

Да, для маленьких файлов это мелочь, но мне, как плюсовику, режет глаз :)

Для реально больших файлов можно не складывать строки в массив, а записывать их в выходной файл сразу (файл должен быть с новым именем, а потом заметь старый через rename). Это сэкономит память, но может усложнить код, так что без надобности можно этого не делать (но однострочник внутри работает именно так).

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)
Ответ на: комментарий от alex_sim

Чтобы понять, как работает этот код, нужно знать об автоматической переменной $_. Этот код можно развернуть в

open (InFile,"wg1.conf");
while ($str=<InFile>)
{
    print "$str";
    $_ =~ s{10.8.100.5/32}{10.8.100.5/32, 192.168.0.0/24}g;
} continue {
    print $_ or die "-p destination: $!\n";
}
close (InFile);

Использование $str для чтения из файла приводит к тому, что автоматическая переменная в цикле больше не заполняется, и остальной код ничего не делает.

Еще здесь есть стилистические недочеты, по которым можно сразу заметить, что код писал новичок: 1) InFile - лучше не использовать bareword-хэндлы (за исключением встроенных - STDIN и т.д.), а если все-таки очень хочется, то называть их КАПСОМ; 2) вместо $str должно быть my $str - тут либо код без strict (что есть зло), либо переменная $str используется в большей области видимости (что тоже зло); 3) в open нужно всегда указывать режим (здесь ‘<’), как минимум для читаемости

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)
Ответ на: комментарий от annulen

Еще здесь есть стилистические недочеты, по которым можно сразу заметить, что код писал новичок.

Я не скрываю, что я новичек, так малчишка с грязным пузом и седой башкой. :-) есть какие то наработки под себя и я их рихтую, под возникающие задачи, но править конфиг приходится впервые, вам спасибо, что хоть что то на пальцах обьяснили, не любят у нас тут обычно, что то обьяснять, поковыряюсь еще, чтоб уложить в голове. Книга есть на 500 страниц но 2002 год и как то со скрипом заходит, мозги видимо уже не те.

С праздником!

alex_sim ★★★★
() автор топика
Ответ на: комментарий от solom

s{(10.8.100.5/32)}{$1, 192.168.0.0/24}g Ещё читабельнее

Ну это уже форс програмерский :-) сейчас мне понятно, что это и как, но изначально, врядли сообразил бы.

С праздником!

alex_sim ★★★★
() автор топика