Search code examples
phpapacheexecution

PHP how to execute a command


I'm trying to use LibreOffice for converting a spreadsheet to another format, when I execute the command from the console it works fine but when I do it from PHP using exec() or system() it doesn't work. It doesn't show any error or anything, it simply silently fails, if I try executing some simple command like "ls" it works just fine.

This is the command I'm using:

<?php
system("libreoffice --headless -convert-to ooxml '/home/www/path_to_app/file.xlsx' -outdir /home/www/path_to_app/");

I already tried changing the apache User and Group on /opt/lampp/etc/httpd.conf to the same logged in user I am.

I'm wondering if the problem is that the www folder is /home instead of inside my user and that causes permissions problems, but so far couldn't make it work.

Any help will be appreciated.


Solution

  • Notwithstanding your $PATH, which drew010 alluded to, I wouldn't do it this way.

    LibreOffice is a pretty big program, has lots of code you don't know about, it generates and updates files in a directory in your $HOME, and is certainly not something you're going to be able to run more than one copy of at a time.

    So instead of having LibreOffice launched by your web server, and subverting Apache's security by running it as a more privileged user than "www-data" or "nobody", you should make a handler.

    First off, verify that you can run your libreoffice ... command line from a terminal. To be extra sure that you don't have any X11 dependencies, run unset DISPLAY (for bash) or unsetenv DISPLAY (for tcsh) in your xterm before you test your command line. Does it break? Fix that problem first. Does it work? Great, then proceed with a handler.

    Your handler, in its simplest form, can be a script that loops forever, checking for "files to handle" in a spool directory, and if it finds them, converts them using libreoffice and puts the resultant file where it can be found by your web app.

    #!/bin/sh
    
    while sleep 10; do
      if [ `ls /var/tmp/myspool/ | grep -c '\.xlsx$'` -gt 0 ]; then
        ls /var/tmp/myspool/*.xlsx | while read file; do
          /usr/local/bin/libreoffice --headless -convert-to ooxml "$file" yadda yadda
          if [ $? = 0 ]; then
            mv "$file" "/var/tmp/myspool/done/
          fi
        done
      fi
    done
    

    If you don't want the overhead of something "polling" (checking the spool directory every 10 seconds), then you could have your PHP script add a line to a log that gets watched by your handler. For example:

    <?php
    
    // process form, save file to spool dir
    syslog(LOG_NOTICE, "Saved: " . $filename);
    
    ?>
    

    Make sure you've configured syslog to store these messages in, say, /var/log/filelog, then your handler can just tail the log.

    #!/bin/sh
    
    tail -F /var/log/filelog | while read line; do
      filename="`echo \"$line\" | sed 's/.*Saved: //'`"
      /usr/local/bin/libreoffice --headless -convert-to ooxml "$file" yadda yadda
      # etc ... error handling and mv as in the other script
    done
    

    Get the idea?