http://qs1969.pair.com?node_id=1228783

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello there, how you guys doing? Hope well. I'm trying to write a perl script which will receive command line arguments and pass it to system.

#!/usr/local/bin/perl use strict; use warnings; # Check if program is being executead as root if ("$>" ne "0") { print "This program can't be executed as root\n"; exit 2 } # Get running vm's my @get_vm_list = (`xl list`); sub show_vm_list { print @get_vm_list; } my $vm_run = pop @ARGV ; my %rec_args = ( vmlist => \&show_vm_list, getdomid => \&get_dom_id, ); my $arg = shift @ARGV; if (defined $arg && exists $rec_args{$arg}) { $rec_args{$arg}->(); }

OK here is my function which I'm trying to get working

sub get_dom_id { my $XENDOMID = "xl list| DOM_ID=`fgrep $vm_run` | awk '{print $ +2}'` && VNCPORT=`ps x \ | fgrep -m 1 "domid $DOM_ID" | awk '{print $1}'` && sockstat -4l | fgr +ep $VNCPORT | awk '{print $6}'"; print `$DOMID`; }

I have already tried set system environment using $ENV{'MYVAR'} without success

Any Directions will be appreciated, thanks in advance

Replies are listed 'Best First'.
Re: system commands/shell and perl variables.
by choroba (Cardinal) on Jan 21, 2019 at 21:42 UTC
    Does your editor support syntax highlighting? Double quotes can't be nested in Perl, and backticks aren't paired inside double quotes as in the shell. Fortunately, Perl has the qq operator:
    my $XENDOMID = qq(xl list| DOM_ID=`fgrep $vm_run` | awk '{print $2}'` +&& VNCPORT=`ps x \ | fgrep -m 1 "domid $DOM_ID" | awk '{print $1}'` && sockstat -4l | fgr +ep $VNCPORT | awk '{print $6}');
    But I'm not sure it works, xl isn't a recognised command on my system.

    Calling grep and awk from perl seems suspicious. Perl can do most of the operations these commands do, and without shelling out to run them, it's usually faster. Please provide a SSCCE so we can help you more.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      In addition to what choroba pointed out,

      the $ (Dollar sigil) in the shell code need to be escaped .. otherwise they will be interpreted by perl.

      So - in this case - your passing of the value of $vm_run and $VNCPORT should work OK, but $DOM_ID, $2, $1, and $6 SHELL variables all need to have their $ escaped (pre-pending a "\").

                      As a computer, I find your faith in technology amusing.

Re: system commands/shell and perl variables.
by haukex (Archbishop) on Jan 22, 2019 at 15:02 UTC

    With a command as complex as you showed, I would very much recommend doing as much of it in Perl as possible instead of shelling out - there are potential security issues, quoting challenges, etc. with shelling out. I wrote about that at length here (with code examples). In particular, both fgrep and awk can be replaced by pure Perl. Instead of ps, you might try Proc::ProcessTable. That leaves only xl and sockstat. If you want to run those external processes and need to feed something to their STDIN, I'd recommend IPC::Run3. Otherwise, if you just want a simple replacement for backticks, there's capturex from IPC::System::Simple.

      Hi there, First of all thank you very much. I am starting with perl and I trying to automate my shell scripts by perl scripts. Here my final script ( of course I will follow HAUKEX advice which is what I want.
      #!/usr/local/bin/perl use strict; use warnings; my @get_vmlist = ( `xl list` ); sub show_vmlist { print @get_vmlist; } my $arg = shift @ARGV; my $vm_run = pop @ARGV; sub get_vncport { my $DOMID = qq(DOM_ID="`xl list | fgrep $vm_run | awk '{print +\$2}'`" && VNCPORT="`ps x | fgrep -m 1 "domid \$DOM_ID" | awk '{print + \$1}'`" && sockstat -4l | fgrep \$VNCPORT | awk '{print \$6}'); print `$DOMID`; } my %rec_args = ( vmlist => \&show_vmlist, getvnc => \&get_vncport, ); if (defined $arg && exists $rec_args{$arg}) { $rec_args{$arg}->(); }
Re: system commands/shell and perl variables.
by NetWallah (Canon) on Jan 22, 2019 at 22:11 UTC
    You may be interested in Xen::API. (I have no experience with this - just found it on CPAN.)
    use Xen::API; my $x = Xen::API->new; my %vms = $x->list_vms

                    As a computer, I find your faith in technology amusing.

Re: system commands/shell and perl variables.
by karlgoethebier (Abbot) on Jan 22, 2019 at 09:59 UTC

    See also

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help