Search code examples
phpapacheubuntupermissionsopenai-whisper

Can't run script using PHP's exec(), possible permissions problems


I'm having trouble executing a command using PHP's exec function. I think there are two different permissions (or maybe environment?) problems.

In this case, the script I'm having trouble with is whisper (OpenAI's Whisper). The setup is Ubuntu 22.04.2 LTS, Apache 2.4.52, PHP 8.1.5.

PHP runs the exec function as the web server user www-data. (I have confirmed this with an exec('whoami').)

Whisper was installed using pip under my regular username, which I'll call myrealusername.

In my command prompt under my regular username, if I type whereis whisper, I get the answer whisper: /home/myrealusername/.local/bin/whisper. If, however, I try sudo -u www-data whereis whisper, I get the answer whisper:, which indicates to me that the web server user www-data just can't find Whisper.

The content of whisper is as follows:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from whisper.transcribe import cli
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(cli())

The command I'm trying to run using exec is whisper 'mediafilename.mp3' --model tiny --language English > 'outputfilename.txt'. (This is a bit simplified; actually, mediafilename.mp3 and outputfilename.txt are specified with respective paths which I won't repeat here; I have ensured that those paths are owned by www-data.) This same command works perfectly fine to generate the output when run using my regular username myrealusername, provided that the input and output are owned by that user name.

When I try running the above command using PHP's exec function, outputfilename.txt is created as an empty file owned by www-data with permissions 0644 (rw-r--r--). This is true whether Whisper is specified in the command as just whisper or as the full path /home/myrealusername/.local/bin/whisper.

When I try running the above command using the command prompt (ensuring first that the output file is deleted) as the web server user with sudo -u www-data whisper 'mediafilename.mp3' --model tiny --language English > 'outputfilename.txt', I get outputfilename.txt: Permission denied, and the output file is not created. This is true whether I specify Whisper as just whisper or as /home/myrealusername/.local/bin/whisper.

However, if the output file is created and its permissions are manually changed to rw-r--rw- using sudo chmod 0646 outputfilename.txt, so that the output file is writeable by all, then, in the command line, sudo -u www-data whisper 'mediafilename.mp3' --model tiny --language English > 'outputfilename.txt' gives the error whisper: command not found and sudo -u www-data /home/myrealusername/.local/bin/whisper 'mediafilename.mp3' --model tiny --language English > 'outputfilename.txt' gives the error

Traceback (most recent call last):
  File "/home/myrealusername/.local/bin/whisper", line 5, in <module>
    from whisper.transcribe import cli
ModuleNotFoundError: No module named 'whisper'

So, I think I might be having two separate problems. First, although PHP is able to create the output text file outputfilename.txt, it doesn't have the proper permissions to write to it via the whisper command. (It's strange to me that www-data can't even create the output file from the command line, whereas PHP somehow can create an (empty) output file, but I'm not sure what to make of that.) Second, I think PHP (i.e., the www-data user) isn't able to find or run the whisper command.

Please, if you have any thoughts or solutions, I would be much obliged.

EDIT: I found this with an answer by mz3 suggesting that www-data cannot read/write/execute anything outside the directories set up in the Apache configuration files. How can I modify my .conf file so that www-data can execute whisper, without letting outside traffic into those parts of my filesystem? Would something like the following work?

  <Directory /home/myrealusername/.local/bin>
    Options ExecCGI
    AllowOverride None
    Require all granted
    <Files "whisper">
      Require all granted
      SetHandler cgi-script
    </Files>
  </Directory>

Solution

  • I just ran into the same issue, spent ours on it, very frustrating. In the end, I even chmod'ed the directory to 777 and still got the same error.

    What finally did it for me was to include the file type and directory in the whisper command, with the --output_format and --output_dir options. So, to be clear,

    exec("whisper /dirname/filename.mp3"); 
    

    ... gave me the permission denied error, but

    exec("whisper /dirname/filename.mp3 --output_format srt --output_dir /dirname");
    

    ... worked without a glitch, no idea why.