Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

PHP and shell_exec return value

Posted on 2007-12-06
14
Medium Priority
?
2,164 Views
Last Modified: 2013-12-12
All,

I'm 100% certain that the following code should return an error, however $res appears to be null.

$res = shell_exec($this->cmd);

According to php.net documentation, the return value is the result of the command and should appear in $res.  $this->cmd looks like the following:

          $this->cmd = "mysqldump -Q -u $this->dbUser -p$this->dbPass $this->dbName";
            
          $this->cmd .= ($this->zip==="bz2") ?
                  " | bzip2 > $this->dest". '/' ."$fname"  :
                  " | gzip > $this->dest".'/'."$fname";

Thanks for any ideas... this should only not come back with any results for a successful dump.
0
Comment
Question by:stevefNYC
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +1
14 Comments
 
LVL 21

Expert Comment

by:nizsmo
ID: 20422966
hi steve,

try and print out $this->cmd and is it the command you are expecting? when you actually use shell to execute the command does it return anything?
0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 20422996
Don't you just want two equal signs for this command, rather than 3?:
($this->zip==="bz2")
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423007
Hey nizsmo,

Yes I've tried that.  I copy/pasted the command from my debug console where I spit it out to make sure the syntax is right... I should be getting an error back:

sf:tmp sf$ mysqldump -Q -u root -pthisisnotmypass foobar | bzip2 > /tmp/builder/foobar.sql.bz2
-bash: /tmp/builder/foobar sql.bz2: No such file or directory
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) when trying to connect

I'm intentionally creating that error on the server-side... I just want the return value to pick it up... (just giving a heads up for those who come into this thread and try to start fixing my mysqldump error... it's intentional.)
0
Simplify Your Workload with One Tool

How do you combat today’s intelligent hacker while managing multiple domains and platforms? By simplifying your workload with one tool. With Lunarpages hosting through Plesk Onyx, you can:

Automate SSL generation and installation with two clicks
Experience total server control

 
LVL 35

Expert Comment

by:Terry Woods
ID: 20423012
I suspect also that:
                  " | bzip2 > $this->dest". '/' ."$fname"  :
                  " | gzip > $this->dest".'/'."$fname";

may need curly brackets added, like this:
                  " | bzip2 > {$this->dest}". '/' ."$fname"  :
                  " | gzip > {$this->dest}".'/'."$fname";

though I'm not 100% sure
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423018
TerryAtOpus,

The identity operator works fine in this scenario. I'm making sure that the type in this case matches as well.
0
 
LVL 21

Expert Comment

by:nizsmo
ID: 20423037
how about simplifying the command and trying it? its not hard to produce an error :)
as you can see here:
http://www.php.net/shell_exec

the return value is indeed the return message, maybe give the example on that webpage a try?
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423107
Works fine when I try the 'ls -ltr' example. Still not returning anything for my mysqldump invocation though
0
 
LVL 21

Expert Comment

by:nizsmo
ID: 20423154
oh? maybe then it will only capture successful command outputs and not error outputs? just a thought.
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423186
Well, according to php.net the following reads in a user comment:

``ALSO, note that shell_exec() does not grab STDERR, so use "2>&1" to redirect it to STDOUT and catch it.''

I've modified my code to read           

$this->cmd .= ($this->zip==="bz2") ?
                  " | bzip2 > $this->dest". '/' ."$fname 2>&1"  :
                  " | gzip > $this->dest".'/'."$fname 2>&1";

Still no go though.

0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 20423455
The following worked for me:
  $cmd = "mjysqldump -Q -u 2>&1";
  $result = shell_exec($cmd);
  echo "Result: '$result'";

Outputs:
Result: 'sh: line 1: mjysqldump: command not found '
0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 20423491
Not sure how likely it is that you're running a different shell from what's normal, but different shells use different syntax to redirect the STDERR. How about trying copying and pasting my example, and see what you get?
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20424992
I'm just using good ol' bash, Terry.

foo:~ sf$ echo $SHELL
/bin/bash
foo:~ sf$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
0
 
LVL 9

Accepted Solution

by:
tkalchev earned 2000 total points
ID: 20448522
Adding  "2>&1" at the end of the command should show you the actual error.  Your problem here is that you are using a complex command, which uses pipes and redirects the output to a file. Actually you are executing 2 commands, first is

mysqldump -Q -uUSERNAME -pPASSWORD DATABASENAME

second is

gzip > FILENAME  (I will assume that you use GZIP to simplify the explanation )


When you pipe the commands as you did the complete output from the first command is sent to the STDIN of the second one.
When you add 2>&1 at the end of the command line you get the following :

mysqldump -Q -uUSERNAME -pPASSWORD DATABASENAME | gzip > FILENAME 2>&1

the following is happened :
1. The first command is executed
2. The contents of everything printed on the 1st's command STDOUT is send to the STDIN of the second command
3. If something (the error message in your case) is sent to the STDERR, it is displayed on the system's STDERR and won't be catched by your shell_exec, as it catches only STDOUT
4. The STDOUT of the second command is redirected to FILENAME
5. The STDERR of the second command is redirected to its STDOUT

This situation won't help you, because you need the STDERR of the first command, not the senond's
So, let's modify it a little bit :

mysqldump -Q -uUSERNAME -pPASSWORD DATABASENAME 2>&1 | gzip > FILENAME

what is changed here :

1. The first command is executed
2. The contents of everything printed on the 1st's command STDOUT is send to the STDIN of the second command
3. If something (the error message in your case) is sent to the STDERR, it is also redirected to the STDOUT, actually to the second command's STDIN
4. The STDOUT of the second command is redirected to FILENAME

Now you have the error message gzipped in the FILENAME, you can check it if you run  zcat FILENAME ... Also not exactly what you have expected.

One possible solution for your case is to play a little bit with the I/O redirection, you can for example issue a command line like this :

exec 6>&1 2>&1 1>/tmp/output; mysqldump  -uUSER -pPASSWORD DATABASENAME ; exec 1>&6 6>&-; if [ -s /tmp/output ]; then cat /tmp/output | gzip > FILENAME; rm -f /tmp/output; fi

What it does :

1. exec 6>&1 2>&1 1>/tmp/output : redirects the STDERR to STDOUT and then STDOUT to a file /tmp/output
2. mysqldump  -uUSER -pPASSWORD DATABASENAME  : it just runs your 1st command
3. exec 1>&6 6>&-   : restores the STDOUT and closes descriptor 6
4. if [ -s /tmp/output ]; then cat /tmp/output | gzip > FILENAME; rm -f /tmp/output; fi   : if the file /tmp/output exists and is not empty it is being gzipped to a file FILENAME and then deleted


Hope it will help you
0
 
LVL 3

Author Closing Comment

by:stevefNYC
ID: 31413250
Beautiful and concise answer. Thank you kindly.  

Until you responded, I just ended up splitting the commands into two, avoiding any file redirection...
0

Featured Post

Plesk WordPress Toolkit

Plesk's WordPress Toolkit allows server administrators, resellers and customers to manage their WordPress instances, enabling a variety of development workflows for WordPress admins of all skill levels, from beginners to pros.

See why 2/3 of Plesk servers use it.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
This article discusses how to implement server side field validation and display customized error messages to the client.
The viewer will learn how to count occurrences of each item in an array.
Learn how to set-up PayPal payment integration in your Wufoo form. Allow your users to remit payment through PayPal upon completion of your online form. This is helpful for collecting membership payments, customer payments, donations, and more.

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question