P粉3620719922023-08-24 12:18:48
Add to (very good) existing answer
open_basedir
may stump you as it can be specified in the web server configuration. While this is easily solved if you run your own dedicated server, there are shared hosting packages (like Plesk, cPanel, etc.) that allow configuration directives on a per-domain basis. Since the software builds the configuration file (i.e. httpd.conf
), you cannot change this file directly as the hosting software will just overwrite it on restart.
With Plesk, they provide a location to override the provided httpd.conf
(called vhost.conf
). Only server administrators can write to this file. Apache's configuration looks like this
<Directory /var/www/vhosts/domain.com> <IfModule mod_php5.c> php_admin_flag engine on php_admin_flag safe_mode off php_admin_value open_basedir "/var/www/vhosts/domain.com:/tmp:/usr/share/pear:/local/PEAR" </IfModule> </Directory>
Ask your server administrator to consult the manuals for the hosting and web server software they use.
It is important to note that executing files via a web server is very different from command line or cron job execution. The biggest difference is that your web server has its own users and permissions. This user is heavily restricted for security reasons. For example, Apache is usually apache
, www-data
, or httpd
(depending on your server). A cron job or CLI execution has whatever permissions the user running it has (i.e. a PHP script run as root will execute with root permissions).
Many times people will solve permission issues by doing the following (Linux example)
chmod 777 /path/to/file
This is not a smart idea because the file or directory is now world-writable. If you own the server and are the only user, this isn't a big deal, but if you're in a shared hosting environment, you're granting access to everyone on the server.
What you need to do is identify the users who need access and grant access only to them. Once you know which users need access, you need to make sure
This user owns the file and may own the parent directory (especially the parent directory if you are writing to the file). In most shared hosting environments this won't be a problem as your user should own all files in the root directory. A Linux example is shown below
chown apache:apache /path/to/file
This user (and only this user) has access rights. In Linux, a good practice is chmod 600
(only the owner can read and write) or chmod 644
(the owner can write, but everyone can read)
You can read a broader discussion of Linux/Unix Permissions and Users here
P粉2686548732023-08-24 00:48:10
There are many reasons why you might encounter this error, so a good checklist of what to check first is helpful.
Assume we are troubleshooting the following line:
require "/path/to/file"
Or move whatever require*
or include*
calls into its own variable, echo it, copy it, and try to Access it via:
$path = "/path/to/file"; echo "Path : $path"; require "$path";
Then, in the terminal:
cat <file path pasted>
/users/tony/htdocs
Best Practices:
To make your script robust when moving content while still generating absolute paths at runtime, you have 2 options:
require __DIR__. "/relative/path/from/current/file"
. __DIR__
Magic constants Returns the directory of the current file. Define a SITE_ROOT
constant:
config.php
Write in
config.php
define('SITE_ROOT', __DIR__);
In every file that you want to reference the site root folder, include config.php
and then use the SITE_ROOT
constant anywhere: p>
require_once __DIR__."/../config.php"; ... require_once SITE_ROOT."/other/file.php";
These 2 practices also make your application more portable since it does not rely on ini settings such as include paths.
Another way to include files, which is neither relative nor purely absolute, is to rely on the include path. This is often the case with libraries or frameworks such as the Zend Framework.
Such an include would look like this:
include "Zend/Mail/Protocol/Imap.php"
In this case, you need to make sure that the folder where "Zend" is located is part of the include path.
You can check the include path using the following command:
echo get_include_path();
You can add folders to it using the following command:
set_include_path(get_include_path().":"."/path/to/new/folder");
To summarize, the user running the server process (Apache or PHP) may not have permission to read or write the file at all.
To check under which user the server is running, you can use posix_getpwuid< /一>:
$user = posix_getpwuid(posix_geteuid()); var_dump($user);
To find the permissions of a file, type the following command in the terminal:
ls -l <path/to/file>
and viewpermission notation
If none of the above methods work, the problem may be that some PHP settings prevent it from accessing the file.
Three settings may be relevant:
phpinfo()
or use ini_get("open_basedir")
ini_get("allow_url_include")
Check and use ini_set("allow_url_include", "1")
Set If none of the above methods can diagnose the problem, some of the following special situations may occur:
You might include a library, such as the Zend Framework, using a relative or absolute path. For example:
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
But you will still encounter the same type of errors.
This happens because the file you (successfully) include itself has an include statement from another file, and the second include statement assumes that you have added the path to the library to the include path.
For example, the Zend framework file mentioned earlier might contain the following:
include "Zend/Mail/Protocol/Exception.php"
Neither included through relative paths nor included through absolute paths. It is assumed that the Zend framework directory has been added to the include path.
In this case, the only practical solution is to add the directory to the include path.
If you are running security-enhanced Linux, this may be the cause of the problem, as access to the file from the server is denied.
To check if SELinux is enabled on your system, run the sestatus
command in the terminal. If this command does not exist, SELinux does not exist on your system. If it does exist, then it should tell you whether it is enforced.
To check if the SELinux policy is the cause of the problem, you can try turning it off temporarily. But be careful as this will completely disable protection. Don't do this on a production server.
setenforce 0
If you no longer have problems after turning off SELinux, then this is the root cause.
To resolve this issue, you must configure SELinux accordingly.
The following context types are required:
httpd_sys_content_t
For files you want the server to be able to readhttpd_sys_rw_content_t
For the file you want read and write access to httpd_log_t
For log fileshttpd_cache_t
Used for cache directoryFor example, to assign the httpd_sys_content_t
context type to your website root, run:
semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?" restorecon -Rv /path/to/root
If your files are located in your home directory, you will also need to turn on httpd_enable_homedirs
Boolean:
setsebool -P httpd_enable_homedirs 1
Regardless, there may be several reasons why SELinux denies access to a file, depending on your policy. So you need to investigate this. Here is a tutorial specifically for configuring SELinux for web servers.
If you are using Symfony and you encounter this error when uploading to the server, it is possible that the app's cache has not been reset because app/cache
has been uploaded, or that the cache has not been cleared.
You can test and fix this issue by running the following console command:
cache:clear
Apparently this error can also occur when calling zip->close()
when some of the files in the zip contain non-ASCII characters (e.g. "é") in their filenames.
A possible solution is to wrap the filename in utf8_decode()
before creating the target file.
Thanks Fran Cano for identifying this problem and proposing a solution< /p>