Solved

PHP and shell_exec return value

Posted on 2007-12-06
14
2,075 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
  • 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
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
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 500 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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
IP 10.0.1.2 / 255.0.0.0 61 56
Extracting store locations from Google maps or site 2 23
Uploading a CSV Data Import via PHP & MySql 3 34
Link failure 16 35
Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
This article discusses four methods for overlaying images in a container on a web page
This video teaches viewers how to create their own website using cPanel and Wordpress. Tutorial walks users through how to set up their own domain name from tools like Domain Registrar, Hosting Account, and Wordpress. More specifically, the order in…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

830 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