perl bzw. sh Problem

mogbo

Banned
Hallo,
hab mir ein recht simples Script für das Starten und Beenden von VPNs gemacht.
Sämtliche *.ovpn Dateien liegen in /etc/openvpn

Mein Problem ist jetzt bei der Ausführung, dass wenn ich den if ($input > 0) Teil ausführe, bekomm ich die Fehlermeldung: sh syntax error `;' unexpected . Ich kann jedoch den Fehler nicht finden. Könnte vlt mal ein zweites Auge drüber schauen, bin am Verzweifeln :)
Code:
#!/usr/bin/env perl

use strict;
use warnings;
use utf8;

my @ls_out;
my $count = 0;
my $zaehler;
my $anzahl;
my $input;

my $path = "/etc/openvpn";

@ls_out = `ls $path | perl -lane 'print if /.ovpn/'`;
$anzahl = @ls_out;

print "0.) Kill openvpn and change /etc/resolv.conf\n";

while ( $anzahl > $count )
{
        $zaehler = $count + 1;
        print "$zaehler.) $ls_out[$count]";
        $count += 1;
}

print "Choose: \n";
chomp( $input = <STDIN> );

if ( $input > 0 )
{
        $input -= 1;
        system("doas sh -c 'openvpn --config $path/$ls_out[$input]; echo $ls_out[$input] > /tmp/vpn_connection; chown root:wheel /tmp/vpn_connection; chmod 440 /tmp/vpn_connection'");
}
else
{
        system("doas sh -c 'pkill openvpn; echo \"nameserver 127.0.0.1\" > /etc/resolv.conf'");
}

Schönheitsfehler und Sonstiges können auch gerne bemängelt werden, hab leider niemanden der mich kritisieren könnte
 
Füge doch einfach ein wenig Debugging hinzu und lass dir das Kommando vorher ausgeben:
Code:
...
if ( $input > 0 )
{
        $input -= 1;
        my $cmd="doas sh -c 'openvpn --config $path/$ls_out[$input]; echo $ls_out[$input] > /tmp/vpn_connection; chown root:wheel /tmp/vpn_connection; chmod 440 /tmp/vpn_connection'";
        warn "calling $cmd\n";
        system($cmd);
}
...
 
Danke für den Tipp, leider kommt dabei auch nicht mehr raus. Die Ausgabe von warn sieht für mich richtig aus, jedoch am Ende mit der gleichen Fehlermeldung: sh syntax error `;' unexpected
 
Ich tippe auf die single quotas innerhalb von double quotas
To summarize the main difference between single and double quotation marks: Single quotation marks do not interpret, and double quotation marks do. That is, if you put something in single quotation marks, Perl assumes that you want the exact characters you place between the marks — except for the slash-single quote (‘) combination and double-slash (\) combination. If you place text inside double quotation marks, however, Perl interprets variable names. Perl also interprets special characters inside double-quoted literal strings.
 
Mit dem Unterschied, dass in dieser Zeile keine Variablen verwendet werden
system("doas sh -c 'openvpn --config $path/$ls_out[$input]; echo $ls_out[$input] > /tmp/vpn_connection; chown root:wheel /tmp/vpn_connection; chmod 440 /tmp/vpn_connection'");
Hier jedoch schon, und dank single quotas können die Variablen nicht übersetzt werden.
Kann mich aber auch täuschen, lese es grad auf einem 4,3Zoll Display :-)
 
Code:
#!/usr/bin/env perl
#===============================================================================
#
#         FILE: ovpn.pl
#
#        USAGE: ./ovpn.pl  
#
#  DESCRIPTION: 
#
#      OPTIONS: ---
# REQUIREMENTS: ---
#         BUGS: ---
#        NOTES: ---
#       AUTHOR: xxxx (), 
# ORGANIZATION: 
#      VERSION: 1.0
#      CREATED: 05/15/17 15:09:33
#     REVISION: ---
#===============================================================================

use strict;
use warnings;
use utf8;

my @ls_out;
my $count = 0;
my $zaehler;
my $anzahl;
my $input;
my $random;

my $path = "/etc/openvpn";

@ls_out = `ls $path | perl -lane 'print if /.ovpn/'`;
$anzahl = @ls_out;

print "0.) Kill openvpn and change /etc/resolv.conf\n";

while ( $anzahl > $count )
{
    $zaehler = $count + 1;
    print "$zaehler.) $ls_out[$count]";
    $count += 1;
}

print "99.) Random connection\n";

print "Choose: \n";
chomp( $input = <STDIN> );

if ( $input > 0 )
{
    if ( $input == 99 )
    {
        $random = $ls_out[rand($anzahl)];
        system("echo \"$random\" > /tmp/vpn_connection");
        system("chmod 660 /tmp/vpn_connection");
        system("doas sh -c 'openvpn --config $path/$random'");
    }
    else
    {
        $input -= 1;
        system("echo \"$ls_out[$input]\" > /tmp/vpn_connection");
        system("chmod 660 /tmp/vpn_connection");
        system("doas sh -c 'openvpn --config $path/$ls_out[$input]'");
    }
}
else
{
    system("doas sh -c 'pkill openvpn;echo \"nameserver 127.0.0.1\" > /etc/resolv.conf'");
}
Hm, habs jetzt so gelöst, auch wenn ich das chown root:wheel /tmp/vpn_connection schon gerne ausführen würde, auch wenns im Endeffekt vermutlich völlig unnötig ist.

Code:
system("doas sh -c 'openvpn --config $path/$ls_out[$input]'");
So lässt es sich komischerweise auch ohne Probleme ausführen, scheint wohl ein Problem mit dem Semicolon zu sein (was für mich völlig sinnfrei ist), oder ich verstehe deine Erklärung nicht richtig.

Nach deiner Erklärung dürfte die Zeile oben auch nicht gehen oder?
 
Nimm die Variablen mal testweise aus dem String raus und setz ihn lieber per concatenation zusammen. Auch gibt es einen Unterschied zwischen system($foo) und system ($foo, $bar, $baz), den du evtl. nutzen kannst.
 
Habs ohne Variablen getestet, läuft, sobald ich eine Variable verwende spuckt er mir sobald ein Semicolon auftaucht eine Fehlermeldung aus, oder führt den Teil nach dem Semicolon nicht aus.
 
Wie sieht der Test jetzt aus? Ich dachte an sowas wie
Code:
system('doas', 'sh', '-c', 'blablabla ' . $foo[$bar] . '; blablabla');
 
Code:
...
if ( $input == 99 )
{
  $random = $ls_out[rand($anzahl)];
  system("echo \"$random\" > /tmp/vpn_connection");
  system("chmod 660 /tmp/vpn_connection");
  my $cmd_1 = "chown root:wheel /tmp/vpn_connection";
  my $cmd_2 = "openvpn --config $path/$random";
  system("'doas', 'sh', '-c', '$cmd_1;$cmd_2ƒ'");
}
...
Meintest du so @TCM ? Kanns leider nicht testen, bin nicht zu Hause
 
Code:
Hm, habs jetzt so gelöst, auch wenn ich das chown root:wheel /tmp/vpn_connection schon gerne ausführen würde, auch wenns im Endeffekt vermutlich völlig unnötig ist.

[code]
system("doas sh -c 'openvpn --config $path/$ls_out[$input]'");
So lässt es sich komischerweise auch ohne Probleme ausführen, scheint wohl ein Problem mit dem Semicolon zu sein (was für mich völlig sinnfrei ist), oder ich verstehe deine Erklärung nicht richtig.

Nach deiner Erklärung dürfte die Zeile oben auch nicht gehen oder?

Versuch es mal so (habs nicht getestet, müsste aber mMn funktionieren):
#!/usr/bin/env perl

use strict;
use warnings;
use utf8;

my @ls_out;
my $count = 0;
my $zaehler;
my $anzahl;
my $input;

my $path = "/etc/openvpn";

@ls_out = `ls $path | perl -lane 'print if /.ovpn/'`;
$anzahl = @ls_out;

print "0.) Kill openvpn and change /etc/resolv.conf\n";

while ( $anzahl > $count )
{
$zaehler = $count + 1;
print "$zaehler.) $ls_out[$count]";
$count += 1;
}

print "Choose: \n";
chomp( $input = <STDIN> );

if ( $input > 0 )
{
$input -= 1;
system("doas sh -c \"openvpn --config $path/$ls_out[$input]; echo $ls_out[$input] > /tmp/vpn_connection; chown root:wheel /tmp/vpn_connection; chmod 440 /tmp/vpn_connection\"");
}
else
{
system("doas sh -c 'pkill openvpn; echo \"nameserver 127.0.0.1\" > /etc/resolv.conf'");
}
 
Quasi Singelquotes durch \" ersetzen, glaub das hab ich wirklich noch nicht probiert, werd ich zu Hause gleich mal testen.

Schon komisch, ganzes Script in 10 mins geschrieben und dann schluckt ein kleiner Schönheitsaspekt soviel Zeit...
 
Bevor du nicht die komplette Kommandozeile postest, die fehlschlägt (das war der Hinweis auf die Debug-Ausgabe), kann dir hier niemand helfen. Glaskugeln sind nunmal Mangelware.

Rob
 
Hier jedoch schon, und dank single quotas können die Variablen nicht übersetzt werden.
Das ist falsch. Da das gesamte Kommando in doppelten Anführungszeichen steht, werden die Variablen auf jeden Fall interpoliert. Die einfachen Anführungszeichen innerhalb der Zeichenkette haben darauf keinen Einfluss mehr.

Rob
 
Bevor du nicht die komplette Kommandozeile postest, die fehlschlägt (das war der Hinweis auf die Debug-Ausgabe), kann dir hier niemand helfen. Glaskugeln sind nunmal Mangelware.

Danke für den Tipp, leider kommt dabei auch nicht mehr raus. Die Ausgabe von warn sieht für mich richtig aus, jedoch am Ende mit der gleichen Fehlermeldung: sh syntax error `;' unexpected

doas sh -c 'openvpn --config /etc/openvpn/xy.ovpn; echo xy.ovpn > /tmp/vpn_connection; chown root:wheel /tmp/vpn_connection; chmod 440 /tmp/vpn_connection'
sh syntax error `;' unexpected

Mehr als diese zwei Zeilen kommt bei warn nicht raus, ich kanns später nochmals testen und posten (bin gerade nicht an meinem PC).

Wozu soll diese Datei überhaupt sein? In deinem Programm wird sie nirgends ein zweites Mal genutzt.
In meinen *.ovpn ist immer ein Script verbaut:

/etc/openvpn/*.ovpn
Code:
...
up "/etc/openvpn/up.sh"
...

Ich brauch die Ausgabe welcher VPN verwendet wird um die Namensauflösung anzupassen, nachdem die Verbindung zum VPN steht, da ich sonst einen DNSleak habe.
Da ich nicht jede *.ovpn als Schneeflocke konfigurieren will, hab ichs lieber so gelöst.

{ system("doas sh -c 'pkill openvpn; echo \"nameserver 127.0.0.1\" > /etc/resolv.conf'"); }

Darum hab ich im Script auch eine extra Funktion zum abschalten des VPNs, da die Namensauflösung nur mit Verbundenem VPN klappt.
 
Das ist falsch. Da das gesamte Kommando in doppelten Anführungszeichen steht, werden die Variablen auf jeden Fall interpoliert. Die einfachen Anführungszeichen innerhalb der Zeichenkette haben darauf keinen Einfluss mehr.

Rob
Das mag bei Perl noch funktionieren, in dem Beispiel wird aber noch die sh augerufen und die kann das dann nicht mehr sauber interpretieiren.

2017-05-16 12_31_57-FreeBSD [wird ausgeführt] - Oracle VM VirtualBox.png

2017-05-16 12_32_27-FreeBSD [wird ausgeführt] - Oracle VM VirtualBox.png


Edit: habe einen Fehler im letzten Beispiel gehabt, daher dieser Update.
 
Zuletzt bearbeitet:
Muss das als Screenshot sein? Man könnte auch code-Tags nutzen...
 
Zurück
Oben