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