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

Hello Monks Sorry for my babyperl , I had happy perl learning, but I find a little Wtf! issue. I try to get db2versions, db2instances and list of data bases without modules. I have The "root powEr!" but When I trying "su - $user -c 'command to get DB list' " I get some like this.

Product instance full path /opt/wheredb2/Version Current instance Userid
but the command doesn't execute

This is my code ...

use warnings; use diagnostics; use strict; use 5.010; use Cwd; use DB2::Admin::Constants; ############################## + + + + ###Get Version and instances## + + + + ############################## + + + + sub check_for_instance{ open(EXEC, '-|', 'db2ls | awk \'!/Install/ && !/----/ \'') +or die "Can't exec: $!\n"; # Now read the output just like a file + + + + while(my $line = <EXEC>) { chomp $line; if($line=~/(\/db2\/V\d.\d+)/){ print "Product instance full path\n $`"."$1\n"; foreach ($line) { my $Path="$`"."$1"."/instance/"; chdir($Path) or die "Cant chdir to $Path $!"; my $dir = getcwd; open my $cmd, '-|', './db2ilist'; while ($line = <$cmd>) { say "Current instance \n$line"; my $user="$line"; my $action="db2 list db directory"; ######################### ### This doesn't works # ######################### system ("su -l - $user -c \'$action > DBlist.txt && cat + DBlist.txt\'"); ########################### # # # this works ! XD # ########################### #system ("su -l - MyRealuser -c \'$action > DBlist.txt && cat DBlist. +txt\'"); ####### } close $cmd; } } } close(EXEC); } &check_for_instance;

btw ,I tried to use sudo - $user -c 'command', sudo su - $user "command", sudo - $user -c "command". but when i use directly the userid su - "Myrealuser" 'comman' works as i waiting.

I hope someone can give me some light

Replies are listed 'Best First'.
Re: run shell command as another user
by graff (Chancellor) on Apr 17, 2014 at 02:56 UTC
    Wouldn't it be a lot easier (and safer, and more reliable, and more flexible, and more maintainable, and…) to use DBI, and have your perl script connect directly to the database(s) you want to get information from?

    (There are database-driver modules on CPAN for connecting to DB2 databases, so it's just a question of making sure you have the modules you need, and then working out how to "list db directory" using DBI, rather than using shell commands that involve "su" privileges (*shudder*).

    (Update: I realize you did mention something about not using modules, but there would have to be some severely compelling reason for not using DBI, especially if the alternative is that you have to use root privileges just to get information from databases.)

      Hello graff thanks for the response,

      yes you are right! "Would it be a lot easier." I'm learning about DBI and DBD::DB2 modules. I'll use in some point. My problem now is that I have root access, but i don't have the password for each instance that is the reason because i can't use DBD::DB2 in this point.

      I need to use "su -" or "sudo su -" to get the instance environment and work with the data bases then maybe i can use DBD::DB2.

Re: run shell command as another user
by kcott (Archbishop) on Apr 17, 2014 at 05:15 UTC

    G'day ox1d0,

    Welcome to the monastery.

    You need some basic debugging here.

    If

    system ("su -l - $user -c \'$action > DBlist.txt && cat DBlist.txt\'") +;

    doesn't work, but

    system ("su -l - MyRealuser -c \'$action > DBlist.txt && cat DBlist.tx +t\'");

    does work, then the only difference between them is $user and MyRealuser.

    Use a print statement like this:

    print ">>>$user<<<\n";

    Do you get:

    >>>some_username<<<

    or:

    >>>some_username <<<

    If the former, replace MyRealuser with some_username (in the system() command that worked), and see if it still works. If not, see system to learn about checking for errors. Maybe there's a problem with some_username's account or privileges.

    If the latter, the newline after $user may be the culprit. You can fix that with:

    chomp(my $user = $line);

    I also note that you're using the same $line variable when reading from the EXEC and $cmd filehandles. Unless there's some specific reason for doing this, I'd use different variables, e.g.

    while(my $exec_line = <EXEC>) { ... while (my $cmd_line = <$cmd>) { ... } }

    Even if using the same variable isn't causing any problems now, it could well turn into a hard-to-track-down bug in the future following some (seemingly innocuous) modification.

    -- Ken

      Hello Ken, seems that the problem is in fact with system() I've tried with
      #my @command = ("su - $user -c id") #################################### #system ("su - $user"); #this Works# #################################### #system ("@command") == 0 or die "system @command failed: $?"; #exec ('su - $user -c $action') or print STDERR "couldn't exec foo: +$!"; #exec("/bin/su","-",$user,$action); #system ("su", "-", $user, "-c", "/bin/bash -c $action"); #system ("su - $user -c /bin/bash -c $action"); #system "sudo","su","-" => $user, -c => $action;

      but each one fails!!

      also i tried these modules, same result ..

      use warnings; use diagnostics; use strict; use Shell::Source; use Shell; my $action="\'Anything\'"; my $user="RealUser"; my $sh = Shell->new; say "$user"; say "$action "; print $sh->sudo("su -l - $user --command $action");

      I start to thinking if my Gentoo has problems , I'll try in another system...

      btw I've checked for $user seems that is good, just before function.

      thanks..