[gelöst] Perl: Maskierung beim Aufruf von system()

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
zongo
Beiträge: 117
Registriert: 09.04.2007 23:53:46

[gelöst] Perl: Maskierung beim Aufruf von system()

Beitrag von zongo » 16.03.2010 15:37:07

Hallo zusammen!

Ich habe ein Maskierungsproblem bei der Funktion system() in Perl:

Ein einfaches Shell-Kommando zu übergeben wie zb. system("cat xxx | grep yyy") ist ja trivial,
aber wie gehe ich damit um, wenn ich zum Beispiel:

system("ps -ef | awk '$1=="user" && $3==1'")

aufrufen will? Das klappt wegen des awk-Konstrukts nicht.

(Das es ein Anachronismus ist awk aus Perl heraus aufzurufen, weiß ich selber ;-) Es geht um eine Quick´n´Dirty-Lösung)

Wie muss ich generell beim Aufruf von system() maskieren um ein beliebiges Shell-Kommando vollständig zu "schützen"?


Vielen Dank im voraus & Gruß aus Braunschweig
Zuletzt geändert von zongo am 17.03.2010 11:17:04, insgesamt 1-mal geändert.

Benutzeravatar
hikaru
Moderator
Beiträge: 13931
Registriert: 09.04.2008 12:48:59

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von hikaru » 16.03.2010 15:50:47

Probier mal das:

Code: Alles auswählen

system("ps -ef | awk '\$1==\"user\" && \$3==1'")

123456
Beiträge: 6126
Registriert: 08.03.2003 14:07:24

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von 123456 » 16.03.2010 16:03:09

der ps Aufruf produziert ne hübsche Fehlermeldung beim Escapen.
system() wird mit "" aufgerufen und der ps/awk Aufruf ist auch ok.
Weil aber mehrfach doppelte "" drin sind funktioniert das nicht. Eine Idee hab ich aber im Moment auch nicht.

Benutzeravatar
hikaru
Moderator
Beiträge: 13931
Registriert: 09.04.2008 12:48:59

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von hikaru » 16.03.2010 16:53:19

Ach ja, die gute Allgemeingültigkeit. Das Problem fängt schon bei den $-Zeichen an, denn so ohne Weiteres ist nicht klar ob die im Perl- oder im awk-Kontext stehen.
Wie kommen denn die Shell-Kommandos in den Perl-Kontext? Solche Spezialfälle wie Anführungs- und Dollarzeichen musst du schon vorher abfangen und dann ggf. über Pattern-Matching ersetzen.

Zum Beispiel ginge das:

Code: Alles auswählen

$_ = "ps -ef | awk '#DL#1==#QT#user#QT# && #DL#3==1'";

s/#DL#/\$/g;
s/#QT#/"/g;

system($_);
Die Frage wäre jetzt, ob es praktikabel ist problematische Zeichen durch entsprechende Sequenzen zu ersetzen bevor sie in den Perl-Kontext kommen. Womit wir wieder beim beliebten Thema "Parser" wären.

123456
Beiträge: 6126
Registriert: 08.03.2003 14:07:24

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von 123456 » 16.03.2010 17:57:12

folgender Workaround sollte auch funktionieren. Der behebt die Probleme mit den doppelten Quotes...

Code: Alles auswählen

system("ps -ef |grep ^USER |awk '\$3==1'");

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von gms » 16.03.2010 18:05:19

zongo hat geschrieben: Wie muss ich generell beim Aufruf von system() maskieren um ein beliebiges Shell-Kommando vollständig zu "schützen"?
wenn du an "system" eine Zeichenkette mit "..." übergibst, müssen die " und $-Zeichen maskiert werden ( außer $ steht für eine Perl-Variable):

Code: Alles auswählen

gms1 ~ # cat x.pl
#!/usr/bin/perl

system("ps -ef | awk '\$1==\"gms\" && \$3==1'");
gms1 ~ # ./x.pl
gms       7927     1  0 Mar07 ?        00:00:01 ssh-agent -s
...
gms1 ~ #
wenn du an "system" eine Zeichenkette mit '...' übergibst, muß nur das '-Zeichen maskiert werden

Code: Alles auswählen

gms1 ~ # cat x.pl
#!/usr/bin/perl

system('ps -ef | awk \'$1=="gms" && $3==1\'');
gms1 ~ #
gms1 ~ # ./x.pl
gms       7927     1  0 Mar07 ?        00:00:01 ssh-agent -s
...
gms1 ~ #
letzteres wäre also der einfachere Fall, dafür mußt du hier bei Verwendung von Perl-Variablen gesondert vorgehen.

z.B system('ps -ef | awk \'$1=="'.$user.'" && $3==1\'');

Gruß
gms

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von gms » 16.03.2010 18:14:06

jetzt ist mir noch eine ( einfachere ) Variante eingefallen ( hier müssen nur die $ von Nicht-Perl-Variablen maskiert werden):

Code: Alles auswählen

gms1 ~ # cat x.pl
#!/usr/bin/perl

system <<EOF;
ps -ef | awk '\$1=="gms" && \$3==1'
EOF
gms1 ~ # ./x.pl
gms       7927     1  0 Mar07 ?        00:00:01 ssh-agent -s
...
zur Sicherheit noch erwähnt: die Zeichen @ und % sind natürlich unter Perl gleich zu behandeln, wie das $-Zeichen

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von Meillo » 16.03.2010 18:17:30

Man könnte bei ps noch -u verwenden um sich das grep bzw. den zweiten Vergleich in awk zu sparen:

Code: Alles auswählen

system("ps -fu USER | awk '\$3==1'");
Zudem hat man in Perl doch alternative Arten zu quoten, was hier sehr praktisch ist:

Code: Alles auswählen

system(q/ps -fu USER | awk '$3==1'/);
Use ed once in a while!

123456
Beiträge: 6126
Registriert: 08.03.2003 14:07:24

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von 123456 » 16.03.2010 18:31:56

Meillo hat geschrieben:Zudem hat man in Perl doch alternative Arten zu quoten, was hier sehr praktisch ist:

Code: Alles auswählen

system(q/ps -fu USER | awk '$3==1'/);
in Zeile wieviel welcher Doku stand das denn? Genau das wollte er wohl ursprünglich wissen.
Dann funktioniert auch sein original mit den neuen "Quotes":

Code: Alles auswählen

system(q/ps -ef | awk '$1=="user" && $3==1'/) 

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von gms » 16.03.2010 18:35:44

ub13 hat geschrieben:[
in Zeile wieviel welcher Doku stand das denn? Genau das wollte er wohl ursprünglich wissen.
in perlop http://perldoc.perl.org/perlop.html#Quo ... -Operators
ub13 hat geschrieben:[

Code: Alles auswählen

system(q/ps -ef | awk '$1=="user" && $3==1'/) 
das soll jetzt natürlich keine Kritik an dieser Lösung sein, aber meistens hat man dann doch auch Perl-Variablen in dem String ( z.B für 'user' ) und dann wird diese Methode am unübersichtlichsten ( finde ich zumindest )


Gruß
gms

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von Meillo » 16.03.2010 18:56:30

ub13 hat geschrieben: in Zeile wieviel welcher Doku stand das denn? Genau das wollte er wohl ursprünglich wissen.
Im Camel-Book natürlich.
gms hat geschrieben:
ub13 hat geschrieben:

Code: Alles auswählen

system(q/ps -ef | awk '$1=="user" && $3==1'/) 
das soll jetzt natürlich keine Kritik an dieser Lösung sein, aber meistens hat man dann doch auch Perl-Variablen in dem String ( z.B für 'user' ) und dann wird diese Methode am unübersichtlichsten ( finde ich zumindest )
Das stimmt.

Wenn Variablen enthalten sind, müssen die Dollarzeichen zwangsläufig escaped werden. Wenn man aber qq// (entspricht Double-Quotes) verwendet, dann muss man die Double-Quotes im Text nicht auch noch escapen.
Use ed once in a while!

123456
Beiträge: 6126
Registriert: 08.03.2003 14:07:24

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von 123456 » 16.03.2010 20:15:51

Meillo hat geschrieben:Im Camel-Book natürlich.
Daran lags also - ich habe gar kein Camel-Book. ;)
gms hat ja eine Quelle genannt. Google hätte mich (wenn ich dann nachgedacht hätte) auch schnell hingeführt.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: Perl: Maskierung beim Aufruf von system()

Beitrag von gms » 16.03.2010 23:06:06

ub13 hat geschrieben: Daran lags also - ich habe gar kein Camel-Book. ;)
gms hat ja eine Quelle genannt.
:oops: das Camel-Book wärs gewesen, ich habe aber auch kein Camel-Book :(, blöd , so konnte ich nur mit diesem schnöden Link zu "perlop" dienen ... :)

Gruß
gms

Benutzeravatar
zongo
Beiträge: 117
Registriert: 09.04.2007 23:53:46

Re: [gelöst] Perl: Maskierung beim Aufruf von system()

Beitrag von zongo » 17.03.2010 11:18:01

Und wieder etwas dazu gelernt ...

Muchas gracias muchachos!

Antworten